1/*
2 Copyright (c) 2000, 2016, Oracle and/or its affiliates.
3 Copyright (c) 2010, 2018, MariaDB
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17*/
18
19/* drop and alter of tables */
20
21#include "mariadb.h"
22#include "sql_priv.h"
23#include "unireg.h"
24#include "debug_sync.h"
25#include "sql_table.h"
26#include "sql_parse.h" // test_if_data_home_dir
27#include "sql_cache.h" // query_cache_*
28#include "sql_base.h" // lock_table_names
29#include "lock.h" // mysql_unlock_tables
30#include "strfunc.h" // find_type2, find_set
31#include "sql_truncate.h" // regenerate_locked_table
32#include "sql_partition.h" // generate_partition_syntax,
33 // partition_info
34 // NOT_A_PARTITION_ID
35#include "sql_db.h" // load_db_opt_by_name
36#include "sql_time.h" // make_truncated_value_warning
37#include "records.h" // init_read_record, end_read_record
38#include "filesort.h" // filesort_free_buffers
39#include "sql_select.h" // setup_order
40#include "sql_handler.h" // mysql_ha_rm_tables
41#include "discover.h" // readfrm
42#include "my_pthread.h" // pthread_mutex_t
43#include "log_event.h" // Query_log_event
44#include "sql_statistics.h"
45#include <hash.h>
46#include <myisam.h>
47#include <my_dir.h>
48#include "create_options.h"
49#include "sp_head.h"
50#include "sp.h"
51#include "sql_trigger.h"
52#include "sql_parse.h"
53#include "sql_show.h"
54#include "transaction.h"
55#include "sql_audit.h"
56#include "sql_sequence.h"
57#include "tztime.h"
58
59
60#ifdef __WIN__
61#include <io.h>
62#endif
63
64const char *primary_key_name="PRIMARY";
65
66static int check_if_keyname_exists(const char *name,KEY *start, KEY *end);
67static char *make_unique_key_name(THD *thd, const char *field_name, KEY *start,
68 KEY *end);
69static void make_unique_constraint_name(THD *thd, LEX_CSTRING *name,
70 List<Virtual_column_info> *vcol,
71 uint *nr);
72static const
73char * make_unique_invisible_field_name(THD *thd, const char *field_name,
74 List<Create_field> *fields);
75
76static int copy_data_between_tables(THD *thd, TABLE *from,TABLE *to,
77 List<Create_field> &create, bool ignore,
78 uint order_num, ORDER *order,
79 ha_rows *copied,ha_rows *deleted,
80 Alter_info::enum_enable_or_disable keys_onoff,
81 Alter_table_ctx *alter_ctx);
82
83static int mysql_prepare_create_table(THD *, HA_CREATE_INFO *, Alter_info *,
84 uint *, handler *, KEY **, uint *, int);
85static uint blob_length_by_type(enum_field_types type);
86
87/**
88 @brief Helper function for explain_filename
89 @param thd Thread handle
90 @param to_p Explained name in system_charset_info
91 @param end_p End of the to_p buffer
92 @param name Name to be converted
93 @param name_len Length of the name, in bytes
94*/
95static char* add_identifier(THD* thd, char *to_p, const char * end_p,
96 const char* name, size_t name_len)
97{
98 uint res;
99 uint errors;
100 const char *conv_name, *conv_name_end;
101 char tmp_name[FN_REFLEN];
102 char conv_string[FN_REFLEN];
103 int quote;
104
105 DBUG_ENTER("add_identifier");
106 if (!name[name_len])
107 conv_name= name;
108 else
109 {
110 strnmov(tmp_name, name, name_len);
111 tmp_name[name_len]= 0;
112 conv_name= tmp_name;
113 }
114 res= strconvert(&my_charset_filename, conv_name, name_len,
115 system_charset_info,
116 conv_string, FN_REFLEN, &errors);
117 if (unlikely(!res || errors))
118 {
119 DBUG_PRINT("error", ("strconvert of '%s' failed with %u (errors: %u)", conv_name, res, errors));
120 conv_name= name;
121 conv_name_end= name + name_len;
122 }
123 else
124 {
125 DBUG_PRINT("info", ("conv '%s' -> '%s'", conv_name, conv_string));
126 conv_name= conv_string;
127 conv_name_end= conv_string + res;
128 }
129
130 quote= (likely(thd) ?
131 get_quote_char_for_identifier(thd, conv_name, res - 1) :
132 '`');
133
134 if (quote != EOF && (end_p - to_p > 2))
135 {
136 *(to_p++)= (char) quote;
137 while (*conv_name && (end_p - to_p - 1) > 0)
138 {
139 int length= my_charlen(system_charset_info, conv_name, conv_name_end);
140 if (length <= 0)
141 length= 1;
142 if (length == 1 && *conv_name == (char) quote)
143 {
144 if ((end_p - to_p) < 3)
145 break;
146 *(to_p++)= (char) quote;
147 *(to_p++)= *(conv_name++);
148 }
149 else if (((long) length) < (end_p - to_p))
150 {
151 to_p= strnmov(to_p, conv_name, length);
152 conv_name+= length;
153 }
154 else
155 break; /* string already filled */
156 }
157 if (end_p > to_p) {
158 *(to_p++)= (char) quote;
159 if (end_p > to_p)
160 *to_p= 0; /* terminate by NUL, but do not include it in the count */
161 }
162 }
163 else
164 to_p= strnmov(to_p, conv_name, end_p - to_p);
165 DBUG_RETURN(to_p);
166}
167
168
169/**
170 @brief Explain a path name by split it to database, table etc.
171
172 @details Break down the path name to its logic parts
173 (database, table, partition, subpartition).
174 filename_to_tablename cannot be used on partitions, due to the #P# part.
175 There can be up to 6 '#', #P# for partition, #SP# for subpartition
176 and #TMP# or #REN# for temporary or renamed partitions.
177 This should be used when something should be presented to a user in a
178 diagnostic, error etc. when it would be useful to know what a particular
179 file [and directory] means. Such as SHOW ENGINE STATUS, error messages etc.
180
181 Examples:
182
183 t1#P#p1 table t1 partition p1
184 t1#P#p1#SP#sp1 table t1 partition p1 subpartition sp1
185 t1#P#p1#SP#sp1#TMP# table t1 partition p1 subpartition sp1 temporary
186 t1#P#p1#SP#sp1#REN# table t1 partition p1 subpartition sp1 renamed
187
188 @param thd Thread handle
189 @param from Path name in my_charset_filename
190 Null terminated in my_charset_filename, normalized
191 to use '/' as directory separation character.
192 @param to Explained name in system_charset_info
193 @param to_length Size of to buffer
194 @param explain_mode Requested output format.
195 EXPLAIN_ALL_VERBOSE ->
196 [Database `db`, ]Table `tbl`[,[ Temporary| Renamed]
197 Partition `p` [, Subpartition `sp`]]
198 EXPLAIN_PARTITIONS_VERBOSE -> `db`.`tbl`
199 [[ Temporary| Renamed] Partition `p`
200 [, Subpartition `sp`]]
201 EXPLAIN_PARTITIONS_AS_COMMENT -> `db`.`tbl` |*
202 [,[ Temporary| Renamed] Partition `p`
203 [, Subpartition `sp`]] *|
204 (| is really a /, and it is all in one line)
205
206 @retval Length of returned string
207*/
208
209uint explain_filename(THD* thd,
210 const char *from,
211 char *to,
212 uint to_length,
213 enum_explain_filename_mode explain_mode)
214{
215 char *to_p= to;
216 char *end_p= to_p + to_length;
217 const char *db_name= NULL;
218 size_t db_name_len= 0;
219 const char *table_name;
220 size_t table_name_len= 0;
221 const char *part_name= NULL;
222 size_t part_name_len= 0;
223 const char *subpart_name= NULL;
224 size_t subpart_name_len= 0;
225 uint part_type= NORMAL_PART_NAME;
226
227 const char *tmp_p;
228 DBUG_ENTER("explain_filename");
229 DBUG_PRINT("enter", ("from '%s'", from));
230 tmp_p= from;
231 table_name= from;
232 /*
233 If '/' then take last directory part as database.
234 '/' is the directory separator, not FN_LIB_CHAR
235 */
236 while ((tmp_p= strchr(tmp_p, '/')))
237 {
238 db_name= table_name;
239 /* calculate the length */
240 db_name_len= (int)(tmp_p - db_name);
241 tmp_p++;
242 table_name= tmp_p;
243 }
244 tmp_p= table_name;
245 /* Look if there are partition tokens in the table name. */
246 while ((tmp_p= strchr(tmp_p, '#')))
247 {
248 tmp_p++;
249 switch (tmp_p[0]) {
250 case 'P':
251 case 'p':
252 if (tmp_p[1] == '#')
253 {
254 part_name= tmp_p + 2;
255 tmp_p+= 2;
256 }
257 break;
258 case 'S':
259 case 's':
260 if ((tmp_p[1] == 'P' || tmp_p[1] == 'p') && tmp_p[2] == '#')
261 {
262 part_name_len= (int)(tmp_p - part_name - 1);
263 subpart_name= tmp_p + 3;
264 tmp_p+= 3;
265 }
266 break;
267 case 'T':
268 case 't':
269 if ((tmp_p[1] == 'M' || tmp_p[1] == 'm') &&
270 (tmp_p[2] == 'P' || tmp_p[2] == 'p') &&
271 tmp_p[3] == '#' && !tmp_p[4])
272 {
273 part_type= TEMP_PART_NAME;
274 tmp_p+= 4;
275 }
276 break;
277 case 'R':
278 case 'r':
279 if ((tmp_p[1] == 'E' || tmp_p[1] == 'e') &&
280 (tmp_p[2] == 'N' || tmp_p[2] == 'n') &&
281 tmp_p[3] == '#' && !tmp_p[4])
282 {
283 part_type= RENAMED_PART_NAME;
284 tmp_p+= 4;
285 }
286 break;
287 default:
288 /* Not partition name part. */
289 ;
290 }
291 }
292 if (part_name)
293 {
294 table_name_len= (int)(part_name - table_name - 3);
295 if (subpart_name)
296 subpart_name_len= strlen(subpart_name);
297 else
298 part_name_len= strlen(part_name);
299 if (part_type != NORMAL_PART_NAME)
300 {
301 if (subpart_name)
302 subpart_name_len-= 5;
303 else
304 part_name_len-= 5;
305 }
306 }
307 else
308 table_name_len= strlen(table_name);
309 if (db_name)
310 {
311 if (explain_mode == EXPLAIN_ALL_VERBOSE)
312 {
313 to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_DATABASE_NAME),
314 end_p - to_p);
315 *(to_p++)= ' ';
316 to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len);
317 to_p= strnmov(to_p, ", ", end_p - to_p);
318 }
319 else
320 {
321 to_p= add_identifier(thd, to_p, end_p, db_name, db_name_len);
322 to_p= strnmov(to_p, ".", end_p - to_p);
323 }
324 }
325 if (explain_mode == EXPLAIN_ALL_VERBOSE)
326 {
327 to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_TABLE_NAME), end_p - to_p);
328 *(to_p++)= ' ';
329 to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len);
330 }
331 else
332 to_p= add_identifier(thd, to_p, end_p, table_name, table_name_len);
333 if (part_name)
334 {
335 if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT)
336 to_p= strnmov(to_p, " /* ", end_p - to_p);
337 else if (explain_mode == EXPLAIN_PARTITIONS_VERBOSE)
338 to_p= strnmov(to_p, " ", end_p - to_p);
339 else
340 to_p= strnmov(to_p, ", ", end_p - to_p);
341 if (part_type != NORMAL_PART_NAME)
342 {
343 if (part_type == TEMP_PART_NAME)
344 to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_TEMPORARY_NAME),
345 end_p - to_p);
346 else
347 to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_RENAMED_NAME),
348 end_p - to_p);
349 to_p= strnmov(to_p, " ", end_p - to_p);
350 }
351 to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_PARTITION_NAME),
352 end_p - to_p);
353 *(to_p++)= ' ';
354 to_p= add_identifier(thd, to_p, end_p, part_name, part_name_len);
355 if (subpart_name)
356 {
357 to_p= strnmov(to_p, ", ", end_p - to_p);
358 to_p= strnmov(to_p, ER_THD_OR_DEFAULT(thd, ER_SUBPARTITION_NAME),
359 end_p - to_p);
360 *(to_p++)= ' ';
361 to_p= add_identifier(thd, to_p, end_p, subpart_name, subpart_name_len);
362 }
363 if (explain_mode == EXPLAIN_PARTITIONS_AS_COMMENT)
364 to_p= strnmov(to_p, " */", end_p - to_p);
365 }
366 DBUG_PRINT("exit", ("to '%s'", to));
367 DBUG_RETURN((uint)(to_p - to));
368}
369
370
371/*
372 Translate a file name to a table name (WL #1324).
373
374 SYNOPSIS
375 filename_to_tablename()
376 from The file name in my_charset_filename.
377 to OUT The table name in system_charset_info.
378 to_length The size of the table name buffer.
379
380 RETURN
381 Table name length.
382*/
383
384uint filename_to_tablename(const char *from, char *to, size_t to_length,
385 bool stay_quiet)
386{
387 uint errors;
388 size_t res;
389 DBUG_ENTER("filename_to_tablename");
390 DBUG_PRINT("enter", ("from '%s'", from));
391
392 res= strconvert(&my_charset_filename, from, FN_REFLEN,
393 system_charset_info, to, to_length, &errors);
394 if (unlikely(errors)) // Old 5.0 name
395 {
396 res= (strxnmov(to, to_length, MYSQL50_TABLE_NAME_PREFIX, from, NullS) -
397 to);
398 if (!stay_quiet)
399 sql_print_error("Invalid (old?) table or database name '%s'", from);
400 }
401
402 DBUG_PRINT("exit", ("to '%s'", to));
403 DBUG_RETURN((uint)res);
404}
405
406
407/**
408 Check if given string begins with "#mysql50#" prefix
409
410 @param name string to check cut
411
412 @retval
413 FALSE no prefix found
414 @retval
415 TRUE prefix found
416*/
417
418bool check_mysql50_prefix(const char *name)
419{
420 return (name[0] == '#' &&
421 !strncmp(name, MYSQL50_TABLE_NAME_PREFIX,
422 MYSQL50_TABLE_NAME_PREFIX_LENGTH));
423}
424
425
426/**
427 Check if given string begins with "#mysql50#" prefix, cut it if so.
428
429 @param from string to check and cut
430 @param to[out] buffer for result string
431 @param to_length its size
432
433 @retval
434 0 no prefix found
435 @retval
436 non-0 result string length
437*/
438
439uint check_n_cut_mysql50_prefix(const char *from, char *to, size_t to_length)
440{
441 if (check_mysql50_prefix(from))
442 return (uint) (strmake(to, from + MYSQL50_TABLE_NAME_PREFIX_LENGTH,
443 to_length - 1) - to);
444 return 0;
445}
446
447
448static bool check_if_frm_exists(char *path, const char *db, const char *table)
449{
450 fn_format(path, table, db, reg_ext, MYF(0));
451 return !access(path, F_OK);
452}
453
454
455/*
456 Translate a table name to a file name (WL #1324).
457
458 SYNOPSIS
459 tablename_to_filename()
460 from The table name in system_charset_info.
461 to OUT The file name in my_charset_filename.
462 to_length The size of the file name buffer.
463
464 RETURN
465 File name length.
466*/
467
468uint tablename_to_filename(const char *from, char *to, size_t to_length)
469{
470 uint errors, length;
471 DBUG_ENTER("tablename_to_filename");
472 DBUG_PRINT("enter", ("from '%s'", from));
473
474 if ((length= check_n_cut_mysql50_prefix(from, to, to_length)))
475 {
476 /*
477 Check if the name supplied is a valid mysql 5.0 name and
478 make the name a zero length string if it's not.
479 Note that just returning zero length is not enough :
480 a lot of places don't check the return value and expect
481 a zero terminated string.
482 */
483 if (check_table_name(to, length, TRUE))
484 {
485 to[0]= 0;
486 length= 0;
487 }
488 DBUG_RETURN(length);
489 }
490 length= strconvert(system_charset_info, from, FN_REFLEN,
491 &my_charset_filename, to, to_length, &errors);
492 if (check_if_legal_tablename(to) &&
493 length + 4 < to_length)
494 {
495 memcpy(to + length, "@@@", 4);
496 length+= 3;
497 }
498 DBUG_PRINT("exit", ("to '%s'", to));
499 DBUG_RETURN(length);
500}
501
502
503/*
504 Creates path to a file: mysql_data_dir/db/table.ext
505
506 SYNOPSIS
507 build_table_filename()
508 buff Where to write result in my_charset_filename.
509 This may be the same as table_name.
510 bufflen buff size
511 db Database name in system_charset_info.
512 table_name Table name in system_charset_info.
513 ext File extension.
514 flags FN_FROM_IS_TMP or FN_TO_IS_TMP or FN_IS_TMP
515 table_name is temporary, do not change.
516
517 NOTES
518
519 Uses database and table name, and extension to create
520 a file name in mysql_data_dir. Database and table
521 names are converted from system_charset_info into "fscs".
522 Unless flags indicate a temporary table name.
523 'db' is always converted.
524 'ext' is not converted.
525
526 The conversion suppression is required for ALTER TABLE. This
527 statement creates intermediate tables. These are regular
528 (non-temporary) tables with a temporary name. Their path names must
529 be derivable from the table name. So we cannot use
530 build_tmptable_filename() for them.
531
532 RETURN
533 path length
534*/
535
536uint build_table_filename(char *buff, size_t bufflen, const char *db,
537 const char *table_name, const char *ext, uint flags)
538{
539 char dbbuff[FN_REFLEN];
540 char tbbuff[FN_REFLEN];
541 DBUG_ENTER("build_table_filename");
542 DBUG_PRINT("enter", ("db: '%s' table_name: '%s' ext: '%s' flags: %x",
543 db, table_name, ext, flags));
544
545 (void) tablename_to_filename(db, dbbuff, sizeof(dbbuff));
546
547 /* Check if this is a temporary table name. Allow it if a corresponding .frm file exists */
548 if (is_prefix(table_name, tmp_file_prefix) && strlen(table_name) < NAME_CHAR_LEN &&
549 check_if_frm_exists(tbbuff, dbbuff, table_name))
550 flags|= FN_IS_TMP;
551
552 if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
553 strmake(tbbuff, table_name, sizeof(tbbuff)-1);
554 else
555 (void) tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
556
557 char *end = buff + bufflen;
558 /* Don't add FN_ROOTDIR if mysql_data_home already includes it */
559 char *pos = strnmov(buff, mysql_data_home, bufflen);
560 size_t rootdir_len= strlen(FN_ROOTDIR);
561 if (pos - rootdir_len >= buff &&
562 memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0)
563 pos= strnmov(pos, FN_ROOTDIR, end - pos);
564 pos= strxnmov(pos, end - pos, dbbuff, FN_ROOTDIR, NullS);
565#ifdef USE_SYMDIR
566 if (!(flags & SKIP_SYMDIR_ACCESS))
567 {
568 unpack_dirname(buff, buff);
569 pos= strend(buff);
570 }
571#endif
572 pos= strxnmov(pos, end - pos, tbbuff, ext, NullS);
573
574 DBUG_PRINT("exit", ("buff: '%s'", buff));
575 DBUG_RETURN((uint)(pos - buff));
576}
577
578
579/**
580 Create path to a temporary table mysql_tmpdir/#sql1234_12_1
581 (i.e. to its .FRM file but without an extension).
582
583 @param thd The thread handle.
584 @param buff Where to write result in my_charset_filename.
585 @param bufflen buff size
586
587 @note
588 Uses current_pid, thread_id, and tmp_table counter to create
589 a file name in mysql_tmpdir.
590
591 @return Path length.
592*/
593
594uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
595{
596 DBUG_ENTER("build_tmptable_filename");
597
598 char *p= strnmov(buff, mysql_tmpdir, bufflen);
599 my_snprintf(p, bufflen - (p - buff), "/%s%lx_%llx_%x",
600 tmp_file_prefix, current_pid,
601 thd->thread_id, thd->tmp_table++);
602
603 if (lower_case_table_names)
604 {
605 /* Convert all except tmpdir to lower case */
606 my_casedn_str(files_charset_info, p);
607 }
608
609 size_t length= unpack_filename(buff, buff);
610 DBUG_PRINT("exit", ("buff: '%s'", buff));
611 DBUG_RETURN((uint)length);
612}
613
614/*
615--------------------------------------------------------------------------
616
617 MODULE: DDL log
618 -----------------
619
620 This module is used to ensure that we can recover from crashes that occur
621 in the middle of a meta-data operation in MySQL. E.g. DROP TABLE t1, t2;
622 We need to ensure that both t1 and t2 are dropped and not only t1 and
623 also that each table drop is entirely done and not "half-baked".
624
625 To support this we create log entries for each meta-data statement in the
626 ddl log while we are executing. These entries are dropped when the
627 operation is completed.
628
629 At recovery those entries that were not completed will be executed.
630
631 There is only one ddl log in the system and it is protected by a mutex
632 and there is a global struct that contains information about its current
633 state.
634
635 History:
636 First version written in 2006 by Mikael Ronstrom
637--------------------------------------------------------------------------
638*/
639
640struct st_global_ddl_log
641{
642 /*
643 We need to adjust buffer size to be able to handle downgrades/upgrades
644 where IO_SIZE has changed. We'll set the buffer size such that we can
645 handle that the buffer size was upto 4 times bigger in the version
646 that wrote the DDL log.
647 */
648 char file_entry_buf[4*IO_SIZE];
649 char file_name_str[FN_REFLEN];
650 char *file_name;
651 DDL_LOG_MEMORY_ENTRY *first_free;
652 DDL_LOG_MEMORY_ENTRY *first_used;
653 uint num_entries;
654 File file_id;
655 uint name_len;
656 uint io_size;
657 bool inited;
658 bool do_release;
659 bool recovery_phase;
660 st_global_ddl_log() : inited(false), do_release(false) {}
661};
662
663st_global_ddl_log global_ddl_log;
664
665mysql_mutex_t LOCK_gdl;
666
667#define DDL_LOG_ENTRY_TYPE_POS 0
668#define DDL_LOG_ACTION_TYPE_POS 1
669#define DDL_LOG_PHASE_POS 2
670#define DDL_LOG_NEXT_ENTRY_POS 4
671#define DDL_LOG_NAME_POS 8
672
673#define DDL_LOG_NUM_ENTRY_POS 0
674#define DDL_LOG_NAME_LEN_POS 4
675#define DDL_LOG_IO_SIZE_POS 8
676
677/**
678 Read one entry from ddl log file.
679
680 @param entry_no Entry number to read
681
682 @return Operation status
683 @retval true Error
684 @retval false Success
685*/
686
687static bool read_ddl_log_file_entry(uint entry_no)
688{
689 bool error= FALSE;
690 File file_id= global_ddl_log.file_id;
691 uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf;
692 size_t io_size= global_ddl_log.io_size;
693 DBUG_ENTER("read_ddl_log_file_entry");
694
695 mysql_mutex_assert_owner(&LOCK_gdl);
696 if (mysql_file_pread(file_id, file_entry_buf, io_size, io_size * entry_no,
697 MYF(MY_WME)) != io_size)
698 error= TRUE;
699 DBUG_RETURN(error);
700}
701
702
703/**
704 Write one entry to ddl log file.
705
706 @param entry_no Entry number to write
707
708 @return Operation status
709 @retval true Error
710 @retval false Success
711*/
712
713static bool write_ddl_log_file_entry(uint entry_no)
714{
715 bool error= FALSE;
716 File file_id= global_ddl_log.file_id;
717 uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf;
718 DBUG_ENTER("write_ddl_log_file_entry");
719
720 mysql_mutex_assert_owner(&LOCK_gdl);
721 if (mysql_file_pwrite(file_id, file_entry_buf,
722 IO_SIZE, IO_SIZE * entry_no, MYF(MY_WME)) != IO_SIZE)
723 error= TRUE;
724 DBUG_RETURN(error);
725}
726
727
728/**
729 Sync the ddl log file.
730
731 @return Operation status
732 @retval FALSE Success
733 @retval TRUE Error
734*/
735
736
737static bool sync_ddl_log_file()
738{
739 DBUG_ENTER("sync_ddl_log_file");
740 DBUG_RETURN(mysql_file_sync(global_ddl_log.file_id, MYF(MY_WME)));
741}
742
743
744/**
745 Write ddl log header.
746
747 @return Operation status
748 @retval TRUE Error
749 @retval FALSE Success
750*/
751
752static bool write_ddl_log_header()
753{
754 uint16 const_var;
755 DBUG_ENTER("write_ddl_log_header");
756
757 int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NUM_ENTRY_POS],
758 global_ddl_log.num_entries);
759 const_var= FN_REFLEN;
760 int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_LEN_POS],
761 (ulong) const_var);
762 const_var= IO_SIZE;
763 int4store(&global_ddl_log.file_entry_buf[DDL_LOG_IO_SIZE_POS],
764 (ulong) const_var);
765 if (write_ddl_log_file_entry(0UL))
766 {
767 sql_print_error("Error writing ddl log header");
768 DBUG_RETURN(TRUE);
769 }
770 DBUG_RETURN(sync_ddl_log_file());
771}
772
773
774/**
775 Create ddl log file name.
776 @param file_name Filename setup
777*/
778
779static inline void create_ddl_log_file_name(char *file_name)
780{
781 strxmov(file_name, mysql_data_home, "/", "ddl_log.log", NullS);
782}
783
784
785/**
786 Read header of ddl log file.
787
788 When we read the ddl log header we get information about maximum sizes
789 of names in the ddl log and we also get information about the number
790 of entries in the ddl log.
791
792 @return Last entry in ddl log (0 if no entries)
793*/
794
795static uint read_ddl_log_header()
796{
797 uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf;
798 char file_name[FN_REFLEN];
799 uint entry_no;
800 bool successful_open= FALSE;
801 DBUG_ENTER("read_ddl_log_header");
802
803 mysql_mutex_init(key_LOCK_gdl, &LOCK_gdl, MY_MUTEX_INIT_SLOW);
804 mysql_mutex_lock(&LOCK_gdl);
805 create_ddl_log_file_name(file_name);
806 if ((global_ddl_log.file_id= mysql_file_open(key_file_global_ddl_log,
807 file_name,
808 O_RDWR | O_BINARY, MYF(0))) >= 0)
809 {
810 if (read_ddl_log_file_entry(0UL))
811 {
812 /* Write message into error log */
813 sql_print_error("Failed to read ddl log file in recovery");
814 }
815 else
816 successful_open= TRUE;
817 }
818 if (successful_open)
819 {
820 entry_no= uint4korr(&file_entry_buf[DDL_LOG_NUM_ENTRY_POS]);
821 global_ddl_log.name_len= uint4korr(&file_entry_buf[DDL_LOG_NAME_LEN_POS]);
822 global_ddl_log.io_size= uint4korr(&file_entry_buf[DDL_LOG_IO_SIZE_POS]);
823 DBUG_ASSERT(global_ddl_log.io_size <=
824 sizeof(global_ddl_log.file_entry_buf));
825 }
826 else
827 {
828 entry_no= 0;
829 }
830 global_ddl_log.first_free= NULL;
831 global_ddl_log.first_used= NULL;
832 global_ddl_log.num_entries= 0;
833 global_ddl_log.do_release= true;
834 mysql_mutex_unlock(&LOCK_gdl);
835 DBUG_RETURN(entry_no);
836}
837
838
839/**
840 Convert from ddl_log_entry struct to file_entry_buf binary blob.
841
842 @param ddl_log_entry filled in ddl_log_entry struct.
843*/
844
845static void set_global_from_ddl_log_entry(const DDL_LOG_ENTRY *ddl_log_entry)
846{
847 mysql_mutex_assert_owner(&LOCK_gdl);
848 global_ddl_log.file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]=
849 (char)DDL_LOG_ENTRY_CODE;
850 global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS]=
851 (char)ddl_log_entry->action_type;
852 global_ddl_log.file_entry_buf[DDL_LOG_PHASE_POS]= 0;
853 int4store(&global_ddl_log.file_entry_buf[DDL_LOG_NEXT_ENTRY_POS],
854 ddl_log_entry->next_entry);
855 DBUG_ASSERT(strlen(ddl_log_entry->name) < FN_REFLEN);
856 strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS],
857 ddl_log_entry->name, FN_REFLEN - 1);
858 if (ddl_log_entry->action_type == DDL_LOG_RENAME_ACTION ||
859 ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION ||
860 ddl_log_entry->action_type == DDL_LOG_EXCHANGE_ACTION)
861 {
862 DBUG_ASSERT(strlen(ddl_log_entry->from_name) < FN_REFLEN);
863 strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_REFLEN],
864 ddl_log_entry->from_name, FN_REFLEN - 1);
865 }
866 else
867 global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + FN_REFLEN]= 0;
868 DBUG_ASSERT(strlen(ddl_log_entry->handler_name) < FN_REFLEN);
869 strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + (2*FN_REFLEN)],
870 ddl_log_entry->handler_name, FN_REFLEN - 1);
871 if (ddl_log_entry->action_type == DDL_LOG_EXCHANGE_ACTION)
872 {
873 DBUG_ASSERT(strlen(ddl_log_entry->tmp_name) < FN_REFLEN);
874 strmake(&global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + (3*FN_REFLEN)],
875 ddl_log_entry->tmp_name, FN_REFLEN - 1);
876 }
877 else
878 global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS + (3*FN_REFLEN)]= 0;
879}
880
881
882/**
883 Convert from file_entry_buf binary blob to ddl_log_entry struct.
884
885 @param[out] ddl_log_entry struct to fill in.
886
887 @note Strings (names) are pointing to the global_ddl_log structure,
888 so LOCK_gdl needs to be hold until they are read or copied.
889*/
890
891static void set_ddl_log_entry_from_global(DDL_LOG_ENTRY *ddl_log_entry,
892 const uint read_entry)
893{
894 char *file_entry_buf= (char*) global_ddl_log.file_entry_buf;
895 uint inx;
896 uchar single_char;
897
898 mysql_mutex_assert_owner(&LOCK_gdl);
899 ddl_log_entry->entry_pos= read_entry;
900 single_char= file_entry_buf[DDL_LOG_ENTRY_TYPE_POS];
901 ddl_log_entry->entry_type= (enum ddl_log_entry_code)single_char;
902 single_char= file_entry_buf[DDL_LOG_ACTION_TYPE_POS];
903 ddl_log_entry->action_type= (enum ddl_log_action_code)single_char;
904 ddl_log_entry->phase= file_entry_buf[DDL_LOG_PHASE_POS];
905 ddl_log_entry->next_entry= uint4korr(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS]);
906 ddl_log_entry->name= &file_entry_buf[DDL_LOG_NAME_POS];
907 inx= DDL_LOG_NAME_POS + global_ddl_log.name_len;
908 ddl_log_entry->from_name= &file_entry_buf[inx];
909 inx+= global_ddl_log.name_len;
910 ddl_log_entry->handler_name= &file_entry_buf[inx];
911 if (ddl_log_entry->action_type == DDL_LOG_EXCHANGE_ACTION)
912 {
913 inx+= global_ddl_log.name_len;
914 ddl_log_entry->tmp_name= &file_entry_buf[inx];
915 }
916 else
917 ddl_log_entry->tmp_name= NULL;
918}
919
920
921/**
922 Read a ddl log entry.
923
924 Read a specified entry in the ddl log.
925
926 @param read_entry Number of entry to read
927 @param[out] entry_info Information from entry
928
929 @return Operation status
930 @retval TRUE Error
931 @retval FALSE Success
932*/
933
934static bool read_ddl_log_entry(uint read_entry, DDL_LOG_ENTRY *ddl_log_entry)
935{
936 DBUG_ENTER("read_ddl_log_entry");
937
938 if (read_ddl_log_file_entry(read_entry))
939 {
940 DBUG_RETURN(TRUE);
941 }
942 set_ddl_log_entry_from_global(ddl_log_entry, read_entry);
943 DBUG_RETURN(FALSE);
944}
945
946
947/**
948 Initialise ddl log.
949
950 Write the header of the ddl log file and length of names. Also set
951 number of entries to zero.
952
953 @return Operation status
954 @retval TRUE Error
955 @retval FALSE Success
956*/
957
958static bool init_ddl_log()
959{
960 char file_name[FN_REFLEN];
961 DBUG_ENTER("init_ddl_log");
962
963 if (global_ddl_log.inited)
964 goto end;
965
966 global_ddl_log.io_size= IO_SIZE;
967 global_ddl_log.name_len= FN_REFLEN;
968 create_ddl_log_file_name(file_name);
969 if ((global_ddl_log.file_id= mysql_file_create(key_file_global_ddl_log,
970 file_name, CREATE_MODE,
971 O_RDWR | O_TRUNC | O_BINARY,
972 MYF(MY_WME))) < 0)
973 {
974 /* Couldn't create ddl log file, this is serious error */
975 sql_print_error("Failed to open ddl log file");
976 DBUG_RETURN(TRUE);
977 }
978 global_ddl_log.inited= TRUE;
979 if (write_ddl_log_header())
980 {
981 (void) mysql_file_close(global_ddl_log.file_id, MYF(MY_WME));
982 global_ddl_log.inited= FALSE;
983 DBUG_RETURN(TRUE);
984 }
985
986end:
987 DBUG_RETURN(FALSE);
988}
989
990
991/**
992 Sync ddl log file.
993
994 @return Operation status
995 @retval TRUE Error
996 @retval FALSE Success
997*/
998
999static bool sync_ddl_log_no_lock()
1000{
1001 DBUG_ENTER("sync_ddl_log_no_lock");
1002
1003 mysql_mutex_assert_owner(&LOCK_gdl);
1004 if ((!global_ddl_log.recovery_phase) &&
1005 init_ddl_log())
1006 {
1007 DBUG_RETURN(TRUE);
1008 }
1009 DBUG_RETURN(sync_ddl_log_file());
1010}
1011
1012
1013/**
1014 @brief Deactivate an individual entry.
1015
1016 @details For complex rename operations we need to deactivate individual
1017 entries.
1018
1019 During replace operations where we start with an existing table called
1020 t1 and a replacement table called t1#temp or something else and where
1021 we want to delete t1 and rename t1#temp to t1 this is not possible to
1022 do in a safe manner unless the ddl log is informed of the phases in
1023 the change.
1024
1025 Delete actions are 1-phase actions that can be ignored immediately after
1026 being executed.
1027 Rename actions from x to y is also a 1-phase action since there is no
1028 interaction with any other handlers named x and y.
1029 Replace action where drop y and x -> y happens needs to be a two-phase
1030 action. Thus the first phase will drop y and the second phase will
1031 rename x -> y.
1032
1033 @param entry_no Entry position of record to change
1034
1035 @return Operation status
1036 @retval TRUE Error
1037 @retval FALSE Success
1038*/
1039
1040static bool deactivate_ddl_log_entry_no_lock(uint entry_no)
1041{
1042 uchar *file_entry_buf= (uchar*)global_ddl_log.file_entry_buf;
1043 DBUG_ENTER("deactivate_ddl_log_entry_no_lock");
1044
1045 mysql_mutex_assert_owner(&LOCK_gdl);
1046 if (!read_ddl_log_file_entry(entry_no))
1047 {
1048 if (file_entry_buf[DDL_LOG_ENTRY_TYPE_POS] == DDL_LOG_ENTRY_CODE)
1049 {
1050 /*
1051 Log entry, if complete mark it done (IGNORE).
1052 Otherwise increase the phase by one.
1053 */
1054 if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_DELETE_ACTION ||
1055 file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_RENAME_ACTION ||
1056 (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION &&
1057 file_entry_buf[DDL_LOG_PHASE_POS] == 1) ||
1058 (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_EXCHANGE_ACTION &&
1059 file_entry_buf[DDL_LOG_PHASE_POS] >= EXCH_PHASE_TEMP_TO_FROM))
1060 file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= DDL_IGNORE_LOG_ENTRY_CODE;
1061 else if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_REPLACE_ACTION)
1062 {
1063 DBUG_ASSERT(file_entry_buf[DDL_LOG_PHASE_POS] == 0);
1064 file_entry_buf[DDL_LOG_PHASE_POS]= 1;
1065 }
1066 else if (file_entry_buf[DDL_LOG_ACTION_TYPE_POS] == DDL_LOG_EXCHANGE_ACTION)
1067 {
1068 DBUG_ASSERT(file_entry_buf[DDL_LOG_PHASE_POS] <=
1069 EXCH_PHASE_FROM_TO_NAME);
1070 file_entry_buf[DDL_LOG_PHASE_POS]++;
1071 }
1072 else
1073 {
1074 DBUG_ASSERT(0);
1075 }
1076 if (write_ddl_log_file_entry(entry_no))
1077 {
1078 sql_print_error("Error in deactivating log entry. Position = %u",
1079 entry_no);
1080 DBUG_RETURN(TRUE);
1081 }
1082 }
1083 }
1084 else
1085 {
1086 sql_print_error("Failed in reading entry before deactivating it");
1087 DBUG_RETURN(TRUE);
1088 }
1089 DBUG_RETURN(FALSE);
1090}
1091
1092
1093/**
1094 Execute one action in a ddl log entry
1095
1096 @param ddl_log_entry Information in action entry to execute
1097
1098 @return Operation status
1099 @retval TRUE Error
1100 @retval FALSE Success
1101*/
1102
1103static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry)
1104{
1105 bool frm_action= FALSE;
1106 LEX_CSTRING handler_name;
1107 handler *file= NULL;
1108 MEM_ROOT mem_root;
1109 int error= TRUE;
1110 char to_path[FN_REFLEN];
1111 char from_path[FN_REFLEN];
1112#ifdef WITH_PARTITION_STORAGE_ENGINE
1113 char *par_ext= (char*)".par";
1114#endif
1115 handlerton *hton;
1116 DBUG_ENTER("execute_ddl_log_action");
1117
1118 mysql_mutex_assert_owner(&LOCK_gdl);
1119 if (ddl_log_entry->entry_type == DDL_IGNORE_LOG_ENTRY_CODE)
1120 {
1121 DBUG_RETURN(FALSE);
1122 }
1123 DBUG_PRINT("ddl_log",
1124 ("execute type %c next %u name '%s' from_name '%s' handler '%s'"
1125 " tmp_name '%s'",
1126 ddl_log_entry->action_type,
1127 ddl_log_entry->next_entry,
1128 ddl_log_entry->name,
1129 ddl_log_entry->from_name,
1130 ddl_log_entry->handler_name,
1131 ddl_log_entry->tmp_name));
1132 handler_name.str= (char*)ddl_log_entry->handler_name;
1133 handler_name.length= strlen(ddl_log_entry->handler_name);
1134 init_sql_alloc(&mem_root, "execute_ddl_log_action", TABLE_ALLOC_BLOCK_SIZE,
1135 0, MYF(MY_THREAD_SPECIFIC));
1136 if (!strcmp(ddl_log_entry->handler_name, reg_ext))
1137 frm_action= TRUE;
1138 else
1139 {
1140 plugin_ref plugin= ha_resolve_by_name(thd, &handler_name, false);
1141 if (!plugin)
1142 {
1143 my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), ddl_log_entry->handler_name);
1144 goto error;
1145 }
1146 hton= plugin_data(plugin, handlerton*);
1147 file= get_new_handler((TABLE_SHARE*)0, &mem_root, hton);
1148 if (unlikely(!file))
1149 goto error;
1150 }
1151 switch (ddl_log_entry->action_type)
1152 {
1153 case DDL_LOG_REPLACE_ACTION:
1154 case DDL_LOG_DELETE_ACTION:
1155 {
1156 if (ddl_log_entry->phase == 0)
1157 {
1158 if (frm_action)
1159 {
1160 strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
1161 if (unlikely((error= mysql_file_delete(key_file_frm, to_path,
1162 MYF(MY_WME)))))
1163 {
1164 if (my_errno != ENOENT)
1165 break;
1166 }
1167#ifdef WITH_PARTITION_STORAGE_ENGINE
1168 strxmov(to_path, ddl_log_entry->name, par_ext, NullS);
1169 (void) mysql_file_delete(key_file_partition, to_path, MYF(MY_WME));
1170#endif
1171 }
1172 else
1173 {
1174 if (unlikely((error= file->ha_delete_table(ddl_log_entry->name))))
1175 {
1176 if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE)
1177 break;
1178 }
1179 }
1180 if ((deactivate_ddl_log_entry_no_lock(ddl_log_entry->entry_pos)))
1181 break;
1182 (void) sync_ddl_log_no_lock();
1183 error= FALSE;
1184 if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION)
1185 break;
1186 }
1187 DBUG_ASSERT(ddl_log_entry->action_type == DDL_LOG_REPLACE_ACTION);
1188 /*
1189 Fall through and perform the rename action of the replace
1190 action. We have already indicated the success of the delete
1191 action in the log entry by stepping up the phase.
1192 */
1193 }
1194 /* fall through */
1195 case DDL_LOG_RENAME_ACTION:
1196 {
1197 error= TRUE;
1198 if (frm_action)
1199 {
1200 strxmov(to_path, ddl_log_entry->name, reg_ext, NullS);
1201 strxmov(from_path, ddl_log_entry->from_name, reg_ext, NullS);
1202 if (mysql_file_rename(key_file_frm, from_path, to_path, MYF(MY_WME)))
1203 break;
1204#ifdef WITH_PARTITION_STORAGE_ENGINE
1205 strxmov(to_path, ddl_log_entry->name, par_ext, NullS);
1206 strxmov(from_path, ddl_log_entry->from_name, par_ext, NullS);
1207 (void) mysql_file_rename(key_file_partition, from_path, to_path, MYF(MY_WME));
1208#endif
1209 }
1210 else
1211 {
1212 if (file->ha_rename_table(ddl_log_entry->from_name,
1213 ddl_log_entry->name))
1214 break;
1215 }
1216 if ((deactivate_ddl_log_entry_no_lock(ddl_log_entry->entry_pos)))
1217 break;
1218 (void) sync_ddl_log_no_lock();
1219 error= FALSE;
1220 break;
1221 }
1222 case DDL_LOG_EXCHANGE_ACTION:
1223 {
1224 /* We hold LOCK_gdl, so we can alter global_ddl_log.file_entry_buf */
1225 char *file_entry_buf= (char*)&global_ddl_log.file_entry_buf;
1226 /* not yet implemented for frm */
1227 DBUG_ASSERT(!frm_action);
1228 /*
1229 Using a case-switch here to revert all currently done phases,
1230 since it will fall through until the first phase is undone.
1231 */
1232 switch (ddl_log_entry->phase) {
1233 case EXCH_PHASE_TEMP_TO_FROM:
1234 /* tmp_name -> from_name possibly done */
1235 (void) file->ha_rename_table(ddl_log_entry->from_name,
1236 ddl_log_entry->tmp_name);
1237 /* decrease the phase and sync */
1238 file_entry_buf[DDL_LOG_PHASE_POS]--;
1239 if (write_ddl_log_file_entry(ddl_log_entry->entry_pos))
1240 break;
1241 if (sync_ddl_log_no_lock())
1242 break;
1243 /* fall through */
1244 case EXCH_PHASE_FROM_TO_NAME:
1245 /* from_name -> name possibly done */
1246 (void) file->ha_rename_table(ddl_log_entry->name,
1247 ddl_log_entry->from_name);
1248 /* decrease the phase and sync */
1249 file_entry_buf[DDL_LOG_PHASE_POS]--;
1250 if (write_ddl_log_file_entry(ddl_log_entry->entry_pos))
1251 break;
1252 if (sync_ddl_log_no_lock())
1253 break;
1254 /* fall through */
1255 case EXCH_PHASE_NAME_TO_TEMP:
1256 /* name -> tmp_name possibly done */
1257 (void) file->ha_rename_table(ddl_log_entry->tmp_name,
1258 ddl_log_entry->name);
1259 /* disable the entry and sync */
1260 file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= DDL_IGNORE_LOG_ENTRY_CODE;
1261 if (write_ddl_log_file_entry(ddl_log_entry->entry_pos))
1262 break;
1263 if (sync_ddl_log_no_lock())
1264 break;
1265 error= FALSE;
1266 break;
1267 default:
1268 DBUG_ASSERT(0);
1269 break;
1270 }
1271
1272 break;
1273 }
1274 default:
1275 DBUG_ASSERT(0);
1276 break;
1277 }
1278 delete file;
1279error:
1280 free_root(&mem_root, MYF(0));
1281 DBUG_RETURN(error);
1282}
1283
1284
1285/**
1286 Get a free entry in the ddl log
1287
1288 @param[out] active_entry A ddl log memory entry returned
1289
1290 @return Operation status
1291 @retval TRUE Error
1292 @retval FALSE Success
1293*/
1294
1295static bool get_free_ddl_log_entry(DDL_LOG_MEMORY_ENTRY **active_entry,
1296 bool *write_header)
1297{
1298 DDL_LOG_MEMORY_ENTRY *used_entry;
1299 DDL_LOG_MEMORY_ENTRY *first_used= global_ddl_log.first_used;
1300 DBUG_ENTER("get_free_ddl_log_entry");
1301
1302 if (global_ddl_log.first_free == NULL)
1303 {
1304 if (!(used_entry= (DDL_LOG_MEMORY_ENTRY*)my_malloc(
1305 sizeof(DDL_LOG_MEMORY_ENTRY), MYF(MY_WME))))
1306 {
1307 sql_print_error("Failed to allocate memory for ddl log free list");
1308 DBUG_RETURN(TRUE);
1309 }
1310 global_ddl_log.num_entries++;
1311 used_entry->entry_pos= global_ddl_log.num_entries;
1312 *write_header= TRUE;
1313 }
1314 else
1315 {
1316 used_entry= global_ddl_log.first_free;
1317 global_ddl_log.first_free= used_entry->next_log_entry;
1318 *write_header= FALSE;
1319 }
1320 /*
1321 Move from free list to used list
1322 */
1323 used_entry->next_log_entry= first_used;
1324 used_entry->prev_log_entry= NULL;
1325 used_entry->next_active_log_entry= NULL;
1326 global_ddl_log.first_used= used_entry;
1327 if (first_used)
1328 first_used->prev_log_entry= used_entry;
1329
1330 *active_entry= used_entry;
1331 DBUG_RETURN(FALSE);
1332}
1333
1334
1335/**
1336 Execute one entry in the ddl log.
1337
1338 Executing an entry means executing a linked list of actions.
1339
1340 @param first_entry Reference to first action in entry
1341
1342 @return Operation status
1343 @retval TRUE Error
1344 @retval FALSE Success
1345*/
1346
1347static bool execute_ddl_log_entry_no_lock(THD *thd, uint first_entry)
1348{
1349 DDL_LOG_ENTRY ddl_log_entry;
1350 uint read_entry= first_entry;
1351 DBUG_ENTER("execute_ddl_log_entry_no_lock");
1352
1353 mysql_mutex_assert_owner(&LOCK_gdl);
1354 do
1355 {
1356 if (read_ddl_log_entry(read_entry, &ddl_log_entry))
1357 {
1358 /* Write to error log and continue with next log entry */
1359 sql_print_error("Failed to read entry = %u from ddl log",
1360 read_entry);
1361 break;
1362 }
1363 DBUG_ASSERT(ddl_log_entry.entry_type == DDL_LOG_ENTRY_CODE ||
1364 ddl_log_entry.entry_type == DDL_IGNORE_LOG_ENTRY_CODE);
1365
1366 if (execute_ddl_log_action(thd, &ddl_log_entry))
1367 {
1368 /* Write to error log and continue with next log entry */
1369 sql_print_error("Failed to execute action for entry = %u from ddl log",
1370 read_entry);
1371 break;
1372 }
1373 read_entry= ddl_log_entry.next_entry;
1374 } while (read_entry);
1375 DBUG_RETURN(FALSE);
1376}
1377
1378
1379/*
1380 External interface methods for the DDL log Module
1381 ---------------------------------------------------
1382*/
1383
1384/**
1385 Write a ddl log entry.
1386
1387 A careful write of the ddl log is performed to ensure that we can
1388 handle crashes occurring during CREATE and ALTER TABLE processing.
1389
1390 @param ddl_log_entry Information about log entry
1391 @param[out] entry_written Entry information written into
1392
1393 @return Operation status
1394 @retval TRUE Error
1395 @retval FALSE Success
1396*/
1397
1398bool write_ddl_log_entry(DDL_LOG_ENTRY *ddl_log_entry,
1399 DDL_LOG_MEMORY_ENTRY **active_entry)
1400{
1401 bool error, write_header;
1402 DBUG_ENTER("write_ddl_log_entry");
1403
1404 mysql_mutex_assert_owner(&LOCK_gdl);
1405 if (init_ddl_log())
1406 {
1407 DBUG_RETURN(TRUE);
1408 }
1409 set_global_from_ddl_log_entry(ddl_log_entry);
1410 if (get_free_ddl_log_entry(active_entry, &write_header))
1411 {
1412 DBUG_RETURN(TRUE);
1413 }
1414 error= FALSE;
1415 DBUG_PRINT("ddl_log",
1416 ("write type %c next %u name '%s' from_name '%s' handler '%s'"
1417 " tmp_name '%s'",
1418 (char) global_ddl_log.file_entry_buf[DDL_LOG_ACTION_TYPE_POS],
1419 ddl_log_entry->next_entry,
1420 (char*) &global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS],
1421 (char*) &global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS
1422 + FN_REFLEN],
1423 (char*) &global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS
1424 + (2*FN_REFLEN)],
1425 (char*) &global_ddl_log.file_entry_buf[DDL_LOG_NAME_POS
1426 + (3*FN_REFLEN)]));
1427 if (unlikely(write_ddl_log_file_entry((*active_entry)->entry_pos)))
1428 {
1429 error= TRUE;
1430 sql_print_error("Failed to write entry_no = %u",
1431 (*active_entry)->entry_pos);
1432 }
1433 if (write_header && likely(!error))
1434 {
1435 (void) sync_ddl_log_no_lock();
1436 if (write_ddl_log_header())
1437 error= TRUE;
1438 }
1439 if (unlikely(error))
1440 release_ddl_log_memory_entry(*active_entry);
1441 DBUG_RETURN(error);
1442}
1443
1444
1445/**
1446 @brief Write final entry in the ddl log.
1447
1448 @details This is the last write in the ddl log. The previous log entries
1449 have already been written but not yet synched to disk.
1450 We write a couple of log entries that describes action to perform.
1451 This entries are set-up in a linked list, however only when a first
1452 execute entry is put as the first entry these will be executed.
1453 This routine writes this first.
1454
1455 @param first_entry First entry in linked list of entries
1456 to execute, if 0 = NULL it means that
1457 the entry is removed and the entries
1458 are put into the free list.
1459 @param complete Flag indicating we are simply writing
1460 info about that entry has been completed
1461 @param[in,out] active_entry Entry to execute, 0 = NULL if the entry
1462 is written first time and needs to be
1463 returned. In this case the entry written
1464 is returned in this parameter
1465
1466 @return Operation status
1467 @retval TRUE Error
1468 @retval FALSE Success
1469*/
1470
1471bool write_execute_ddl_log_entry(uint first_entry,
1472 bool complete,
1473 DDL_LOG_MEMORY_ENTRY **active_entry)
1474{
1475 bool write_header= FALSE;
1476 char *file_entry_buf= (char*)global_ddl_log.file_entry_buf;
1477 DBUG_ENTER("write_execute_ddl_log_entry");
1478
1479 mysql_mutex_assert_owner(&LOCK_gdl);
1480 if (init_ddl_log())
1481 {
1482 DBUG_RETURN(TRUE);
1483 }
1484 if (!complete)
1485 {
1486 /*
1487 We haven't synched the log entries yet, we synch them now before
1488 writing the execute entry. If complete is true we haven't written
1489 any log entries before, we are only here to write the execute
1490 entry to indicate it is done.
1491 */
1492 (void) sync_ddl_log_no_lock();
1493 file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_LOG_EXECUTE_CODE;
1494 }
1495 else
1496 file_entry_buf[DDL_LOG_ENTRY_TYPE_POS]= (char)DDL_IGNORE_LOG_ENTRY_CODE;
1497 file_entry_buf[DDL_LOG_ACTION_TYPE_POS]= 0; /* Ignored for execute entries */
1498 file_entry_buf[DDL_LOG_PHASE_POS]= 0;
1499 int4store(&file_entry_buf[DDL_LOG_NEXT_ENTRY_POS], first_entry);
1500 file_entry_buf[DDL_LOG_NAME_POS]= 0;
1501 file_entry_buf[DDL_LOG_NAME_POS + FN_REFLEN]= 0;
1502 file_entry_buf[DDL_LOG_NAME_POS + 2*FN_REFLEN]= 0;
1503 if (!(*active_entry))
1504 {
1505 if (get_free_ddl_log_entry(active_entry, &write_header))
1506 {
1507 DBUG_RETURN(TRUE);
1508 }
1509 write_header= TRUE;
1510 }
1511 if (write_ddl_log_file_entry((*active_entry)->entry_pos))
1512 {
1513 sql_print_error("Error writing execute entry in ddl log");
1514 release_ddl_log_memory_entry(*active_entry);
1515 DBUG_RETURN(TRUE);
1516 }
1517 (void) sync_ddl_log_no_lock();
1518 if (write_header)
1519 {
1520 if (write_ddl_log_header())
1521 {
1522 release_ddl_log_memory_entry(*active_entry);
1523 DBUG_RETURN(TRUE);
1524 }
1525 }
1526 DBUG_RETURN(FALSE);
1527}
1528
1529
1530/**
1531 Deactivate an individual entry.
1532
1533 @details see deactivate_ddl_log_entry_no_lock.
1534
1535 @param entry_no Entry position of record to change
1536
1537 @return Operation status
1538 @retval TRUE Error
1539 @retval FALSE Success
1540*/
1541
1542bool deactivate_ddl_log_entry(uint entry_no)
1543{
1544 bool error;
1545 DBUG_ENTER("deactivate_ddl_log_entry");
1546
1547 mysql_mutex_lock(&LOCK_gdl);
1548 error= deactivate_ddl_log_entry_no_lock(entry_no);
1549 mysql_mutex_unlock(&LOCK_gdl);
1550 DBUG_RETURN(error);
1551}
1552
1553
1554/**
1555 Sync ddl log file.
1556
1557 @return Operation status
1558 @retval TRUE Error
1559 @retval FALSE Success
1560*/
1561
1562bool sync_ddl_log()
1563{
1564 bool error;
1565 DBUG_ENTER("sync_ddl_log");
1566
1567 mysql_mutex_lock(&LOCK_gdl);
1568 error= sync_ddl_log_no_lock();
1569 mysql_mutex_unlock(&LOCK_gdl);
1570
1571 DBUG_RETURN(error);
1572}
1573
1574
1575/**
1576 Release a log memory entry.
1577 @param log_memory_entry Log memory entry to release
1578*/
1579
1580void release_ddl_log_memory_entry(DDL_LOG_MEMORY_ENTRY *log_entry)
1581{
1582 DDL_LOG_MEMORY_ENTRY *first_free= global_ddl_log.first_free;
1583 DDL_LOG_MEMORY_ENTRY *next_log_entry= log_entry->next_log_entry;
1584 DDL_LOG_MEMORY_ENTRY *prev_log_entry= log_entry->prev_log_entry;
1585 DBUG_ENTER("release_ddl_log_memory_entry");
1586
1587 mysql_mutex_assert_owner(&LOCK_gdl);
1588 global_ddl_log.first_free= log_entry;
1589 log_entry->next_log_entry= first_free;
1590
1591 if (prev_log_entry)
1592 prev_log_entry->next_log_entry= next_log_entry;
1593 else
1594 global_ddl_log.first_used= next_log_entry;
1595 if (next_log_entry)
1596 next_log_entry->prev_log_entry= prev_log_entry;
1597 DBUG_VOID_RETURN;
1598}
1599
1600
1601/**
1602 Execute one entry in the ddl log.
1603
1604 Executing an entry means executing a linked list of actions.
1605
1606 @param first_entry Reference to first action in entry
1607
1608 @return Operation status
1609 @retval TRUE Error
1610 @retval FALSE Success
1611*/
1612
1613bool execute_ddl_log_entry(THD *thd, uint first_entry)
1614{
1615 bool error;
1616 DBUG_ENTER("execute_ddl_log_entry");
1617
1618 mysql_mutex_lock(&LOCK_gdl);
1619 error= execute_ddl_log_entry_no_lock(thd, first_entry);
1620 mysql_mutex_unlock(&LOCK_gdl);
1621 DBUG_RETURN(error);
1622}
1623
1624
1625/**
1626 Close the ddl log.
1627*/
1628
1629static void close_ddl_log()
1630{
1631 DBUG_ENTER("close_ddl_log");
1632 if (global_ddl_log.file_id >= 0)
1633 {
1634 (void) mysql_file_close(global_ddl_log.file_id, MYF(MY_WME));
1635 global_ddl_log.file_id= (File) -1;
1636 }
1637 DBUG_VOID_RETURN;
1638}
1639
1640
1641/**
1642 Execute the ddl log at recovery of MySQL Server.
1643*/
1644
1645void execute_ddl_log_recovery()
1646{
1647 uint num_entries, i;
1648 THD *thd;
1649 DDL_LOG_ENTRY ddl_log_entry;
1650 char file_name[FN_REFLEN];
1651 static char recover_query_string[]= "INTERNAL DDL LOG RECOVER IN PROGRESS";
1652 DBUG_ENTER("execute_ddl_log_recovery");
1653
1654 /*
1655 Initialise global_ddl_log struct
1656 */
1657 bzero(global_ddl_log.file_entry_buf, sizeof(global_ddl_log.file_entry_buf));
1658 global_ddl_log.inited= FALSE;
1659 global_ddl_log.recovery_phase= TRUE;
1660 global_ddl_log.io_size= IO_SIZE;
1661 global_ddl_log.file_id= (File) -1;
1662
1663 /*
1664 To be able to run this from boot, we allocate a temporary THD
1665 */
1666 if (!(thd=new THD(0)))
1667 DBUG_VOID_RETURN;
1668 thd->thread_stack= (char*) &thd;
1669 thd->store_globals();
1670
1671 thd->set_query(recover_query_string, strlen(recover_query_string));
1672
1673 /* this also initialize LOCK_gdl */
1674 num_entries= read_ddl_log_header();
1675 mysql_mutex_lock(&LOCK_gdl);
1676 for (i= 1; i < num_entries + 1; i++)
1677 {
1678 if (read_ddl_log_entry(i, &ddl_log_entry))
1679 {
1680 sql_print_error("Failed to read entry no = %u from ddl log",
1681 i);
1682 continue;
1683 }
1684 if (ddl_log_entry.entry_type == DDL_LOG_EXECUTE_CODE)
1685 {
1686 if (execute_ddl_log_entry_no_lock(thd, ddl_log_entry.next_entry))
1687 {
1688 /* Real unpleasant scenario but we continue anyways. */
1689 continue;
1690 }
1691 }
1692 }
1693 close_ddl_log();
1694 create_ddl_log_file_name(file_name);
1695 (void) mysql_file_delete(key_file_global_ddl_log, file_name, MYF(0));
1696 global_ddl_log.recovery_phase= FALSE;
1697 mysql_mutex_unlock(&LOCK_gdl);
1698 thd->reset_query();
1699 delete thd;
1700 DBUG_VOID_RETURN;
1701}
1702
1703
1704/**
1705 Release all memory allocated to the ddl log.
1706*/
1707
1708void release_ddl_log()
1709{
1710 DDL_LOG_MEMORY_ENTRY *free_list;
1711 DDL_LOG_MEMORY_ENTRY *used_list;
1712 DBUG_ENTER("release_ddl_log");
1713
1714 if (!global_ddl_log.do_release)
1715 DBUG_VOID_RETURN;
1716
1717 mysql_mutex_lock(&LOCK_gdl);
1718 free_list= global_ddl_log.first_free;
1719 used_list= global_ddl_log.first_used;
1720 while (used_list)
1721 {
1722 DDL_LOG_MEMORY_ENTRY *tmp= used_list->next_log_entry;
1723 my_free(used_list);
1724 used_list= tmp;
1725 }
1726 while (free_list)
1727 {
1728 DDL_LOG_MEMORY_ENTRY *tmp= free_list->next_log_entry;
1729 my_free(free_list);
1730 free_list= tmp;
1731 }
1732 close_ddl_log();
1733 global_ddl_log.inited= 0;
1734 mysql_mutex_unlock(&LOCK_gdl);
1735 mysql_mutex_destroy(&LOCK_gdl);
1736 global_ddl_log.do_release= false;
1737 DBUG_VOID_RETURN;
1738}
1739
1740
1741/*
1742---------------------------------------------------------------------------
1743
1744 END MODULE DDL log
1745 --------------------
1746
1747---------------------------------------------------------------------------
1748*/
1749
1750
1751/**
1752 @brief construct a temporary shadow file name.
1753
1754 @details Make a shadow file name used by ALTER TABLE to construct the
1755 modified table (with keeping the original). The modified table is then
1756 moved back as original table. The name must start with the temp file
1757 prefix so it gets filtered out by table files listing routines.
1758
1759 @param[out] buff buffer to receive the constructed name
1760 @param bufflen size of buff
1761 @param lpt alter table data structure
1762
1763 @retval path length
1764*/
1765
1766uint build_table_shadow_filename(char *buff, size_t bufflen,
1767 ALTER_PARTITION_PARAM_TYPE *lpt)
1768{
1769 char tmp_name[FN_REFLEN];
1770 my_snprintf(tmp_name, sizeof (tmp_name), "%s-%s", tmp_file_prefix,
1771 lpt->table_name.str);
1772 return build_table_filename(buff, bufflen, lpt->db.str, tmp_name, "",
1773 FN_IS_TMP);
1774}
1775
1776
1777/*
1778 SYNOPSIS
1779 mysql_write_frm()
1780 lpt Struct carrying many parameters needed for this
1781 method
1782 flags Flags as defined below
1783 WFRM_INITIAL_WRITE If set we need to prepare table before
1784 creating the frm file
1785 WFRM_INSTALL_SHADOW If set we should install the new frm
1786 WFRM_KEEP_SHARE If set we know that the share is to be
1787 retained and thus we should ensure share
1788 object is correct, if not set we don't
1789 set the new partition syntax string since
1790 we know the share object is destroyed.
1791 WFRM_PACK_FRM If set we should pack the frm file and delete
1792 the frm file
1793
1794 RETURN VALUES
1795 TRUE Error
1796 FALSE Success
1797
1798 DESCRIPTION
1799 A support method that creates a new frm file and in this process it
1800 regenerates the partition data. It works fine also for non-partitioned
1801 tables since it only handles partitioned data if it exists.
1802*/
1803
1804bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags)
1805{
1806 /*
1807 Prepare table to prepare for writing a new frm file where the
1808 partitions in add/drop state have temporarily changed their state
1809 We set tmp_table to avoid get errors on naming of primary key index.
1810 */
1811 int error= 0;
1812 char path[FN_REFLEN+1];
1813 char shadow_path[FN_REFLEN+1];
1814 char shadow_frm_name[FN_REFLEN+1];
1815 char frm_name[FN_REFLEN+1];
1816#ifdef WITH_PARTITION_STORAGE_ENGINE
1817 char *part_syntax_buf;
1818 uint syntax_len;
1819#endif
1820 DBUG_ENTER("mysql_write_frm");
1821
1822 /*
1823 Build shadow frm file name
1824 */
1825 build_table_shadow_filename(shadow_path, sizeof(shadow_path) - 1, lpt);
1826 strxmov(shadow_frm_name, shadow_path, reg_ext, NullS);
1827 if (flags & WFRM_WRITE_SHADOW)
1828 {
1829 if (mysql_prepare_create_table(lpt->thd, lpt->create_info, lpt->alter_info,
1830 &lpt->db_options, lpt->table->file,
1831 &lpt->key_info_buffer, &lpt->key_count,
1832 C_ALTER_TABLE))
1833 {
1834 DBUG_RETURN(TRUE);
1835 }
1836#ifdef WITH_PARTITION_STORAGE_ENGINE
1837 {
1838 partition_info *part_info= lpt->table->part_info;
1839 if (part_info)
1840 {
1841 if (!(part_syntax_buf= generate_partition_syntax(lpt->thd, part_info,
1842 &syntax_len, TRUE,
1843 lpt->create_info,
1844 lpt->alter_info)))
1845 {
1846 DBUG_RETURN(TRUE);
1847 }
1848 part_info->part_info_string= part_syntax_buf;
1849 part_info->part_info_len= syntax_len;
1850 }
1851 }
1852#endif
1853 /* Write shadow frm file */
1854 lpt->create_info->table_options= lpt->db_options;
1855 LEX_CUSTRING frm= build_frm_image(lpt->thd, &lpt->table_name,
1856 lpt->create_info,
1857 lpt->alter_info->create_list,
1858 lpt->key_count, lpt->key_info_buffer,
1859 lpt->table->file);
1860 if (!frm.str)
1861 {
1862 error= 1;
1863 goto end;
1864 }
1865
1866 int error= writefrm(shadow_path, lpt->db.str, lpt->table_name.str,
1867 lpt->create_info->tmp_table(), frm.str, frm.length);
1868 my_free(const_cast<uchar*>(frm.str));
1869
1870 if (unlikely(error) ||
1871 unlikely(lpt->table->file->
1872 ha_create_partitioning_metadata(shadow_path,
1873 NULL, CHF_CREATE_FLAG)))
1874 {
1875 mysql_file_delete(key_file_frm, shadow_frm_name, MYF(0));
1876 error= 1;
1877 goto end;
1878 }
1879 }
1880 if (flags & WFRM_INSTALL_SHADOW)
1881 {
1882#ifdef WITH_PARTITION_STORAGE_ENGINE
1883 partition_info *part_info= lpt->part_info;
1884#endif
1885 /*
1886 Build frm file name
1887 */
1888 build_table_filename(path, sizeof(path) - 1, lpt->db.str,
1889 lpt->table_name.str, "", 0);
1890 strxnmov(frm_name, sizeof(frm_name), path, reg_ext, NullS);
1891 /*
1892 When we are changing to use new frm file we need to ensure that we
1893 don't collide with another thread in process to open the frm file.
1894 We start by deleting the .frm file and possible .par file. Then we
1895 write to the DDL log that we have completed the delete phase by
1896 increasing the phase of the log entry. Next step is to rename the
1897 new .frm file and the new .par file to the real name. After
1898 completing this we write a new phase to the log entry that will
1899 deactivate it.
1900 */
1901 if (mysql_file_delete(key_file_frm, frm_name, MYF(MY_WME)) ||
1902#ifdef WITH_PARTITION_STORAGE_ENGINE
1903 lpt->table->file->ha_create_partitioning_metadata(path, shadow_path,
1904 CHF_DELETE_FLAG) ||
1905 deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos) ||
1906 (sync_ddl_log(), FALSE) ||
1907 mysql_file_rename(key_file_frm,
1908 shadow_frm_name, frm_name, MYF(MY_WME)) ||
1909 lpt->table->file->ha_create_partitioning_metadata(path, shadow_path,
1910 CHF_RENAME_FLAG))
1911#else
1912 mysql_file_rename(key_file_frm,
1913 shadow_frm_name, frm_name, MYF(MY_WME)))
1914#endif
1915 {
1916 error= 1;
1917 goto err;
1918 }
1919#ifdef WITH_PARTITION_STORAGE_ENGINE
1920 if (part_info && (flags & WFRM_KEEP_SHARE))
1921 {
1922 TABLE_SHARE *share= lpt->table->s;
1923 char *tmp_part_syntax_str;
1924 if (!(part_syntax_buf= generate_partition_syntax(lpt->thd, part_info,
1925 &syntax_len, TRUE,
1926 lpt->create_info,
1927 lpt->alter_info)))
1928 {
1929 error= 1;
1930 goto err;
1931 }
1932 if (share->partition_info_buffer_size < syntax_len + 1)
1933 {
1934 share->partition_info_buffer_size= syntax_len+1;
1935 if (!(tmp_part_syntax_str= (char*) strmake_root(&share->mem_root,
1936 part_syntax_buf,
1937 syntax_len)))
1938 {
1939 error= 1;
1940 goto err;
1941 }
1942 share->partition_info_str= tmp_part_syntax_str;
1943 }
1944 else
1945 memcpy((char*) share->partition_info_str, part_syntax_buf,
1946 syntax_len + 1);
1947 share->partition_info_str_len= part_info->part_info_len= syntax_len;
1948 part_info->part_info_string= part_syntax_buf;
1949 }
1950#endif
1951
1952err:
1953#ifdef WITH_PARTITION_STORAGE_ENGINE
1954 deactivate_ddl_log_entry(part_info->frm_log_entry->entry_pos);
1955 part_info->frm_log_entry= NULL;
1956 (void) sync_ddl_log();
1957#endif
1958 ;
1959 }
1960
1961end:
1962 DBUG_RETURN(error);
1963}
1964
1965
1966/*
1967 SYNOPSIS
1968 write_bin_log()
1969 thd Thread object
1970 clear_error is clear_error to be called
1971 query Query to log
1972 query_length Length of query
1973 is_trans if the event changes either
1974 a trans or non-trans engine.
1975
1976 RETURN VALUES
1977 NONE
1978
1979 DESCRIPTION
1980 Write the binlog if open, routine used in multiple places in this
1981 file
1982*/
1983
1984int write_bin_log(THD *thd, bool clear_error,
1985 char const *query, ulong query_length, bool is_trans)
1986{
1987 int error= 0;
1988 if (mysql_bin_log.is_open())
1989 {
1990 int errcode= 0;
1991 thd_proc_info(thd, "Writing to binlog");
1992 if (clear_error)
1993 thd->clear_error();
1994 else
1995 errcode= query_error_code(thd, TRUE);
1996 error= thd->binlog_query(THD::STMT_QUERY_TYPE,
1997 query, query_length, is_trans, FALSE, FALSE,
1998 errcode);
1999 thd_proc_info(thd, 0);
2000 }
2001 return error;
2002}
2003
2004
2005/*
2006 delete (drop) tables.
2007
2008 SYNOPSIS
2009 mysql_rm_table()
2010 thd Thread handle
2011 tables List of tables to delete
2012 if_exists If 1, don't give error if one table doesn't exists
2013 drop_temporary 1 if DROP TEMPORARY
2014 drop_sequence 1 if DROP SEQUENCE
2015
2016 NOTES
2017 Will delete all tables that can be deleted and give a compact error
2018 messages for tables that could not be deleted.
2019 If a table is in use, we will wait for all users to free the table
2020 before dropping it
2021
2022 Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set, but
2023 not if under LOCK TABLES.
2024
2025 RETURN
2026 FALSE OK. In this case ok packet is sent to user
2027 TRUE Error
2028
2029*/
2030
2031bool mysql_rm_table(THD *thd,TABLE_LIST *tables, bool if_exists,
2032 bool drop_temporary, bool drop_sequence)
2033{
2034 bool error;
2035 Drop_table_error_handler err_handler;
2036 TABLE_LIST *table;
2037 DBUG_ENTER("mysql_rm_table");
2038
2039 /* Disable drop of enabled log tables, must be done before name locking */
2040 for (table= tables; table; table= table->next_local)
2041 {
2042 if (check_if_log_table(table, TRUE, "DROP"))
2043 DBUG_RETURN(true);
2044 }
2045
2046 if (!drop_temporary)
2047 {
2048 if (!in_bootstrap)
2049 {
2050 for (table= tables; table; table= table->next_local)
2051 {
2052 LEX_CSTRING db_name= table->db;
2053 LEX_CSTRING table_name= table->table_name;
2054 if (table->open_type == OT_BASE_ONLY ||
2055 !thd->find_temporary_table(table))
2056 (void) delete_statistics_for_table(thd, &db_name, &table_name);
2057 }
2058 }
2059
2060 if (!thd->locked_tables_mode)
2061 {
2062 if (drop_sequence)
2063 {
2064 /* We are trying to drop a sequence.
2065 Change all temporary tables that are not sequences to
2066 normal tables so that we can try to drop them instead.
2067 If we don't do this, we will get an error 'not a sequence'
2068 when trying to drop a sequence that is hidden by a temporary
2069 table.
2070 */
2071 for (table= tables; table; table= table->next_global)
2072 {
2073 if (table->open_type == OT_TEMPORARY_OR_BASE &&
2074 is_temporary_table(table) && !table->table->s->sequence)
2075 {
2076 thd->mark_tmp_table_as_free_for_reuse(table->table);
2077 table->table= NULL;
2078 }
2079 }
2080 }
2081 if (lock_table_names(thd, tables, NULL,
2082 thd->variables.lock_wait_timeout, 0))
2083 DBUG_RETURN(true);
2084 }
2085 else
2086 {
2087 for (table= tables; table; table= table->next_local)
2088 {
2089 if (is_temporary_table(table))
2090 {
2091 /*
2092 A temporary table.
2093
2094 Don't try to find a corresponding MDL lock or assign it
2095 to table->mdl_request.ticket. There can't be metadata
2096 locks for temporary tables: they are local to the session.
2097
2098 Later in this function we release the MDL lock only if
2099 table->mdl_requeset.ticket is not NULL. Thus here we
2100 ensure that we won't release the metadata lock on the base
2101 table locked with LOCK TABLES as a side effect of temporary
2102 table drop.
2103 */
2104 DBUG_ASSERT(table->mdl_request.ticket == NULL);
2105 }
2106 else
2107 {
2108 /*
2109 Not a temporary table.
2110
2111 Since 'tables' list can't contain duplicates (this is ensured
2112 by parser) it is safe to cache pointer to the TABLE instances
2113 in its elements.
2114 */
2115 table->table= find_table_for_mdl_upgrade(thd, table->db.str,
2116 table->table_name.str, false);
2117 if (!table->table)
2118 DBUG_RETURN(true);
2119 table->mdl_request.ticket= table->table->mdl_ticket;
2120 }
2121 }
2122 }
2123 }
2124
2125 /* mark for close and remove all cached entries */
2126 thd->push_internal_handler(&err_handler);
2127 error= mysql_rm_table_no_locks(thd, tables, if_exists, drop_temporary,
2128 false, drop_sequence, false, false);
2129 thd->pop_internal_handler();
2130
2131 if (unlikely(error))
2132 DBUG_RETURN(TRUE);
2133 my_ok(thd);
2134 DBUG_RETURN(FALSE);
2135
2136}
2137
2138
2139/**
2140 Find the comment in the query.
2141 That's auxiliary function to be used handling DROP TABLE [comment].
2142
2143 @param thd Thread handler
2144 @param comment_pos How many characters to skip before the comment.
2145 Can be either 9 for DROP TABLE or
2146 17 for DROP TABLE IF EXISTS
2147 @param comment_start returns the beginning of the comment if found.
2148
2149 @retval 0 no comment found
2150 @retval >0 the lenght of the comment found
2151
2152*/
2153static uint32 comment_length(THD *thd, uint32 comment_pos,
2154 const char **comment_start)
2155{
2156 /* We use uchar * here to make array indexing portable */
2157 const uchar *query= (uchar*) thd->query();
2158 const uchar *query_end= (uchar*) query + thd->query_length();
2159 const uchar *const state_map= thd->charset()->state_map;
2160
2161 for (; query < query_end; query++)
2162 {
2163 if (state_map[static_cast<uchar>(*query)] == MY_LEX_SKIP)
2164 continue;
2165 if (comment_pos-- == 0)
2166 break;
2167 }
2168 if (query > query_end - 3 /* comment can't be shorter than 4 */ ||
2169 state_map[static_cast<uchar>(*query)] != MY_LEX_LONG_COMMENT || query[1] != '*')
2170 return 0;
2171
2172 *comment_start= (char*) query;
2173
2174 for (query+= 3; query < query_end; query++)
2175 {
2176 if (query[-1] == '*' && query[0] == '/')
2177 return (uint32)((char*) query - *comment_start + 1);
2178 }
2179 return 0;
2180}
2181
2182/**
2183 Execute the drop of a normal or temporary table.
2184
2185 @param thd Thread handler
2186 @param tables Tables to drop
2187 @param if_exists If set, don't give an error if table doesn't exists.
2188 In this case we give an warning of level 'NOTE'
2189 @param drop_temporary Only drop temporary tables
2190 @param drop_view Allow to delete VIEW .frm
2191 @param dont_log_query Don't write query to log files. This will also not
2192 generate warnings if the handler files doesn't exists
2193 @param dont_free_locks Don't do automatic UNLOCK TABLE if no more locked
2194 tables
2195
2196 @retval 0 ok
2197 @retval 1 Error
2198 @retval -1 Thread was killed
2199
2200 @note This function assumes that metadata locks have already been taken.
2201 It is also assumed that the tables have been removed from TDC.
2202
2203 @note This function assumes that temporary tables to be dropped have
2204 been pre-opened using corresponding table list elements.
2205
2206 @todo When logging to the binary log, we should log
2207 tmp_tables and transactional tables as separate statements if we
2208 are in a transaction; This is needed to get these tables into the
2209 cached binary log that is only written on COMMIT.
2210 The current code only writes DROP statements that only uses temporary
2211 tables to the cache binary log. This should be ok on most cases, but
2212 not all.
2213*/
2214
2215int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
2216 bool drop_temporary, bool drop_view,
2217 bool drop_sequence,
2218 bool dont_log_query,
2219 bool dont_free_locks)
2220{
2221 TABLE_LIST *table;
2222 char path[FN_REFLEN + 1], wrong_tables_buff[160];
2223 LEX_CSTRING alias= null_clex_str;
2224 String wrong_tables(wrong_tables_buff, sizeof(wrong_tables_buff)-1,
2225 system_charset_info);
2226 uint path_length= 0, errors= 0;
2227 int error= 0;
2228 int non_temp_tables_count= 0;
2229 bool non_tmp_error= 0;
2230 bool trans_tmp_table_deleted= 0, non_trans_tmp_table_deleted= 0;
2231 bool non_tmp_table_deleted= 0;
2232 bool is_drop_tmp_if_exists_added= 0;
2233 bool was_view= 0, was_table= 0, is_sequence;
2234 String built_query;
2235 String built_trans_tmp_query, built_non_trans_tmp_query;
2236 DBUG_ENTER("mysql_rm_table_no_locks");
2237
2238 wrong_tables.length(0);
2239 /*
2240 Prepares the drop statements that will be written into the binary
2241 log as follows:
2242
2243 1 - If we are not processing a "DROP TEMPORARY" it prepares a
2244 "DROP".
2245
2246 2 - A "DROP" may result in a "DROP TEMPORARY" but the opposite is
2247 not true.
2248
2249 3 - If the current format is row, the IF EXISTS token needs to be
2250 appended because one does not know if CREATE TEMPORARY was previously
2251 written to the binary log.
2252
2253 4 - Add the IF_EXISTS token if necessary, i.e. if_exists is TRUE.
2254
2255 5 - For temporary tables, there is a need to differentiate tables
2256 in transactional and non-transactional storage engines. For that,
2257 reason, two types of drop statements are prepared.
2258
2259 The need to different the type of tables when dropping a temporary
2260 table stems from the fact that such drop does not commit an ongoing
2261 transaction and changes to non-transactional tables must be written
2262 ahead of the transaction in some circumstances.
2263
2264 6- Slave SQL thread ignores all replicate-* filter rules
2265 for temporary tables with 'IF EXISTS' clause. (See sql/sql_parse.cc:
2266 mysql_execute_command() for details). These commands will be binlogged
2267 as they are, even if the default database (from USE `db`) is not present
2268 on the Slave. This can cause point in time recovery failures later
2269 when user uses the slave's binlog to re-apply. Hence at the time of binary
2270 logging, these commands will be written with fully qualified table names
2271 and use `db` will be suppressed.
2272 */
2273 if (!dont_log_query)
2274 {
2275 const char *object_to_drop= (drop_sequence) ? "SEQUENCE" : "TABLE";
2276
2277 if (!drop_temporary)
2278 {
2279 const char *comment_start;
2280 uint32 comment_len;
2281
2282 built_query.set_charset(thd->charset());
2283 built_query.append("DROP ");
2284 built_query.append(object_to_drop);
2285 built_query.append(' ');
2286 if (if_exists)
2287 built_query.append("IF EXISTS ");
2288
2289 /* Preserve comment in original query */
2290 if ((comment_len= comment_length(thd, if_exists ? 17:9, &comment_start)))
2291 {
2292 built_query.append(comment_start, comment_len);
2293 built_query.append(" ");
2294 }
2295 }
2296
2297 built_trans_tmp_query.set_charset(system_charset_info);
2298 built_trans_tmp_query.append("DROP TEMPORARY ");
2299 built_trans_tmp_query.append(object_to_drop);
2300 built_trans_tmp_query.append(' ');
2301 if (thd->is_current_stmt_binlog_format_row() || if_exists)
2302 {
2303 is_drop_tmp_if_exists_added= true;
2304 built_trans_tmp_query.append("IF EXISTS ");
2305 }
2306 built_non_trans_tmp_query.set_charset(system_charset_info);
2307 built_non_trans_tmp_query.copy(built_trans_tmp_query);
2308 }
2309
2310 for (table= tables; table; table= table->next_local)
2311 {
2312 bool is_trans= 0;
2313 bool table_creation_was_logged= 1;
2314 LEX_CSTRING db= table->db;
2315 handlerton *table_type= 0;
2316
2317 DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p",
2318 table->db.str, table->table_name.str, table->table,
2319 table->table ? table->table->s : NULL));
2320
2321 /*
2322 If we are in locked tables mode and are dropping a temporary table,
2323 the ticket should be NULL to ensure that we don't release a lock
2324 on a base table later.
2325 */
2326 DBUG_ASSERT(!(thd->locked_tables_mode &&
2327 table->open_type != OT_BASE_ONLY &&
2328 thd->find_temporary_table(table) &&
2329 table->mdl_request.ticket != NULL));
2330
2331 if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table) ||
2332 (drop_sequence && table->table->s->table_type != TABLE_TYPE_SEQUENCE))
2333 error= 1;
2334 else
2335 {
2336 table_creation_was_logged= table->table->s->table_creation_was_logged;
2337 if (thd->drop_temporary_table(table->table, &is_trans, true))
2338 {
2339 error= 1;
2340 goto err;
2341 }
2342 error= 0;
2343 table->table= 0;
2344 }
2345
2346 if ((drop_temporary && if_exists) || !error)
2347 {
2348 /*
2349 This handles the case of temporary tables. We have the following cases:
2350
2351 . "DROP TEMPORARY" was executed and a temporary table was affected
2352 (i.e. drop_temporary && !error) or the if_exists was specified (i.e.
2353 drop_temporary && if_exists).
2354
2355 . "DROP" was executed but a temporary table was affected (.i.e
2356 !error).
2357 */
2358 if (!dont_log_query && table_creation_was_logged)
2359 {
2360 /*
2361 If there is an error, we don't know the type of the engine
2362 at this point. So, we keep it in the trx-cache.
2363 */
2364 is_trans= error ? TRUE : is_trans;
2365 if (is_trans)
2366 trans_tmp_table_deleted= TRUE;
2367 else
2368 non_trans_tmp_table_deleted= TRUE;
2369
2370 String *built_ptr_query=
2371 (is_trans ? &built_trans_tmp_query : &built_non_trans_tmp_query);
2372 /*
2373 Write the database name if it is not the current one or if
2374 thd->db is NULL or 'IF EXISTS' clause is present in 'DROP TEMPORARY'
2375 query.
2376 */
2377 if (thd->db.str == NULL || cmp(&db, &thd->db) ||
2378 is_drop_tmp_if_exists_added )
2379 {
2380 append_identifier(thd, built_ptr_query, &db);
2381 built_ptr_query->append(".");
2382 }
2383 append_identifier(thd, built_ptr_query, &table->table_name);
2384 built_ptr_query->append(",");
2385 }
2386 /*
2387 This means that a temporary table was droped and as such there
2388 is no need to proceed with the code that tries to drop a regular
2389 table.
2390 */
2391 if (!error) continue;
2392 }
2393 else if (!drop_temporary)
2394 {
2395 non_temp_tables_count++;
2396
2397 DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db.str,
2398 table->table_name.str,
2399 MDL_SHARED));
2400
2401 alias= (lower_case_table_names == 2) ? table->alias : table->table_name;
2402 /* remove .frm file and engine files */
2403 path_length= build_table_filename(path, sizeof(path) - 1, db.str, alias.str,
2404 reg_ext, 0);
2405
2406 /*
2407 This handles the case where a "DROP" was executed and a regular
2408 table "may be" dropped as drop_temporary is FALSE and error is
2409 TRUE. If the error was FALSE a temporary table was dropped and
2410 regardless of the status of drop_temporary a "DROP TEMPORARY"
2411 must be used.
2412 */
2413 if (!dont_log_query)
2414 {
2415 /*
2416 Note that unless if_exists is TRUE or a temporary table was deleted,
2417 there is no means to know if the statement should be written to the
2418 binary log. See further information on this variable in what follows.
2419 */
2420 non_tmp_table_deleted= (if_exists ? TRUE : non_tmp_table_deleted);
2421 /*
2422 Don't write the database name if it is the current one (or if
2423 thd->db is NULL).
2424 */
2425 if (thd->db.str == NULL || cmp(&db, &thd->db) != 0)
2426 {
2427 append_identifier(thd, &built_query, &db);
2428 built_query.append(".");
2429 }
2430
2431 append_identifier(thd, &built_query, &table->table_name);
2432 built_query.append(",");
2433 }
2434 }
2435 DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table");
2436 error= 0;
2437 if (drop_temporary ||
2438 (ha_table_exists(thd, &db, &alias, &table_type, &is_sequence) == 0 &&
2439 table_type == 0) ||
2440 (!drop_view && (was_view= (table_type == view_pseudo_hton))) ||
2441 (drop_sequence && !is_sequence))
2442 {
2443 /*
2444 One of the following cases happened:
2445 . "DROP TEMPORARY" but a temporary table was not found.
2446 . "DROP" but table was not found
2447 . "DROP TABLE" statement, but it's a view.
2448 . "DROP SEQUENCE", but it's not a sequence
2449 */
2450 was_table= drop_sequence && table_type;
2451 if (if_exists)
2452 {
2453 char buff[FN_REFLEN];
2454 int err= (drop_sequence ? ER_UNKNOWN_SEQUENCES :
2455 ER_BAD_TABLE_ERROR);
2456 String tbl_name(buff, sizeof(buff), system_charset_info);
2457 tbl_name.length(0);
2458 tbl_name.append(&db);
2459 tbl_name.append('.');
2460 tbl_name.append(&table->table_name);
2461 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
2462 err, ER_THD(thd, err),
2463 tbl_name.c_ptr_safe());
2464 }
2465 else
2466 {
2467 non_tmp_error = (drop_temporary ? non_tmp_error : TRUE);
2468 error= 1;
2469 }
2470 }
2471 else
2472 {
2473 char *end;
2474 int frm_delete_error= 0;
2475 /*
2476 It could happen that table's share in the table definition cache
2477 is the only thing that keeps the engine plugin loaded
2478 (if it is uninstalled and waits for the ref counter to drop to 0).
2479
2480 In this case, the tdc_remove_table() below will release and unload
2481 the plugin. And ha_delete_table() will get a dangling pointer.
2482
2483 Let's lock the plugin till the end of the statement.
2484 */
2485 if (table_type && table_type != view_pseudo_hton)
2486 ha_lock_engine(thd, table_type);
2487
2488 if (thd->locked_tables_mode == LTM_LOCK_TABLES ||
2489 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)
2490 {
2491 if (wait_while_table_is_used(thd, table->table, HA_EXTRA_NOT_USED))
2492 {
2493 error= -1;
2494 goto err;
2495 }
2496 /* the following internally does TDC_RT_REMOVE_ALL */
2497 close_all_tables_for_name(thd, table->table->s,
2498 HA_EXTRA_PREPARE_FOR_DROP, NULL);
2499 table->table= 0;
2500 }
2501 else
2502 tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db.str, table->table_name.str,
2503 false);
2504
2505 /* Check that we have an exclusive lock on the table to be dropped. */
2506 DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db.str,
2507 table->table_name.str,
2508 MDL_EXCLUSIVE));
2509
2510 // Remove extension for delete
2511 *(end= path + path_length - reg_ext_length)= '\0';
2512
2513 error= ha_delete_table(thd, table_type, path, &db, &table->table_name,
2514 !dont_log_query);
2515 if (!error)
2516 {
2517 /* Delete the table definition file */
2518 strmov(end,reg_ext);
2519 if (table_type && table_type != view_pseudo_hton &&
2520 table_type->discover_table)
2521 {
2522 /*
2523 Table type is using discovery and may not need a .frm file.
2524 Delete it silently if it exists
2525 */
2526 (void) mysql_file_delete(key_file_frm, path, MYF(0));
2527 }
2528 else if (unlikely(mysql_file_delete(key_file_frm, path,
2529 MYF(MY_WME))))
2530 {
2531 frm_delete_error= my_errno;
2532 DBUG_ASSERT(frm_delete_error);
2533 }
2534 }
2535
2536 if (likely(!error))
2537 {
2538 int trigger_drop_error= 0;
2539
2540 if (likely(!frm_delete_error))
2541 {
2542 non_tmp_table_deleted= TRUE;
2543 trigger_drop_error=
2544 Table_triggers_list::drop_all_triggers(thd, &db, &table->table_name);
2545 }
2546
2547 if (unlikely(trigger_drop_error) ||
2548 (frm_delete_error && frm_delete_error != ENOENT))
2549 error= 1;
2550 else if (frm_delete_error && if_exists)
2551 thd->clear_error();
2552 }
2553 non_tmp_error|= MY_TEST(error);
2554 }
2555
2556 if (error)
2557 {
2558 if (wrong_tables.length())
2559 wrong_tables.append(',');
2560 wrong_tables.append(&db);
2561 wrong_tables.append('.');
2562 wrong_tables.append(&table->table_name);
2563 errors++;
2564 }
2565 else
2566 {
2567 PSI_CALL_drop_table_share(false, table->db.str, (uint)table->db.length,
2568 table->table_name.str, (uint)table->table_name.length);
2569 mysql_audit_drop_table(thd, table);
2570 }
2571
2572 DBUG_PRINT("table", ("table: %p s: %p", table->table,
2573 table->table ? table->table->s : NULL));
2574 }
2575 DEBUG_SYNC(thd, "rm_table_no_locks_before_binlog");
2576 thd->thread_specific_used|= (trans_tmp_table_deleted ||
2577 non_trans_tmp_table_deleted);
2578 error= 0;
2579err:
2580 if (wrong_tables.length())
2581 {
2582 DBUG_ASSERT(errors);
2583 if (errors == 1 && was_view)
2584 my_error(ER_IT_IS_A_VIEW, MYF(0), wrong_tables.c_ptr_safe());
2585 else if (errors == 1 && drop_sequence && was_table)
2586 my_error(ER_NOT_SEQUENCE2, MYF(0), wrong_tables.c_ptr_safe());
2587 else if (errors > 1 || !thd->is_error())
2588 my_error((drop_sequence ? ER_UNKNOWN_SEQUENCES :
2589 ER_BAD_TABLE_ERROR),
2590 MYF(0), wrong_tables.c_ptr_safe());
2591 error= 1;
2592 }
2593
2594 /*
2595 We are always logging drop of temporary tables.
2596 The reason is to handle the following case:
2597 - Use statement based replication
2598 - CREATE TEMPORARY TABLE foo (logged)
2599 - set row based replication
2600 - DROP TEMPORAY TABLE foo (needs to be logged)
2601 This should be fixed so that we remember if creation of the
2602 temporary table was logged and only log it if the creation was
2603 logged.
2604 */
2605
2606 if (non_trans_tmp_table_deleted ||
2607 trans_tmp_table_deleted || non_tmp_table_deleted)
2608 {
2609 if (non_trans_tmp_table_deleted || trans_tmp_table_deleted)
2610 thd->transaction.stmt.mark_dropped_temp_table();
2611
2612 query_cache_invalidate3(thd, tables, 0);
2613 if (!dont_log_query && mysql_bin_log.is_open())
2614 {
2615 if (non_trans_tmp_table_deleted)
2616 {
2617 /* Chop of the last comma */
2618 built_non_trans_tmp_query.chop();
2619 built_non_trans_tmp_query.append(" /* generated by server */");
2620#ifdef WITH_WSREP
2621 thd->wsrep_skip_wsrep_GTID = true;
2622#endif /* WITH_WSREP */
2623 error |= thd->binlog_query(THD::STMT_QUERY_TYPE,
2624 built_non_trans_tmp_query.ptr(),
2625 built_non_trans_tmp_query.length(),
2626 FALSE, FALSE,
2627 is_drop_tmp_if_exists_added,
2628 0);
2629 }
2630 if (trans_tmp_table_deleted)
2631 {
2632 /* Chop of the last comma */
2633 built_trans_tmp_query.chop();
2634 built_trans_tmp_query.append(" /* generated by server */");
2635#ifdef WITH_WSREP
2636 thd->wsrep_skip_wsrep_GTID = true;
2637#endif /* WITH_WSREP */
2638 error |= thd->binlog_query(THD::STMT_QUERY_TYPE,
2639 built_trans_tmp_query.ptr(),
2640 built_trans_tmp_query.length(),
2641 TRUE, FALSE,
2642 is_drop_tmp_if_exists_added,
2643 0);
2644 }
2645 if (non_tmp_table_deleted)
2646 {
2647 /* Chop of the last comma */
2648 built_query.chop();
2649 built_query.append(" /* generated by server */");
2650 int error_code = non_tmp_error ? thd->get_stmt_da()->sql_errno()
2651 : 0;
2652#ifdef WITH_WSREP
2653 thd->wsrep_skip_wsrep_GTID = false;
2654#endif /* WITH_WSREP */
2655 error |= thd->binlog_query(THD::STMT_QUERY_TYPE,
2656 built_query.ptr(),
2657 built_query.length(),
2658 TRUE, FALSE, FALSE,
2659 error_code);
2660 }
2661 }
2662 }
2663
2664 if (!drop_temporary)
2665 {
2666 /*
2667 Under LOCK TABLES we should release meta-data locks on the tables
2668 which were dropped.
2669
2670 Leave LOCK TABLES mode if we managed to drop all tables which were
2671 locked. Additional check for 'non_temp_tables_count' is to avoid
2672 leaving LOCK TABLES mode if we have dropped only temporary tables.
2673 */
2674 if (thd->locked_tables_mode)
2675 {
2676 if (thd->lock && thd->lock->table_count == 0 &&
2677 non_temp_tables_count > 0 && !dont_free_locks)
2678 {
2679 thd->locked_tables_list.unlock_locked_tables(thd);
2680 goto end;
2681 }
2682 for (table= tables; table; table= table->next_local)
2683 {
2684 /* Drop locks for all successfully dropped tables. */
2685 if (table->table == NULL && table->mdl_request.ticket)
2686 {
2687 /*
2688 Under LOCK TABLES we may have several instances of table open
2689 and locked and therefore have to remove several metadata lock
2690 requests associated with them.
2691 */
2692 thd->mdl_context.release_all_locks_for_name(table->mdl_request.ticket);
2693 }
2694 }
2695 }
2696 /*
2697 Rely on the caller to implicitly commit the transaction
2698 and release metadata locks.
2699 */
2700 }
2701
2702end:
2703#ifdef WITH_WSREP
2704 thd->wsrep_skip_wsrep_GTID = false;
2705#endif /* WITH_WSREP */
2706 DBUG_RETURN(error);
2707}
2708
2709/**
2710 Log the drop of a table.
2711
2712 @param thd Thread handler
2713 @param db_name Database name
2714 @param table_name Table name
2715 @param temporary_table 1 if table was a temporary table
2716
2717 This code is only used in the case of failed CREATE OR REPLACE TABLE
2718 when the original table was dropped but we could not create the new one.
2719*/
2720
2721bool log_drop_table(THD *thd, const LEX_CSTRING *db_name,
2722 const LEX_CSTRING *table_name,
2723 bool temporary_table)
2724{
2725 char buff[NAME_LEN*2 + 80];
2726 String query(buff, sizeof(buff), system_charset_info);
2727 bool error;
2728 DBUG_ENTER("log_drop_table");
2729
2730 if (!mysql_bin_log.is_open())
2731 DBUG_RETURN(0);
2732
2733 query.length(0);
2734 query.append(STRING_WITH_LEN("DROP "));
2735 if (temporary_table)
2736 query.append(STRING_WITH_LEN("TEMPORARY "));
2737 query.append(STRING_WITH_LEN("TABLE IF EXISTS "));
2738 append_identifier(thd, &query, db_name);
2739 query.append(".");
2740 append_identifier(thd, &query, table_name);
2741 query.append(STRING_WITH_LEN("/* Generated to handle "
2742 "failed CREATE OR REPLACE */"));
2743 error= thd->binlog_query(THD::STMT_QUERY_TYPE,
2744 query.ptr(), query.length(),
2745 FALSE, FALSE, temporary_table, 0);
2746 DBUG_RETURN(error);
2747}
2748
2749
2750/**
2751 Quickly remove a table.
2752
2753 @param thd Thread context.
2754 @param base The handlerton handle.
2755 @param db The database name.
2756 @param table_name The table name.
2757 @param flags Flags for build_table_filename() as well as describing
2758 if handler files / .FRM should be deleted as well.
2759
2760 @return False in case of success, True otherwise.
2761*/
2762
2763bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db,
2764 const LEX_CSTRING *table_name, uint flags, const char *table_path)
2765{
2766 char path[FN_REFLEN + 1];
2767 int error= 0;
2768 DBUG_ENTER("quick_rm_table");
2769
2770 size_t path_length= table_path ?
2771 (strxnmov(path, sizeof(path) - 1, table_path, reg_ext, NullS) - path) :
2772 build_table_filename(path, sizeof(path)-1, db->str, table_name->str, reg_ext, flags);
2773 if (mysql_file_delete(key_file_frm, path, MYF(0)))
2774 error= 1; /* purecov: inspected */
2775 path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
2776 if (flags & NO_HA_TABLE)
2777 {
2778 handler *file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base);
2779 if (!file)
2780 DBUG_RETURN(true);
2781 (void) file->ha_create_partitioning_metadata(path, NULL, CHF_DELETE_FLAG);
2782 delete file;
2783 }
2784 if (!(flags & (FRM_ONLY|NO_HA_TABLE)))
2785 error|= ha_delete_table(current_thd, base, path, db, table_name, 0);
2786
2787 if (likely(error == 0))
2788 {
2789 PSI_CALL_drop_table_share(flags & FN_IS_TMP, db->str, (uint)db->length,
2790 table_name->str, (uint)table_name->length);
2791 }
2792
2793 DBUG_RETURN(error);
2794}
2795
2796
2797/*
2798 Sort keys in the following order:
2799 - PRIMARY KEY
2800 - UNIQUE keys where all column are NOT NULL
2801 - UNIQUE keys that don't contain partial segments
2802 - Other UNIQUE keys
2803 - Normal keys
2804 - Fulltext keys
2805
2806 This will make checking for duplicated keys faster and ensure that
2807 PRIMARY keys are prioritized.
2808*/
2809
2810static int sort_keys(KEY *a, KEY *b)
2811{
2812 ulong a_flags= a->flags, b_flags= b->flags;
2813
2814 if (a_flags & HA_NOSAME)
2815 {
2816 if (!(b_flags & HA_NOSAME))
2817 return -1;
2818 if ((a_flags ^ b_flags) & HA_NULL_PART_KEY)
2819 {
2820 /* Sort NOT NULL keys before other keys */
2821 return (a_flags & HA_NULL_PART_KEY) ? 1 : -1;
2822 }
2823 if (a->name.str == primary_key_name)
2824 return -1;
2825 if (b->name.str == primary_key_name)
2826 return 1;
2827 /* Sort keys don't containing partial segments before others */
2828 if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
2829 return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
2830 }
2831 else if (b_flags & HA_NOSAME)
2832 return 1; // Prefer b
2833
2834 if ((a_flags ^ b_flags) & HA_FULLTEXT)
2835 {
2836 return (a_flags & HA_FULLTEXT) ? 1 : -1;
2837 }
2838 /*
2839 Prefer original key order. usable_key_parts contains here
2840 the original key position.
2841 */
2842 return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
2843 (a->usable_key_parts > b->usable_key_parts) ? 1 :
2844 0);
2845}
2846
2847/*
2848 Check TYPELIB (set or enum) for duplicates
2849
2850 SYNOPSIS
2851 check_duplicates_in_interval()
2852 set_or_name "SET" or "ENUM" string for warning message
2853 name name of the checked column
2854 typelib list of values for the column
2855 dup_val_count returns count of duplicate elements
2856
2857 DESCRIPTION
2858 This function prints an warning for each value in list
2859 which has some duplicates on its right
2860
2861 RETURN VALUES
2862 0 ok
2863 1 Error
2864*/
2865
2866bool check_duplicates_in_interval(const char *set_or_name,
2867 const char *name, TYPELIB *typelib,
2868 CHARSET_INFO *cs, unsigned int *dup_val_count)
2869{
2870 TYPELIB tmp= *typelib;
2871 const char **cur_value= typelib->type_names;
2872 unsigned int *cur_length= typelib->type_lengths;
2873 *dup_val_count= 0;
2874
2875 for ( ; tmp.count > 1; cur_value++, cur_length++)
2876 {
2877 tmp.type_names++;
2878 tmp.type_lengths++;
2879 tmp.count--;
2880 if (find_type2(&tmp, (const char*)*cur_value, *cur_length, cs))
2881 {
2882 THD *thd= current_thd;
2883 ErrConvString err(*cur_value, *cur_length, cs);
2884 if (current_thd->is_strict_mode())
2885 {
2886 my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
2887 name, err.ptr(), set_or_name);
2888 return 1;
2889 }
2890 push_warning_printf(thd,Sql_condition::WARN_LEVEL_NOTE,
2891 ER_DUPLICATED_VALUE_IN_TYPE,
2892 ER_THD(thd, ER_DUPLICATED_VALUE_IN_TYPE),
2893 name, err.ptr(), set_or_name);
2894 (*dup_val_count)++;
2895 }
2896 }
2897 return 0;
2898}
2899
2900
2901bool Column_definition::prepare_stage2_blob(handler *file,
2902 ulonglong table_flags,
2903 uint field_flags)
2904{
2905 if (table_flags & HA_NO_BLOBS)
2906 {
2907 my_error(ER_TABLE_CANT_HANDLE_BLOB, MYF(0), file->table_type());
2908 return true;
2909 }
2910 pack_flag= field_flags |
2911 pack_length_to_packflag(pack_length - portable_sizeof_char_ptr);
2912 if (charset->state & MY_CS_BINSORT)
2913 pack_flag|= FIELDFLAG_BINARY;
2914 length= 8; // Unireg field length
2915 return false;
2916}
2917
2918
2919bool Column_definition::prepare_stage2_typelib(const char *type_name,
2920 uint field_flags,
2921 uint *dup_val_count)
2922{
2923 pack_flag= pack_length_to_packflag(pack_length) | field_flags;
2924 if (charset->state & MY_CS_BINSORT)
2925 pack_flag|= FIELDFLAG_BINARY;
2926 return check_duplicates_in_interval(type_name, field_name.str, interval,
2927 charset, dup_val_count);
2928}
2929
2930
2931uint Column_definition::pack_flag_numeric(uint dec) const
2932{
2933 return (FIELDFLAG_NUMBER |
2934 (flags & UNSIGNED_FLAG ? 0 : FIELDFLAG_DECIMAL) |
2935 (flags & ZEROFILL_FLAG ? FIELDFLAG_ZEROFILL : 0) |
2936 (dec << FIELDFLAG_DEC_SHIFT));
2937}
2938
2939
2940bool Column_definition::prepare_stage2_varchar(ulonglong table_flags)
2941{
2942#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
2943 if (table_flags & HA_NO_VARCHAR)
2944 {
2945 /* convert VARCHAR to CHAR because handler is not yet up to date */
2946 set_handler(&type_handler_var_string);
2947 pack_length= type_handler()->calc_pack_length((uint) length);
2948 if ((length / charset->mbmaxlen) > MAX_FIELD_CHARLENGTH)
2949 {
2950 my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name.str,
2951 static_cast<ulong>(MAX_FIELD_CHARLENGTH));
2952 return true;
2953 }
2954 }
2955#endif
2956 pack_flag= (charset->state & MY_CS_BINSORT) ? FIELDFLAG_BINARY : 0;
2957 return false;
2958}
2959
2960
2961/*
2962 Prepare a Column_definition instance for packing
2963 Members such as pack_flag are valid after this call.
2964
2965 @param IN handler - storage engine handler,
2966 or NULL if preparing for an SP variable
2967 @param IN table_flags - table flags
2968
2969 @retval false - ok
2970 @retval true - error (not supported type, bad definition, etc)
2971*/
2972
2973bool Column_definition::prepare_stage2(handler *file,
2974 ulonglong table_flags)
2975{
2976 DBUG_ENTER("Column_definition::prepare_stage2");
2977
2978 /*
2979 This code came from mysql_prepare_create_table.
2980 Indent preserved to make patching easier
2981 */
2982 DBUG_ASSERT(charset);
2983
2984 if (type_handler()->Column_definition_prepare_stage2(this, file, table_flags))
2985 DBUG_RETURN(true);
2986
2987 if (!(flags & NOT_NULL_FLAG) ||
2988 (vcol_info)) /* Make virtual columns allow NULL values */
2989 pack_flag|= FIELDFLAG_MAYBE_NULL;
2990 if (flags & NO_DEFAULT_VALUE_FLAG)
2991 pack_flag|= FIELDFLAG_NO_DEFAULT;
2992 DBUG_RETURN(false);
2993}
2994
2995
2996/*
2997 Get character set from field object generated by parser using
2998 default values when not set.
2999
3000 SYNOPSIS
3001 get_sql_field_charset()
3002 sql_field The sql_field object
3003 create_info Info generated by parser
3004
3005 RETURN VALUES
3006 cs Character set
3007*/
3008
3009CHARSET_INFO* get_sql_field_charset(Column_definition *sql_field,
3010 HA_CREATE_INFO *create_info)
3011{
3012 CHARSET_INFO *cs= sql_field->charset;
3013
3014 if (!cs)
3015 cs= create_info->default_table_charset;
3016 /*
3017 table_charset is set only in ALTER TABLE t1 CONVERT TO CHARACTER SET csname
3018 if we want change character set for all varchar/char columns.
3019 But the table charset must not affect the BLOB fields, so don't
3020 allow to change my_charset_bin to somethig else.
3021 */
3022 if (create_info->table_charset && cs != &my_charset_bin)
3023 cs= create_info->table_charset;
3024 return cs;
3025}
3026
3027
3028/**
3029 Modifies the first column definition whose SQL type is TIMESTAMP
3030 by adding the features DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
3031
3032 If the first TIMESTAMP column appears to be nullable, or to have an
3033 explicit default, or to be a virtual column, then no promition is done.
3034
3035 @param column_definitions The list of column definitions, in the physical
3036 order in which they appear in the table.
3037*/
3038
3039void promote_first_timestamp_column(List<Create_field> *column_definitions)
3040{
3041 List_iterator_fast<Create_field> it(*column_definitions);
3042 Create_field *column_definition;
3043
3044 while ((column_definition= it++) != NULL)
3045 {
3046 if (column_definition->is_timestamp_type() || // TIMESTAMP
3047 column_definition->unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy
3048 {
3049 DBUG_PRINT("info", ("field-ptr:%p", column_definition->field));
3050 if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
3051 column_definition->default_value == NULL && // no constant default,
3052 column_definition->unireg_check == Field::NONE && // no function default
3053 column_definition->vcol_info == NULL &&
3054 !(column_definition->flags & VERS_SYSTEM_FIELD)) // column isn't generated
3055 {
3056 DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to "
3057 "DEFAULT CURRENT_TIMESTAMP ON UPDATE "
3058 "CURRENT_TIMESTAMP",
3059 column_definition->field_name.str
3060 ));
3061 column_definition->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
3062 }
3063 return;
3064 }
3065 }
3066}
3067
3068
3069/**
3070 Check if there is a duplicate key. Report a warning for every duplicate key.
3071
3072 @param thd Thread context.
3073 @param key Key to be checked.
3074 @param key_info Key meta-data info.
3075 @param key_list List of existing keys.
3076*/
3077static void check_duplicate_key(THD *thd, Key *key, KEY *key_info,
3078 List<Key> *key_list)
3079{
3080 /*
3081 We only check for duplicate indexes if it is requested and the
3082 key is not auto-generated.
3083
3084 Check is requested if the key was explicitly created or altered
3085 by the user (unless it's a foreign key).
3086 */
3087 if (!key->key_create_info.check_for_duplicate_indexes || key->generated)
3088 return;
3089
3090 List_iterator_fast<Key> key_list_iterator(*key_list);
3091 List_iterator_fast<Key_part_spec> key_column_iterator(key->columns);
3092 Key *k;
3093
3094 while ((k= key_list_iterator++))
3095 {
3096 // Looking for a similar key...
3097
3098 if (k == key)
3099 break;
3100
3101 if (k->generated ||
3102 (key->type != k->type) ||
3103 (key->key_create_info.algorithm != k->key_create_info.algorithm) ||
3104 (key->columns.elements != k->columns.elements))
3105 {
3106 // Keys are different.
3107 continue;
3108 }
3109
3110 /*
3111 Keys 'key' and 'k' might be identical.
3112 Check that the keys have identical columns in the same order.
3113 */
3114
3115 List_iterator_fast<Key_part_spec> k_column_iterator(k->columns);
3116 uint i;
3117 key_column_iterator.rewind();
3118
3119 for (i= 0; i < key->columns.elements; ++i)
3120 {
3121 Key_part_spec *c1= key_column_iterator++;
3122 Key_part_spec *c2= k_column_iterator++;
3123
3124 DBUG_ASSERT(c1 && c2);
3125
3126 if (lex_string_cmp(system_charset_info,
3127 &c1->field_name, &c2->field_name) ||
3128 (c1->length != c2->length))
3129 break;
3130 }
3131
3132 // Report a warning if we have two identical keys.
3133
3134 if (i == key->columns.elements)
3135 {
3136 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
3137 ER_DUP_INDEX, ER_THD(thd, ER_DUP_INDEX),
3138 key_info->name.str);
3139 break;
3140 }
3141 }
3142}
3143
3144
3145bool Column_definition::prepare_stage1_typelib(THD *thd,
3146 MEM_ROOT *mem_root,
3147 handler *file,
3148 ulonglong table_flags)
3149{
3150 /*
3151 Pass the last parameter to prepare_interval_field() as follows:
3152 - If we are preparing for an SP variable (file is NULL), we pass "false",
3153 to force allocation and full copying of TYPELIB values on the given
3154 mem_root, even if no character set conversion is needed. This is needed
3155 because a life cycle of an SP variable is longer than the current query.
3156
3157 - If we are preparing for a CREATE TABLE, (file != NULL), we pass "true".
3158 This will create the typelib in runtime memory - we will free the
3159 occupied memory at the same time when we free this
3160 sql_field -- at the end of execution.
3161 Pass "true" as the last argument to reuse "interval_list"
3162 values in "interval" in cases when no character conversion is needed,
3163 to avoid extra copying.
3164 */
3165 if (prepare_interval_field(mem_root, file != NULL))
3166 return true; // E.g. wrong values with commas: SET('a,b')
3167 create_length_to_internal_length_typelib();
3168
3169 DBUG_ASSERT(file || !default_value); // SP variables have no default_value
3170 if (default_value && default_value->expr->basic_const_item())
3171 {
3172 if ((charset != default_value->expr->collation.collation &&
3173 prepare_stage1_convert_default(thd, mem_root, charset)) ||
3174 prepare_stage1_check_typelib_default())
3175 return true;
3176 }
3177 return false;
3178}
3179
3180
3181bool Column_definition::prepare_stage1_string(THD *thd,
3182 MEM_ROOT *mem_root,
3183 handler *file,
3184 ulonglong table_flags)
3185{
3186 create_length_to_internal_length_string();
3187 if (prepare_blob_field(thd))
3188 return true;
3189 DBUG_ASSERT(file || !default_value); // SP variables have no default_value
3190 /*
3191 Convert the default value from client character
3192 set into the column character set if necessary.
3193 We can only do this for constants as we have not yet run fix_fields.
3194 But not for blobs, as they will be stored as SQL expressions, not
3195 written down into the record image.
3196 */
3197 if (!(flags & BLOB_FLAG) && default_value &&
3198 default_value->expr->basic_const_item() &&
3199 charset != default_value->expr->collation.collation)
3200 {
3201 if (prepare_stage1_convert_default(thd, mem_root, charset))
3202 return true;
3203 }
3204 return false;
3205}
3206
3207
3208bool Column_definition::prepare_stage1_bit(THD *thd,
3209 MEM_ROOT *mem_root,
3210 handler *file,
3211 ulonglong table_flags)
3212{
3213 pack_flag= FIELDFLAG_NUMBER;
3214 if (!(table_flags & HA_CAN_BIT_FIELD))
3215 pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
3216 create_length_to_internal_length_bit();
3217 return false;
3218}
3219
3220
3221bool Column_definition::prepare_stage1(THD *thd,
3222 MEM_ROOT *mem_root,
3223 handler *file,
3224 ulonglong table_flags)
3225{
3226 return type_handler()->Column_definition_prepare_stage1(thd, mem_root,
3227 this, file,
3228 table_flags);
3229}
3230
3231
3232bool Column_definition::prepare_stage1_convert_default(THD *thd,
3233 MEM_ROOT *mem_root,
3234 CHARSET_INFO *cs)
3235{
3236 DBUG_ASSERT(thd->mem_root == mem_root);
3237 Item *item;
3238 if (!(item= default_value->expr->safe_charset_converter(thd, cs)))
3239 {
3240 my_error(ER_INVALID_DEFAULT, MYF(0), field_name.str);
3241 return true; // Could not convert
3242 }
3243 /* Fix for prepare statement */
3244 thd->change_item_tree(&default_value->expr, item);
3245 return false;
3246}
3247
3248
3249bool Column_definition::prepare_stage1_check_typelib_default()
3250{
3251 StringBuffer<MAX_FIELD_WIDTH> str;
3252 String *def= default_value->expr->val_str(&str);
3253 bool not_found;
3254 if (def == NULL) /* SQL "NULL" maps to NULL */
3255 {
3256 not_found= flags & NOT_NULL_FLAG;
3257 }
3258 else
3259 {
3260 not_found= false;
3261 if (real_field_type() == MYSQL_TYPE_SET)
3262 {
3263 char *not_used;
3264 uint not_used2;
3265 find_set(interval, def->ptr(), def->length(),
3266 charset, &not_used, &not_used2, &not_found);
3267 }
3268 else /* MYSQL_TYPE_ENUM */
3269 {
3270 def->length(charset->cset->lengthsp(charset,
3271 def->ptr(), def->length()));
3272 not_found= !find_type2(interval, def->ptr(), def->length(), charset);
3273 }
3274 }
3275 if (not_found)
3276 {
3277 my_error(ER_INVALID_DEFAULT, MYF(0), field_name.str);
3278 return true;
3279 }
3280 return false;
3281}
3282/*
3283 This function adds a invisible field to field_list
3284 SYNOPSIS
3285 mysql_add_invisible_field()
3286 thd Thread Object
3287 field_list list of all table fields
3288 field_name name/prefix of invisible field
3289 ( Prefix in the case when it is
3290 *INVISIBLE_FULL*
3291 and given name is duplicate)
3292 type_handler field data type
3293 invisible
3294 default value
3295 RETURN VALUE
3296 Create_field pointer
3297*/
3298int mysql_add_invisible_field(THD *thd, List<Create_field> * field_list,
3299 const char *field_name, Type_handler *type_handler,
3300 field_visibility_t invisible, Item* default_value)
3301{
3302 Create_field *fld= new(thd->mem_root)Create_field();
3303 const char *new_name= NULL;
3304 /* Get unique field name if invisible == INVISIBLE_FULL */
3305 if (invisible == INVISIBLE_FULL)
3306 {
3307 if ((new_name= make_unique_invisible_field_name(thd, field_name,
3308 field_list)))
3309 {
3310 fld->field_name.str= new_name;
3311 fld->field_name.length= strlen(new_name);
3312 }
3313 else
3314 return 1; //Should not happen
3315 }
3316 else
3317 {
3318 fld->field_name.str= thd->strmake(field_name, strlen(field_name));
3319 fld->field_name.length= strlen(field_name);
3320 }
3321 fld->set_handler(type_handler);
3322 fld->invisible= invisible;
3323 if (default_value)
3324 {
3325 Virtual_column_info *v= new (thd->mem_root) Virtual_column_info();
3326 v->expr= default_value;
3327 v->utf8= 0;
3328 fld->default_value= v;
3329 }
3330 field_list->push_front(fld, thd->mem_root);
3331 return 0;
3332}
3333
3334Key *
3335mysql_add_invisible_index(THD *thd, List<Key> *key_list,
3336 LEX_CSTRING* field_name, enum Key::Keytype type)
3337{
3338 Key *key= NULL;
3339 key= new (thd->mem_root) Key(type, &null_clex_str, HA_KEY_ALG_UNDEF,
3340 false, DDL_options(DDL_options::OPT_NONE));
3341 key->columns.push_back(new(thd->mem_root) Key_part_spec(field_name, 0),
3342 thd->mem_root);
3343 key_list->push_back(key, thd->mem_root);
3344 return key;
3345}
3346/*
3347 Preparation for table creation
3348
3349 SYNOPSIS
3350 mysql_prepare_create_table()
3351 thd Thread object.
3352 create_info Create information (like MAX_ROWS).
3353 alter_info List of columns and indexes to create
3354 db_options INOUT Table options (like HA_OPTION_PACK_RECORD).
3355 file The handler for the new table.
3356 key_info_buffer OUT An array of KEY structs for the indexes.
3357 key_count OUT The number of elements in the array.
3358 create_table_mode C_ORDINARY_CREATE, C_ALTER_TABLE,
3359 C_CREATE_SELECT, C_ASSISTED_DISCOVERY
3360
3361 DESCRIPTION
3362 Prepares the table and key structures for table creation.
3363
3364 NOTES
3365 sets create_info->varchar if the table has a varchar
3366
3367 RETURN VALUES
3368 FALSE OK
3369 TRUE error
3370*/
3371
3372static int
3373mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
3374 Alter_info *alter_info, uint *db_options,
3375 handler *file, KEY **key_info_buffer,
3376 uint *key_count, int create_table_mode)
3377{
3378 const char *key_name;
3379 Create_field *sql_field,*dup_field;
3380 uint field,null_fields,max_key_length;
3381 ulong record_offset= 0;
3382 KEY *key_info;
3383 KEY_PART_INFO *key_part_info;
3384 int field_no,dup_no;
3385 int select_field_pos,auto_increment=0;
3386 List_iterator_fast<Create_field> it(alter_info->create_list);
3387 List_iterator<Create_field> it2(alter_info->create_list);
3388 uint total_uneven_bit_length= 0;
3389 int select_field_count= C_CREATE_SELECT(create_table_mode);
3390 bool tmp_table= create_table_mode == C_ALTER_TABLE;
3391 DBUG_ENTER("mysql_prepare_create_table");
3392
3393 DBUG_EXECUTE_IF("test_pseudo_invisible",{
3394 mysql_add_invisible_field(thd, &alter_info->create_list,
3395 "invisible", &type_handler_long, INVISIBLE_SYSTEM,
3396 new (thd->mem_root)Item_int(thd, 9));
3397 });
3398 DBUG_EXECUTE_IF("test_completely_invisible",{
3399 mysql_add_invisible_field(thd, &alter_info->create_list,
3400 "invisible", &type_handler_long, INVISIBLE_FULL,
3401 new (thd->mem_root)Item_int(thd, 9));
3402 });
3403 DBUG_EXECUTE_IF("test_invisible_index",{
3404 LEX_CSTRING temp;
3405 temp.str= "invisible";
3406 temp.length= strlen("invisible");
3407 mysql_add_invisible_index(thd, &alter_info->key_list
3408 , &temp, Key::MULTIPLE);
3409 });
3410 LEX_CSTRING* connect_string = &create_info->connect_string;
3411 if (connect_string->length != 0 &&
3412 connect_string->length > CONNECT_STRING_MAXLEN &&
3413 (system_charset_info->cset->charpos(system_charset_info,
3414 connect_string->str,
3415 (connect_string->str +
3416 connect_string->length),
3417 CONNECT_STRING_MAXLEN)
3418 < connect_string->length))
3419 {
3420 my_error(ER_WRONG_STRING_LENGTH, MYF(0),
3421 connect_string->str, "CONNECTION", CONNECT_STRING_MAXLEN);
3422 DBUG_RETURN(TRUE);
3423 }
3424
3425 select_field_pos= alter_info->create_list.elements - select_field_count;
3426 null_fields= 0;
3427 create_info->varchar= 0;
3428 max_key_length= file->max_key_length();
3429
3430 /* Handle creation of sequences */
3431 if (create_info->sequence)
3432 {
3433 if (!(file->ha_table_flags() & HA_CAN_TABLES_WITHOUT_ROLLBACK))
3434 {
3435 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0), file->table_type(),
3436 "SEQUENCE");
3437 DBUG_RETURN(TRUE);
3438 }
3439
3440 /* The user specified fields: check that structure is ok */
3441 if (check_sequence_fields(thd->lex, &alter_info->create_list))
3442 DBUG_RETURN(TRUE);
3443 }
3444
3445 for (field_no=0; (sql_field=it++) ; field_no++)
3446 {
3447 /*
3448 Initialize length from its original value (number of characters),
3449 which was set in the parser. This is necessary if we're
3450 executing a prepared statement for the second time.
3451 */
3452 sql_field->length= sql_field->char_length;
3453 /* Set field charset. */
3454 sql_field->charset= get_sql_field_charset(sql_field, create_info);
3455 if ((sql_field->flags & BINCMP_FLAG) &&
3456 !(sql_field->charset= find_bin_collation(sql_field->charset)))
3457 DBUG_RETURN(true);
3458
3459 if (sql_field->prepare_stage1(thd, thd->mem_root,
3460 file, file->ha_table_flags()))
3461 DBUG_RETURN(true);
3462
3463 if (sql_field->real_field_type() == MYSQL_TYPE_BIT &&
3464 file->ha_table_flags() & HA_CAN_BIT_FIELD)
3465 total_uneven_bit_length+= sql_field->length & 7;
3466
3467 if (!(sql_field->flags & NOT_NULL_FLAG))
3468 null_fields++;
3469
3470 if (check_column_name(sql_field->field_name.str))
3471 {
3472 my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name.str);
3473 DBUG_RETURN(TRUE);
3474 }
3475
3476 /* Check if we have used the same field name before */
3477 for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
3478 {
3479 if (lex_string_cmp(system_charset_info,
3480 &sql_field->field_name,
3481 &dup_field->field_name) == 0)
3482 {
3483 /*
3484 If this was a CREATE ... SELECT statement, accept a field
3485 redefinition if we are changing a field in the SELECT part
3486 */
3487 if (field_no < select_field_pos || dup_no >= select_field_pos ||
3488 dup_field->invisible >= INVISIBLE_SYSTEM)
3489 {
3490 my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name.str);
3491 DBUG_RETURN(TRUE);
3492 }
3493 else
3494 {
3495 /* Field redefined */
3496
3497 /*
3498 If we are replacing a BIT field, revert the increment
3499 of total_uneven_bit_length that was done above.
3500 */
3501 if (sql_field->real_field_type() == MYSQL_TYPE_BIT &&
3502 file->ha_table_flags() & HA_CAN_BIT_FIELD)
3503 total_uneven_bit_length-= sql_field->length & 7;
3504
3505 /*
3506 We're making one field from two, the result field will have
3507 dup_field->flags as flags. If we've incremented null_fields
3508 because of sql_field->flags, decrement it back.
3509 */
3510 if (!(sql_field->flags & NOT_NULL_FLAG))
3511 null_fields--;
3512
3513 if (sql_field->redefine_stage1(dup_field, file, create_info))
3514 DBUG_RETURN(true);
3515
3516 it2.remove(); // Remove first (create) definition
3517 select_field_pos--;
3518 break;
3519 }
3520 }
3521 }
3522 /* Don't pack rows in old tables if the user has requested this */
3523 if ((sql_field->flags & BLOB_FLAG) ||
3524 (sql_field->real_field_type() == MYSQL_TYPE_VARCHAR &&
3525 create_info->row_type != ROW_TYPE_FIXED))
3526 (*db_options)|= HA_OPTION_PACK_RECORD;
3527 it2.rewind();
3528 }
3529
3530 /* record_offset will be increased with 'length-of-null-bits' later */
3531 record_offset= 0;
3532 null_fields+= total_uneven_bit_length;
3533
3534 it.rewind();
3535 while ((sql_field=it++))
3536 {
3537 DBUG_ASSERT(sql_field->charset != 0);
3538 if (sql_field->prepare_stage2(file, file->ha_table_flags()))
3539 DBUG_RETURN(TRUE);
3540 if (sql_field->real_field_type() == MYSQL_TYPE_VARCHAR)
3541 create_info->varchar= TRUE;
3542 sql_field->offset= record_offset;
3543 if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
3544 auto_increment++;
3545 if (parse_option_list(thd, create_info->db_type, &sql_field->option_struct,
3546 &sql_field->option_list,
3547 create_info->db_type->field_options, FALSE,
3548 thd->mem_root))
3549 DBUG_RETURN(TRUE);
3550 /*
3551 For now skip fields that are not physically stored in the database
3552 (virtual fields) and update their offset later
3553 (see the next loop).
3554 */
3555 if (sql_field->stored_in_db())
3556 record_offset+= sql_field->pack_length;
3557 if (sql_field->flags & VERS_SYSTEM_FIELD)
3558 continue;
3559 }
3560 /* Update virtual fields' offset and give error if
3561 All fields are invisible */
3562 bool is_all_invisible= true;
3563 it.rewind();
3564 while ((sql_field=it++))
3565 {
3566 if (!sql_field->stored_in_db())
3567 {
3568 sql_field->offset= record_offset;
3569 record_offset+= sql_field->pack_length;
3570 }
3571 if (sql_field->invisible == VISIBLE)
3572 is_all_invisible= false;
3573 }
3574 if (is_all_invisible)
3575 {
3576 my_error(ER_TABLE_MUST_HAVE_COLUMNS, MYF(0));
3577 DBUG_RETURN(TRUE);
3578 }
3579 if (auto_increment > 1)
3580 {
3581 my_message(ER_WRONG_AUTO_KEY, ER_THD(thd, ER_WRONG_AUTO_KEY), MYF(0));
3582 DBUG_RETURN(TRUE);
3583 }
3584 if (auto_increment &&
3585 (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
3586 {
3587 my_error(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT, MYF(0), file->table_type());
3588 DBUG_RETURN(TRUE);
3589 }
3590
3591 /*
3592 CREATE TABLE[with auto_increment column] SELECT is unsafe as the rows
3593 inserted in the created table depends on the order of the rows fetched
3594 from the select tables. This order may differ on master and slave. We
3595 therefore mark it as unsafe.
3596 */
3597 if (select_field_count > 0 && auto_increment)
3598 thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_CREATE_SELECT_AUTOINC);
3599
3600 /* Create keys */
3601
3602 List_iterator<Key> key_iterator(alter_info->key_list);
3603 List_iterator<Key> key_iterator2(alter_info->key_list);
3604 uint key_parts=0, fk_key_count=0;
3605 bool primary_key=0,unique_key=0;
3606 Key *key, *key2;
3607 uint tmp, key_number;
3608 /* special marker for keys to be ignored */
3609 static char ignore_key[1];
3610
3611 /* Calculate number of key segements */
3612 *key_count= 0;
3613
3614 while ((key=key_iterator++))
3615 {
3616 DBUG_PRINT("info", ("key name: '%s' type: %d", key->name.str ? key->name.str :
3617 "(none)" , key->type));
3618 if (key->type == Key::FOREIGN_KEY)
3619 {
3620 fk_key_count++;
3621 Foreign_key *fk_key= (Foreign_key*) key;
3622 if (fk_key->validate(alter_info->create_list))
3623 DBUG_RETURN(TRUE);
3624 if (fk_key->ref_columns.elements &&
3625 fk_key->ref_columns.elements != fk_key->columns.elements)
3626 {
3627 my_error(ER_WRONG_FK_DEF, MYF(0),
3628 (fk_key->name.str ? fk_key->name.str :
3629 "foreign key without name"),
3630 ER_THD(thd, ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
3631 DBUG_RETURN(TRUE);
3632 }
3633 continue;
3634 }
3635 (*key_count)++;
3636 tmp=file->max_key_parts();
3637 if (key->columns.elements > tmp)
3638 {
3639 my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
3640 DBUG_RETURN(TRUE);
3641 }
3642 if (check_ident_length(&key->name))
3643 DBUG_RETURN(TRUE);
3644 key_iterator2.rewind ();
3645 if (key->type != Key::FOREIGN_KEY)
3646 {
3647 while ((key2 = key_iterator2++) != key)
3648 {
3649 /*
3650 foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
3651 'generated', and a generated key is a prefix of the other key.
3652 Then we do not need the generated shorter key.
3653 */
3654 if ((key2->type != Key::FOREIGN_KEY &&
3655 key2->name.str != ignore_key &&
3656 !foreign_key_prefix(key, key2)))
3657 {
3658 /* TODO: issue warning message */
3659 /* mark that the generated key should be ignored */
3660 if (!key2->generated ||
3661 (key->generated && key->columns.elements <
3662 key2->columns.elements))
3663 key->name.str= ignore_key;
3664 else
3665 {
3666 key2->name.str= ignore_key;
3667 key_parts-= key2->columns.elements;
3668 (*key_count)--;
3669 }
3670 break;
3671 }
3672 }
3673 }
3674 if (key->name.str != ignore_key)
3675 key_parts+=key->columns.elements;
3676 else
3677 (*key_count)--;
3678 if (key->name.str && !tmp_table && (key->type != Key::PRIMARY) &&
3679 !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
3680 {
3681 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
3682 DBUG_RETURN(TRUE);
3683 }
3684 }
3685 tmp=file->max_keys();
3686 if (*key_count > tmp)
3687 {
3688 my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
3689 DBUG_RETURN(TRUE);
3690 }
3691
3692 (*key_info_buffer)= key_info= (KEY*) thd->calloc(sizeof(KEY) * (*key_count));
3693 key_part_info=(KEY_PART_INFO*) thd->calloc(sizeof(KEY_PART_INFO)*key_parts);
3694 if (!*key_info_buffer || ! key_part_info)
3695 DBUG_RETURN(TRUE); // Out of memory
3696
3697 key_iterator.rewind();
3698 key_number=0;
3699 for (; (key=key_iterator++) ; key_number++)
3700 {
3701 uint key_length=0;
3702 Key_part_spec *column;
3703
3704 if (key->name.str == ignore_key)
3705 {
3706 /* ignore redundant keys */
3707 do
3708 key=key_iterator++;
3709 while (key && key->name.str == ignore_key);
3710 if (!key)
3711 break;
3712 }
3713
3714 switch (key->type) {
3715 case Key::MULTIPLE:
3716 key_info->flags= 0;
3717 break;
3718 case Key::FULLTEXT:
3719 key_info->flags= HA_FULLTEXT;
3720 if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
3721 key_info->flags|= HA_USES_PARSER;
3722 else
3723 key_info->parser_name= 0;
3724 break;
3725 case Key::SPATIAL:
3726#ifdef HAVE_SPATIAL
3727 key_info->flags= HA_SPATIAL;
3728 break;
3729#else
3730 my_error(ER_FEATURE_DISABLED, MYF(0),
3731 sym_group_geom.name, sym_group_geom.needed_define);
3732 DBUG_RETURN(TRUE);
3733#endif
3734 case Key::FOREIGN_KEY:
3735 key_number--; // Skip this key
3736 continue;
3737 default:
3738 key_info->flags = HA_NOSAME;
3739 break;
3740 }
3741 if (key->generated)
3742 key_info->flags|= HA_GENERATED_KEY;
3743
3744 key_info->user_defined_key_parts=(uint8) key->columns.elements;
3745 key_info->key_part=key_part_info;
3746 key_info->usable_key_parts= key_number;
3747 key_info->algorithm= key->key_create_info.algorithm;
3748 key_info->option_list= key->option_list;
3749 if (parse_option_list(thd, create_info->db_type, &key_info->option_struct,
3750 &key_info->option_list,
3751 create_info->db_type->index_options, FALSE,
3752 thd->mem_root))
3753 DBUG_RETURN(TRUE);
3754
3755 if (key->type == Key::FULLTEXT)
3756 {
3757 if (!(file->ha_table_flags() & HA_CAN_FULLTEXT))
3758 {
3759 my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0), file->table_type());
3760 DBUG_RETURN(TRUE);
3761 }
3762 }
3763 /*
3764 Make SPATIAL to be RTREE by default
3765 SPATIAL only on BLOB or at least BINARY, this
3766 actually should be replaced by special GEOM type
3767 in near future when new frm file is ready
3768 checking for proper key parts number:
3769 */
3770
3771 /* TODO: Add proper checks if handler supports key_type and algorithm */
3772 if (key_info->flags & HA_SPATIAL)
3773 {
3774 if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS))
3775 {
3776 my_error(ER_TABLE_CANT_HANDLE_SPKEYS, MYF(0), file->table_type());
3777 DBUG_RETURN(TRUE);
3778 }
3779 if (key_info->user_defined_key_parts != 1)
3780 {
3781 my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
3782 DBUG_RETURN(TRUE);
3783 }
3784 }
3785 else if (key_info->algorithm == HA_KEY_ALG_RTREE)
3786 {
3787#ifdef HAVE_RTREE_KEYS
3788 if ((key_info->user_defined_key_parts & 1) == 1)
3789 {
3790 my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
3791 DBUG_RETURN(TRUE);
3792 }
3793 /* TODO: To be deleted */
3794 my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
3795 DBUG_RETURN(TRUE);
3796#else
3797 my_error(ER_FEATURE_DISABLED, MYF(0),
3798 sym_group_rtree.name, sym_group_rtree.needed_define);
3799 DBUG_RETURN(TRUE);
3800#endif
3801 }
3802
3803 /* Take block size from key part or table part */
3804 /*
3805 TODO: Add warning if block size changes. We can't do it here, as
3806 this may depend on the size of the key
3807 */
3808 key_info->block_size= (key->key_create_info.block_size ?
3809 key->key_create_info.block_size :
3810 create_info->key_block_size);
3811
3812 /*
3813 Remember block_size for the future if the block size was given
3814 either for key or table and it was given for the key during
3815 create/alter table or we have an active key_block_size for the
3816 table.
3817 The idea is that table specific key_block_size > 0 will only affect
3818 new keys and old keys will remember their original value.
3819 */
3820 if (key_info->block_size &&
3821 ((key->key_create_info.flags & HA_USES_BLOCK_SIZE) ||
3822 create_info->key_block_size))
3823 key_info->flags|= HA_USES_BLOCK_SIZE;
3824
3825 List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
3826 CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
3827 for (uint column_nr=0 ; (column=cols++) ; column_nr++)
3828 {
3829 Key_part_spec *dup_column;
3830
3831 it.rewind();
3832 field=0;
3833 while ((sql_field=it++) &&
3834 lex_string_cmp(system_charset_info,
3835 &column->field_name,
3836 &sql_field->field_name))
3837 field++;
3838 /*
3839 Either field is not present or field visibility is > INVISIBLE_USER
3840 */
3841 if (!sql_field)
3842 {
3843 my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
3844 DBUG_RETURN(TRUE);
3845 }
3846 if (sql_field->invisible > INVISIBLE_USER &&
3847 !(sql_field->flags & VERS_SYSTEM_FIELD) &&
3848 !key->invisible && DBUG_EVALUATE_IF("test_invisible_index", 0, 1))
3849 {
3850 my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
3851 DBUG_RETURN(TRUE);
3852 }
3853 while ((dup_column= cols2++) != column)
3854 {
3855 if (!lex_string_cmp(system_charset_info,
3856 &column->field_name, &dup_column->field_name))
3857 {
3858 my_error(ER_DUP_FIELDNAME, MYF(0), column->field_name.str);
3859 DBUG_RETURN(TRUE);
3860 }
3861 }
3862
3863 if (sql_field->compression_method())
3864 {
3865 my_error(ER_COMPRESSED_COLUMN_USED_AS_KEY, MYF(0),
3866 column->field_name.str);
3867 DBUG_RETURN(TRUE);
3868 }
3869
3870 cols2.rewind();
3871 if (key->type == Key::FULLTEXT)
3872 {
3873 if ((sql_field->real_field_type() != MYSQL_TYPE_STRING &&
3874 sql_field->real_field_type() != MYSQL_TYPE_VARCHAR &&
3875 !f_is_blob(sql_field->pack_flag)) ||
3876 sql_field->charset == &my_charset_bin ||
3877 sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
3878 (ft_key_charset && sql_field->charset != ft_key_charset))
3879 {
3880 my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str);
3881 DBUG_RETURN(-1);
3882 }
3883 ft_key_charset=sql_field->charset;
3884 /*
3885 for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
3886 code anyway, and 0 (set to column width later) for char's. it has
3887 to be correct col width for char's, as char data are not prefixed
3888 with length (unlike blobs, where ft code takes data length from a
3889 data prefix, ignoring column->length).
3890 */
3891 column->length= MY_TEST(f_is_blob(sql_field->pack_flag));
3892 }
3893 else
3894 {
3895 column->length*= sql_field->charset->mbmaxlen;
3896
3897 if (key->type == Key::SPATIAL)
3898 {
3899 if (column->length)
3900 {
3901 my_error(ER_WRONG_SUB_KEY, MYF(0));
3902 DBUG_RETURN(TRUE);
3903 }
3904 if (!f_is_geom(sql_field->pack_flag))
3905 {
3906 my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
3907 DBUG_RETURN(TRUE);
3908 }
3909 }
3910
3911 if (f_is_blob(sql_field->pack_flag) ||
3912 (f_is_geom(sql_field->pack_flag) && key->type != Key::SPATIAL))
3913 {
3914 if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
3915 {
3916 my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str,
3917 file->table_type());
3918 DBUG_RETURN(TRUE);
3919 }
3920 if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
3921 Field::GEOM_POINT)
3922 column->length= MAX_LEN_GEOM_POINT_FIELD;
3923 if (!column->length)
3924 {
3925 my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
3926 DBUG_RETURN(TRUE);
3927 }
3928 }
3929#ifdef HAVE_SPATIAL
3930 if (key->type == Key::SPATIAL)
3931 {
3932 if (!column->length)
3933 {
3934 /*
3935 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
3936 Lately we'll extend this code to support more dimensions
3937 */
3938 column->length= 4*sizeof(double);
3939 }
3940 }
3941#endif
3942 if (sql_field->vcol_info)
3943 {
3944 if (key->type == Key::PRIMARY)
3945 {
3946 my_error(ER_PRIMARY_KEY_BASED_ON_GENERATED_COLUMN, MYF(0));
3947 DBUG_RETURN(TRUE);
3948 }
3949 if (sql_field->vcol_info->flags & VCOL_NOT_STRICTLY_DETERMINISTIC)
3950 {
3951 /* use check_expression() to report an error */
3952 check_expression(sql_field->vcol_info, &sql_field->field_name,
3953 VCOL_GENERATED_STORED);
3954 DBUG_ASSERT(thd->is_error());
3955 DBUG_RETURN(TRUE);
3956 }
3957 }
3958 if (!(sql_field->flags & NOT_NULL_FLAG))
3959 {
3960 if (key->type == Key::PRIMARY)
3961 {
3962 /* Implicitly set primary key fields to NOT NULL for ISO conf. */
3963 sql_field->flags|= NOT_NULL_FLAG;
3964 sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
3965 null_fields--;
3966 }
3967 else
3968 {
3969 key_info->flags|= HA_NULL_PART_KEY;
3970 if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
3971 {
3972 my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
3973 DBUG_RETURN(TRUE);
3974 }
3975 if (key->type == Key::SPATIAL)
3976 {
3977 my_message(ER_SPATIAL_CANT_HAVE_NULL,
3978 ER_THD(thd, ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
3979 DBUG_RETURN(TRUE);
3980 }
3981 }
3982 }
3983 if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
3984 {
3985 if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
3986 auto_increment--; // Field is used
3987 }
3988 }
3989
3990 key_part_info->fieldnr= field;
3991 key_part_info->offset= (uint16) sql_field->offset;
3992 key_part_info->key_type=sql_field->pack_flag;
3993 uint key_part_length= sql_field->key_length;
3994
3995 if (column->length)
3996 {
3997 if (f_is_blob(sql_field->pack_flag))
3998 {
3999 key_part_length= MY_MIN(column->length,
4000 blob_length_by_type(sql_field->real_field_type())
4001 * sql_field->charset->mbmaxlen);
4002 if (key_part_length > max_key_length ||
4003 key_part_length > file->max_key_part_length())
4004 {
4005 key_part_length= MY_MIN(max_key_length, file->max_key_part_length());
4006 if (key->type == Key::MULTIPLE)
4007 {
4008 /* not a critical problem */
4009 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
4010 ER_TOO_LONG_KEY,
4011 ER_THD(thd, ER_TOO_LONG_KEY),
4012 key_part_length);
4013 /* Align key length to multibyte char boundary */
4014 key_part_length-= key_part_length % sql_field->charset->mbmaxlen;
4015 }
4016 else
4017 {
4018 my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
4019 DBUG_RETURN(TRUE);
4020 }
4021 }
4022 }
4023 // Catch invalid use of partial keys
4024 else if (!f_is_geom(sql_field->pack_flag) &&
4025 // is the key partial?
4026 column->length != key_part_length &&
4027 // is prefix length bigger than field length?
4028 (column->length > key_part_length ||
4029 // can the field have a partial key?
4030 !sql_field->type_handler()->type_can_have_key_part() ||
4031 // a packed field can't be used in a partial key
4032 f_is_packed(sql_field->pack_flag) ||
4033 // does the storage engine allow prefixed search?
4034 ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
4035 // and is this a 'unique' key?
4036 (key_info->flags & HA_NOSAME))))
4037 {
4038 my_message(ER_WRONG_SUB_KEY, ER_THD(thd, ER_WRONG_SUB_KEY), MYF(0));
4039 DBUG_RETURN(TRUE);
4040 }
4041 else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
4042 key_part_length= column->length;
4043 }
4044 else if (key_part_length == 0 && (sql_field->flags & NOT_NULL_FLAG))
4045 {
4046 my_error(ER_WRONG_KEY_COLUMN, MYF(0), file->table_type(),
4047 column->field_name.str);
4048 DBUG_RETURN(TRUE);
4049 }
4050 if (key_part_length > file->max_key_part_length() &&
4051 key->type != Key::FULLTEXT)
4052 {
4053 key_part_length= file->max_key_part_length();
4054 if (key->type == Key::MULTIPLE)
4055 {
4056 /* not a critical problem */
4057 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
4058 ER_TOO_LONG_KEY, ER_THD(thd, ER_TOO_LONG_KEY),
4059 key_part_length);
4060 /* Align key length to multibyte char boundary */
4061 key_part_length-= key_part_length % sql_field->charset->mbmaxlen;
4062 }
4063 else
4064 {
4065 my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
4066 DBUG_RETURN(TRUE);
4067 }
4068 }
4069 key_part_info->length= (uint16) key_part_length;
4070 /* Use packed keys for long strings on the first column */
4071 if (!((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
4072 !((create_info->table_options & HA_OPTION_NO_PACK_KEYS)) &&
4073 (key_part_length >= KEY_DEFAULT_PACK_LENGTH &&
4074 (sql_field->real_field_type() == MYSQL_TYPE_STRING ||
4075 sql_field->real_field_type() == MYSQL_TYPE_VARCHAR ||
4076 sql_field->pack_flag & FIELDFLAG_BLOB)))
4077 {
4078 if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
4079 sql_field->real_field_type() == MYSQL_TYPE_VARCHAR)
4080 key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
4081 else
4082 key_info->flags|= HA_PACK_KEY;
4083 }
4084 /* Check if the key segment is partial, set the key flag accordingly */
4085 if (key_part_length != sql_field->key_length)
4086 key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
4087
4088 key_length+= key_part_length;
4089 key_part_info++;
4090
4091 /* Create the key name based on the first column (if not given) */
4092 if (column_nr == 0)
4093 {
4094 if (key->type == Key::PRIMARY)
4095 {
4096 if (primary_key)
4097 {
4098 my_message(ER_MULTIPLE_PRI_KEY, ER_THD(thd, ER_MULTIPLE_PRI_KEY),
4099 MYF(0));
4100 DBUG_RETURN(TRUE);
4101 }
4102 key_name=primary_key_name;
4103 primary_key=1;
4104 }
4105 else if (!(key_name= key->name.str))
4106 key_name=make_unique_key_name(thd, sql_field->field_name.str,
4107 *key_info_buffer, key_info);
4108 if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
4109 {
4110 my_error(ER_DUP_KEYNAME, MYF(0), key_name);
4111 DBUG_RETURN(TRUE);
4112 }
4113 key_info->name.str= (char*) key_name;
4114 key_info->name.length= strlen(key_name);
4115 }
4116 }
4117 if (!key_info->name.str || check_column_name(key_info->name.str))
4118 {
4119 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name.str);
4120 DBUG_RETURN(TRUE);
4121 }
4122 if (key->type == Key::UNIQUE && !(key_info->flags & HA_NULL_PART_KEY))
4123 unique_key=1;
4124 key_info->key_length=(uint16) key_length;
4125 if (key_length > max_key_length && key->type != Key::FULLTEXT)
4126 {
4127 my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
4128 DBUG_RETURN(TRUE);
4129 }
4130
4131 if (validate_comment_length(thd, &key->key_create_info.comment,
4132 INDEX_COMMENT_MAXLEN,
4133 ER_TOO_LONG_INDEX_COMMENT,
4134 key_info->name.str))
4135 DBUG_RETURN(TRUE);
4136
4137 key_info->comment.length= key->key_create_info.comment.length;
4138 if (key_info->comment.length > 0)
4139 {
4140 key_info->flags|= HA_USES_COMMENT;
4141 key_info->comment.str= key->key_create_info.comment.str;
4142 }
4143
4144 // Check if a duplicate index is defined.
4145 check_duplicate_key(thd, key, key_info, &alter_info->key_list);
4146
4147 key_info++;
4148 }
4149
4150 if (!unique_key && !primary_key &&
4151 (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
4152 {
4153 my_message(ER_REQUIRES_PRIMARY_KEY, ER_THD(thd, ER_REQUIRES_PRIMARY_KEY),
4154 MYF(0));
4155 DBUG_RETURN(TRUE);
4156 }
4157 if (auto_increment > 0)
4158 {
4159 my_message(ER_WRONG_AUTO_KEY, ER_THD(thd, ER_WRONG_AUTO_KEY), MYF(0));
4160 DBUG_RETURN(TRUE);
4161 }
4162 /* Sort keys in optimized order */
4163 my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
4164 (qsort_cmp) sort_keys);
4165 create_info->null_bits= null_fields;
4166
4167 /* Check fields. */
4168 it.rewind();
4169 while ((sql_field=it++))
4170 {
4171 Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
4172
4173 /*
4174 Set NO_DEFAULT_VALUE_FLAG if this field doesn't have a default value and
4175 it is NOT NULL, not an AUTO_INCREMENT field, not a TIMESTAMP and not
4176 updated trough a NOW() function.
4177 */
4178 if (!sql_field->default_value &&
4179 !sql_field->has_default_function() &&
4180 (sql_field->flags & NOT_NULL_FLAG) &&
4181 (!sql_field->is_timestamp_type() ||
4182 opt_explicit_defaults_for_timestamp)&&
4183 !sql_field->vers_sys_field())
4184 {
4185 sql_field->flags|= NO_DEFAULT_VALUE_FLAG;
4186 sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
4187 }
4188
4189 if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
4190 !sql_field->default_value && !sql_field->vcol_info &&
4191 sql_field->is_timestamp_type() &&
4192 !opt_explicit_defaults_for_timestamp &&
4193 (sql_field->flags & NOT_NULL_FLAG) &&
4194 (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
4195 {
4196 /*
4197 An error should be reported if:
4198 - NO_ZERO_DATE SQL mode is active;
4199 - there is no explicit DEFAULT clause (default column value);
4200 - this is a TIMESTAMP column;
4201 - the column is not NULL;
4202 - this is not the DEFAULT CURRENT_TIMESTAMP column.
4203
4204 In other words, an error should be reported if
4205 - NO_ZERO_DATE SQL mode is active;
4206 - the column definition is equivalent to
4207 'column_name TIMESTAMP DEFAULT 0'.
4208 */
4209
4210 my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name.str);
4211 DBUG_RETURN(TRUE);
4212 }
4213 if (sql_field->invisible == INVISIBLE_USER &&
4214 sql_field->flags & NOT_NULL_FLAG &&
4215 sql_field->flags & NO_DEFAULT_VALUE_FLAG)
4216 {
4217 my_error(ER_INVISIBLE_NOT_NULL_WITHOUT_DEFAULT, MYF(0),
4218 sql_field->field_name.str);
4219 DBUG_RETURN(TRUE);
4220 }
4221 }
4222
4223 /* Check table level constraints */
4224 create_info->check_constraint_list= &alter_info->check_constraint_list;
4225 {
4226 uint nr= 1;
4227 List_iterator_fast<Virtual_column_info> c_it(alter_info->check_constraint_list);
4228 Virtual_column_info *check;
4229 while ((check= c_it++))
4230 {
4231 if (!check->name.length)
4232 make_unique_constraint_name(thd, &check->name,
4233 &alter_info->check_constraint_list,
4234 &nr);
4235 {
4236 /* Check that there's no repeating constraint names. */
4237 List_iterator_fast<Virtual_column_info>
4238 dup_it(alter_info->check_constraint_list);
4239 Virtual_column_info *dup_check;
4240 while ((dup_check= dup_it++) && dup_check != check)
4241 {
4242 if (!lex_string_cmp(system_charset_info,
4243 &check->name, &dup_check->name))
4244 {
4245 my_error(ER_DUP_CONSTRAINT_NAME, MYF(0), "CHECK", check->name.str);
4246 DBUG_RETURN(TRUE);
4247 }
4248 }
4249 }
4250
4251 if (check_string_char_length(&check->name, 0, NAME_CHAR_LEN,
4252 system_charset_info, 1))
4253 {
4254 my_error(ER_TOO_LONG_IDENT, MYF(0), check->name.str);
4255 DBUG_RETURN(TRUE);
4256 }
4257 if (check_expression(check, &check->name, VCOL_CHECK_TABLE))
4258 DBUG_RETURN(TRUE);
4259 }
4260 }
4261
4262 /* Give warnings for not supported table options */
4263#if defined(WITH_ARIA_STORAGE_ENGINE)
4264 extern handlerton *maria_hton;
4265 if (file->partition_ht() != maria_hton)
4266#endif
4267 if (create_info->transactional)
4268 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
4269 ER_ILLEGAL_HA_CREATE_OPTION,
4270 ER_THD(thd, ER_ILLEGAL_HA_CREATE_OPTION),
4271 file->engine_name()->str,
4272 "TRANSACTIONAL=1");
4273
4274 if (parse_option_list(thd, file->partition_ht(), &create_info->option_struct,
4275 &create_info->option_list,
4276 file->partition_ht()->table_options, FALSE,
4277 thd->mem_root))
4278 DBUG_RETURN(TRUE);
4279
4280 DBUG_RETURN(FALSE);
4281}
4282
4283/**
4284 check comment length of table, column, index and partition
4285
4286 If comment lenght is more than the standard length
4287 truncate it and store the comment lenght upto the standard
4288 comment length size
4289
4290 @param thd Thread handle
4291 @param[in,out] comment Comment
4292 @param max_len Maximum allowed comment length
4293 @param err_code Error message
4294 @param name Name of commented object
4295
4296 @return Operation status
4297 @retval true Error found
4298 @retval false On Success
4299*/
4300bool validate_comment_length(THD *thd, LEX_CSTRING *comment, size_t max_len,
4301 uint err_code, const char *name)
4302{
4303 DBUG_ENTER("validate_comment_length");
4304 size_t tmp_len= my_charpos(system_charset_info, comment->str,
4305 comment->str + comment->length, max_len);
4306 if (tmp_len < comment->length)
4307 {
4308 if (thd->is_strict_mode())
4309 {
4310 my_error(err_code, MYF(0), name, static_cast<ulong>(max_len));
4311 DBUG_RETURN(true);
4312 }
4313 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN, err_code,
4314 ER_THD(thd, err_code), name,
4315 static_cast<ulong>(max_len));
4316 comment->length= tmp_len;
4317 }
4318 DBUG_RETURN(false);
4319}
4320
4321
4322/*
4323 Set table default charset, if not set
4324
4325 SYNOPSIS
4326 set_table_default_charset()
4327 create_info Table create information
4328
4329 DESCRIPTION
4330 If the table character set was not given explicitly,
4331 let's fetch the database default character set and
4332 apply it to the table.
4333*/
4334
4335static void set_table_default_charset(THD *thd,
4336 HA_CREATE_INFO *create_info,
4337 const LEX_CSTRING *db)
4338{
4339 /*
4340 If the table character set was not given explicitly,
4341 let's fetch the database default character set and
4342 apply it to the table.
4343 */
4344 if (!create_info->default_table_charset)
4345 {
4346 Schema_specification_st db_info;
4347
4348 load_db_opt_by_name(thd, db->str, &db_info);
4349
4350 create_info->default_table_charset= db_info.default_table_charset;
4351 }
4352}
4353
4354
4355/*
4356 Extend long VARCHAR fields to blob & prepare field if it's a blob
4357
4358 SYNOPSIS
4359 prepare_blob_field()
4360
4361 RETURN
4362 0 ok
4363 1 Error (sql_field can't be converted to blob)
4364 In this case the error is given
4365*/
4366
4367bool Column_definition::prepare_blob_field(THD *thd)
4368{
4369 DBUG_ENTER("Column_definition::prepare_blob_field");
4370
4371 if (length > MAX_FIELD_VARCHARLENGTH && !(flags & BLOB_FLAG))
4372 {
4373 /* Convert long VARCHAR columns to TEXT or BLOB */
4374 char warn_buff[MYSQL_ERRMSG_SIZE];
4375
4376 if (thd->is_strict_mode())
4377 {
4378 my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name.str,
4379 static_cast<ulong>(MAX_FIELD_VARCHARLENGTH / charset->mbmaxlen));
4380 DBUG_RETURN(1);
4381 }
4382 set_handler(&type_handler_blob);
4383 flags|= BLOB_FLAG;
4384 my_snprintf(warn_buff, sizeof(warn_buff), ER_THD(thd, ER_AUTO_CONVERT),
4385 field_name.str,
4386 (charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
4387 (charset == &my_charset_bin) ? "BLOB" : "TEXT");
4388 push_warning(thd, Sql_condition::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
4389 warn_buff);
4390 }
4391
4392 if ((flags & BLOB_FLAG) && length)
4393 {
4394 if (real_field_type() == FIELD_TYPE_BLOB ||
4395 real_field_type() == FIELD_TYPE_TINY_BLOB ||
4396 real_field_type() == FIELD_TYPE_MEDIUM_BLOB)
4397 {
4398 /* The user has given a length to the blob column */
4399 set_handler(Type_handler::blob_type_handler((uint) length));
4400 pack_length= type_handler()->calc_pack_length(0);
4401 }
4402 length= 0;
4403 }
4404 DBUG_RETURN(0);
4405}
4406
4407
4408/*
4409 Preparation of Create_field for SP function return values.
4410 Based on code used in the inner loop of mysql_prepare_create_table()
4411 above.
4412
4413 SYNOPSIS
4414 sp_prepare_create_field()
4415 thd Thread object
4416 mem_root Memory root to allocate components on (e.g. interval)
4417
4418 DESCRIPTION
4419 Prepares the field structures for field creation.
4420
4421*/
4422
4423bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root)
4424{
4425 return prepare_stage1(thd, mem_root, NULL, HA_CAN_GEOMETRY) ||
4426 prepare_stage2(NULL, HA_CAN_GEOMETRY);
4427}
4428
4429
4430static bool vers_prepare_keys(THD *thd, HA_CREATE_INFO *create_info,
4431 Alter_info *alter_info, KEY **key_info, uint key_count)
4432{
4433 DBUG_ASSERT(create_info->versioned());
4434
4435 const char *row_start_field= create_info->vers_info.as_row.start;
4436 DBUG_ASSERT(row_start_field);
4437 const char *row_end_field= create_info->vers_info.as_row.end;
4438 DBUG_ASSERT(row_end_field);
4439
4440 List_iterator<Key> key_it(alter_info->key_list);
4441 Key *key= NULL;
4442 while ((key=key_it++))
4443 {
4444 if (key->type != Key::PRIMARY && key->type != Key::UNIQUE)
4445 continue;
4446
4447 Key_part_spec *key_part= NULL;
4448 List_iterator<Key_part_spec> part_it(key->columns);
4449 while ((key_part=part_it++))
4450 {
4451 if (!my_strcasecmp(system_charset_info,
4452 row_start_field,
4453 key_part->field_name.str) ||
4454
4455 !my_strcasecmp(system_charset_info,
4456 row_end_field,
4457 key_part->field_name.str))
4458 break;
4459 }
4460 if (key_part)
4461 continue; // Key already contains Sys_start or Sys_end
4462
4463 Key_part_spec *key_part_sys_end_col=
4464 new (thd->mem_root) Key_part_spec(&create_info->vers_info.as_row.end, 0);
4465 key->columns.push_back(key_part_sys_end_col);
4466 }
4467
4468 return false;
4469}
4470
4471handler *mysql_create_frm_image(THD *thd,
4472 const LEX_CSTRING *db, const LEX_CSTRING *table_name,
4473 HA_CREATE_INFO *create_info,
4474 Alter_info *alter_info, int create_table_mode,
4475 KEY **key_info,
4476 uint *key_count,
4477 LEX_CUSTRING *frm)
4478{
4479 uint db_options;
4480 handler *file;
4481 DBUG_ENTER("mysql_create_frm_image");
4482
4483 if (!alter_info->create_list.elements)
4484 {
4485 my_error(ER_TABLE_MUST_HAVE_COLUMNS, MYF(0));
4486 DBUG_RETURN(NULL);
4487 }
4488
4489 set_table_default_charset(thd, create_info, db);
4490
4491 db_options= create_info->table_options_with_row_type();
4492
4493 if (unlikely(!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
4494 create_info->db_type))))
4495 DBUG_RETURN(NULL);
4496
4497#ifdef WITH_PARTITION_STORAGE_ENGINE
4498 partition_info *part_info= thd->work_part_info;
4499
4500 if (!part_info && create_info->db_type->partition_flags &&
4501 (create_info->db_type->partition_flags() & HA_USE_AUTO_PARTITION))
4502 {
4503 /*
4504 Table is not defined as a partitioned table but the engine handles
4505 all tables as partitioned. The handler will set up the partition info
4506 object with the default settings.
4507 */
4508 thd->work_part_info= part_info= new partition_info();
4509 if (unlikely(!part_info))
4510 goto err;
4511
4512 file->set_auto_partitions(part_info);
4513 part_info->default_engine_type= create_info->db_type;
4514 part_info->is_auto_partitioned= TRUE;
4515 }
4516 if (part_info)
4517 {
4518 /*
4519 The table has been specified as a partitioned table.
4520 If this is part of an ALTER TABLE the handler will be the partition
4521 handler but we need to specify the default handler to use for
4522 partitions also in the call to check_partition_info. We transport
4523 this information in the default_db_type variable, it is either
4524 DB_TYPE_DEFAULT or the engine set in the ALTER TABLE command.
4525 */
4526 handlerton *part_engine_type= create_info->db_type;
4527 char *part_syntax_buf;
4528 uint syntax_len;
4529 handlerton *engine_type;
4530 List_iterator<partition_element> part_it(part_info->partitions);
4531 partition_element *part_elem;
4532
4533 while ((part_elem= part_it++))
4534 {
4535 if (part_elem->part_comment)
4536 {
4537 LEX_CSTRING comment= { part_elem->part_comment,
4538 strlen(part_elem->part_comment)
4539 };
4540 if (validate_comment_length(thd, &comment,
4541 TABLE_PARTITION_COMMENT_MAXLEN,
4542 ER_TOO_LONG_TABLE_PARTITION_COMMENT,
4543 part_elem->partition_name))
4544 DBUG_RETURN(NULL);
4545 /* cut comment length. Safe to do in all cases */
4546 ((char*)part_elem->part_comment)[comment.length]= '\0';
4547 }
4548 if (part_elem->subpartitions.elements)
4549 {
4550 List_iterator<partition_element> sub_it(part_elem->subpartitions);
4551 partition_element *subpart_elem;
4552 while ((subpart_elem= sub_it++))
4553 {
4554 if (subpart_elem->part_comment)
4555 {
4556 LEX_CSTRING comment= {
4557 subpart_elem->part_comment, strlen(subpart_elem->part_comment)
4558 };
4559 if (validate_comment_length(thd, &comment,
4560 TABLE_PARTITION_COMMENT_MAXLEN,
4561 ER_TOO_LONG_TABLE_PARTITION_COMMENT,
4562 subpart_elem->partition_name))
4563 DBUG_RETURN(NULL);
4564 /* cut comment length. Safe to do in all cases */
4565 ((char*)subpart_elem->part_comment)[comment.length]= '\0';
4566 }
4567 }
4568 }
4569 }
4570
4571 if (create_info->tmp_table())
4572 {
4573 my_error(ER_PARTITION_NO_TEMPORARY, MYF(0));
4574 goto err;
4575 }
4576 if ((part_engine_type == partition_hton) &&
4577 part_info->default_engine_type)
4578 {
4579 /*
4580 This only happens at ALTER TABLE.
4581 default_engine_type was assigned from the engine set in the ALTER
4582 TABLE command.
4583 */
4584 ;
4585 }
4586 else
4587 {
4588 if (create_info->used_fields & HA_CREATE_USED_ENGINE)
4589 {
4590 part_info->default_engine_type= create_info->db_type;
4591 }
4592 else
4593 {
4594 if (part_info->default_engine_type == NULL)
4595 {
4596 part_info->default_engine_type= ha_default_handlerton(thd);
4597 }
4598 }
4599 }
4600 DBUG_PRINT("info", ("db_type = %s create_info->db_type = %s",
4601 ha_resolve_storage_engine_name(part_info->default_engine_type),
4602 ha_resolve_storage_engine_name(create_info->db_type)));
4603 if (part_info->check_partition_info(thd, &engine_type, file,
4604 create_info, FALSE))
4605 goto err;
4606 part_info->default_engine_type= engine_type;
4607
4608 if (part_info->vers_info && !create_info->versioned())
4609 {
4610 my_error(ER_VERS_NOT_VERSIONED, MYF(0), table_name->str);
4611 goto err;
4612 }
4613
4614 /*
4615 We reverse the partitioning parser and generate a standard format
4616 for syntax stored in frm file.
4617 */
4618 sql_mode_t old_mode= thd->variables.sql_mode;
4619 thd->variables.sql_mode &= ~MODE_ANSI_QUOTES;
4620 part_syntax_buf= generate_partition_syntax(thd, part_info, &syntax_len,
4621 true, create_info, alter_info);
4622 thd->variables.sql_mode= old_mode;
4623 if (!part_syntax_buf)
4624 goto err;
4625 part_info->part_info_string= part_syntax_buf;
4626 part_info->part_info_len= syntax_len;
4627 if ((!(engine_type->partition_flags &&
4628 ((engine_type->partition_flags() & HA_CAN_PARTITION) ||
4629 (part_info->part_type == VERSIONING_PARTITION &&
4630 engine_type->partition_flags() & HA_ONLY_VERS_PARTITION))
4631 )) ||
4632 create_info->db_type == partition_hton)
4633 {
4634 /*
4635 The handler assigned to the table cannot handle partitioning.
4636 Assign the partition handler as the handler of the table.
4637 */
4638 DBUG_PRINT("info", ("db_type: %s",
4639 ha_resolve_storage_engine_name(create_info->db_type)));
4640 delete file;
4641 create_info->db_type= partition_hton;
4642 if (!(file= get_ha_partition(part_info)))
4643 DBUG_RETURN(NULL);
4644
4645 /*
4646 If we have default number of partitions or subpartitions we
4647 might require to set-up the part_info object such that it
4648 creates a proper .par file. The current part_info object is
4649 only used to create the frm-file and .par-file.
4650 */
4651 if (part_info->use_default_num_partitions &&
4652 part_info->num_parts &&
4653 (int)part_info->num_parts !=
4654 file->get_default_no_partitions(create_info))
4655 {
4656 uint i;
4657 List_iterator<partition_element> part_it(part_info->partitions);
4658 part_it++;
4659 DBUG_ASSERT(thd->lex->sql_command != SQLCOM_CREATE_TABLE);
4660 for (i= 1; i < part_info->partitions.elements; i++)
4661 (part_it++)->part_state= PART_TO_BE_DROPPED;
4662 }
4663 else if (part_info->is_sub_partitioned() &&
4664 part_info->use_default_num_subpartitions &&
4665 part_info->num_subparts &&
4666 (int)part_info->num_subparts !=
4667 file->get_default_no_partitions(create_info))
4668 {
4669 DBUG_ASSERT(thd->lex->sql_command != SQLCOM_CREATE_TABLE);
4670 part_info->num_subparts= file->get_default_no_partitions(create_info);
4671 }
4672 }
4673 else if (create_info->db_type != engine_type)
4674 {
4675 /*
4676 We come here when we don't use a partitioned handler.
4677 Since we use a partitioned table it must be "native partitioned".
4678 We have switched engine from defaults, most likely only specified
4679 engines in partition clauses.
4680 */
4681 delete file;
4682 if (unlikely(!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
4683 engine_type))))
4684 DBUG_RETURN(NULL);
4685 }
4686 }
4687 /*
4688 Unless table's storage engine supports partitioning natively
4689 don't allow foreign keys on partitioned tables (they won't
4690 work work even with InnoDB beneath of partitioning engine).
4691 If storage engine handles partitioning natively (like NDB)
4692 foreign keys support is possible, so we let the engine decide.
4693 */
4694 if (create_info->db_type == partition_hton)
4695 {
4696 List_iterator_fast<Key> key_iterator(alter_info->key_list);
4697 Key *key;
4698 while ((key= key_iterator++))
4699 {
4700 if (key->type == Key::FOREIGN_KEY)
4701 {
4702 my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
4703 goto err;
4704 }
4705 }
4706 }
4707#endif
4708
4709 if (create_info->versioned())
4710 {
4711 if(vers_prepare_keys(thd, create_info, alter_info, key_info,
4712 *key_count))
4713 goto err;
4714 }
4715
4716 if (mysql_prepare_create_table(thd, create_info, alter_info, &db_options,
4717 file, key_info, key_count,
4718 create_table_mode))
4719 goto err;
4720 create_info->table_options=db_options;
4721
4722 *frm= build_frm_image(thd, table_name, create_info,
4723 alter_info->create_list, *key_count,
4724 *key_info, file);
4725
4726 if (frm->str)
4727 DBUG_RETURN(file);
4728
4729err:
4730 delete file;
4731 DBUG_RETURN(NULL);
4732}
4733
4734
4735/**
4736 Create a table
4737
4738 @param thd Thread object
4739 @param orig_db Database for error messages
4740 @param orig_table_name Table name for error messages
4741 (it's different from table_name for ALTER TABLE)
4742 @param db Database
4743 @param table_name Table name
4744 @param path Path to table (i.e. to its .FRM file without
4745 the extension).
4746 @param create_info Create information (like MAX_ROWS)
4747 @param alter_info Description of fields and keys for new table
4748 @param create_table_mode C_ORDINARY_CREATE, C_ALTER_TABLE, C_ASSISTED_DISCOVERY
4749 or any positive number (for C_CREATE_SELECT).
4750 @param[out] is_trans Identifies the type of engine where the table
4751 was created: either trans or non-trans.
4752 @param[out] key_info Array of KEY objects describing keys in table
4753 which was created.
4754 @param[out] key_count Number of keys in table which was created.
4755
4756 If one creates a temporary table, its is automatically opened and its
4757 TABLE_SHARE is added to THD::all_temp_tables list.
4758
4759 Note that this function assumes that caller already have taken
4760 exclusive metadata lock on table being created or used some other
4761 way to ensure that concurrent operations won't intervene.
4762 mysql_create_table() is a wrapper that can be used for this.
4763
4764 @retval 0 OK
4765 @retval 1 error
4766 @retval -1 table existed but IF EXISTS was used
4767*/
4768
4769static
4770int create_table_impl(THD *thd,
4771 const LEX_CSTRING *orig_db,
4772 const LEX_CSTRING *orig_table_name,
4773 const LEX_CSTRING *db, const LEX_CSTRING *table_name,
4774 const char *path,
4775 const DDL_options_st options,
4776 HA_CREATE_INFO *create_info,
4777 Alter_info *alter_info,
4778 int create_table_mode,
4779 bool *is_trans,
4780 KEY **key_info,
4781 uint *key_count,
4782 LEX_CUSTRING *frm)
4783{
4784 LEX_CSTRING *alias;
4785 handler *file= 0;
4786 int error= 1;
4787 bool frm_only= create_table_mode == C_ALTER_TABLE_FRM_ONLY;
4788 bool internal_tmp_table= create_table_mode == C_ALTER_TABLE || frm_only;
4789 DBUG_ENTER("mysql_create_table_no_lock");
4790 DBUG_PRINT("enter", ("db: '%s' table: '%s' tmp: %d path: %s",
4791 db->str, table_name->str, internal_tmp_table, path));
4792
4793 if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)
4794 {
4795 if (create_info->data_file_name)
4796 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
4797 WARN_OPTION_IGNORED,
4798 ER_THD(thd, WARN_OPTION_IGNORED),
4799 "DATA DIRECTORY");
4800 if (create_info->index_file_name)
4801 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
4802 WARN_OPTION_IGNORED,
4803 ER_THD(thd, WARN_OPTION_IGNORED),
4804 "INDEX DIRECTORY");
4805 create_info->data_file_name= create_info->index_file_name= 0;
4806 }
4807 else
4808 {
4809 if (unlikely(error_if_data_home_dir(create_info->data_file_name,
4810 "DATA DIRECTORY")) ||
4811 unlikely(error_if_data_home_dir(create_info->index_file_name,
4812 "INDEX DIRECTORY")) ||
4813 unlikely(check_partition_dirs(thd->lex->part_info)))
4814 goto err;
4815 }
4816
4817 alias= const_cast<LEX_CSTRING*>(table_case_name(create_info, table_name));
4818
4819 /* Check if table exists */
4820 if (create_info->tmp_table())
4821 {
4822 /*
4823 If a table exists, it must have been pre-opened. Try looking for one
4824 in-use in THD::all_temp_tables list of TABLE_SHAREs.
4825 */
4826 TABLE *tmp_table= thd->find_temporary_table(db->str, table_name->str);
4827
4828 if (tmp_table)
4829 {
4830 bool table_creation_was_logged= tmp_table->s->table_creation_was_logged;
4831 if (options.or_replace())
4832 {
4833 /*
4834 We are using CREATE OR REPLACE on an existing temporary table
4835 Remove the old table so that we can re-create it.
4836 */
4837 if (thd->drop_temporary_table(tmp_table, NULL, true))
4838 goto err;
4839 }
4840 else if (options.if_not_exists())
4841 goto warn;
4842 else
4843 {
4844 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias->str);
4845 goto err;
4846 }
4847 /*
4848 We have to log this query, even if it failed later to ensure the
4849 drop is done.
4850 */
4851 if (table_creation_was_logged)
4852 {
4853 thd->variables.option_bits|= OPTION_KEEP_LOG;
4854 thd->log_current_statement= 1;
4855 create_info->table_was_deleted= 1;
4856 }
4857 }
4858 }
4859 else
4860 {
4861 if (!internal_tmp_table && ha_table_exists(thd, db, table_name))
4862 {
4863 if (options.or_replace())
4864 {
4865 TABLE_LIST table_list;
4866 table_list.init_one_table(db, table_name, 0, TL_WRITE_ALLOW_WRITE);
4867 table_list.table= create_info->table;
4868
4869 if (check_if_log_table(&table_list, TRUE, "CREATE OR REPLACE"))
4870 goto err;
4871
4872 /*
4873 Rollback the empty transaction started in mysql_create_table()
4874 call to open_and_lock_tables() when we are using LOCK TABLES.
4875 */
4876 (void) trans_rollback_stmt(thd);
4877 /* Remove normal table without logging. Keep tables locked */
4878 if (mysql_rm_table_no_locks(thd, &table_list, 0, 0, 0, 0, 1, 1))
4879 goto err;
4880
4881 /*
4882 We have to log this query, even if it failed later to ensure the
4883 drop is done.
4884 */
4885 thd->variables.option_bits|= OPTION_KEEP_LOG;
4886 thd->log_current_statement= 1;
4887 create_info->table_was_deleted= 1;
4888 DBUG_EXECUTE_IF("send_kill_after_delete", thd->set_killed(KILL_QUERY); );
4889
4890 /*
4891 Restart statement transactions for the case of CREATE ... SELECT.
4892 */
4893 if (thd->lex->select_lex.item_list.elements &&
4894 restart_trans_for_tables(thd, thd->lex->query_tables))
4895 goto err;
4896 }
4897 else if (options.if_not_exists())
4898 goto warn;
4899 else
4900 {
4901 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name->str);
4902 goto err;
4903 }
4904 }
4905 }
4906
4907 THD_STAGE_INFO(thd, stage_creating_table);
4908
4909 if (check_engine(thd, orig_db->str, orig_table_name->str, create_info))
4910 goto err;
4911
4912 if (create_table_mode == C_ASSISTED_DISCOVERY)
4913 {
4914 /* check that it's used correctly */
4915 DBUG_ASSERT(alter_info->create_list.elements == 0);
4916 DBUG_ASSERT(alter_info->key_list.elements == 0);
4917
4918 TABLE_SHARE share;
4919 handlerton *hton= create_info->db_type;
4920 int ha_err;
4921 Field *no_fields= 0;
4922
4923 if (!hton->discover_table_structure)
4924 {
4925 my_error(ER_TABLE_MUST_HAVE_COLUMNS, MYF(0));
4926 goto err;
4927 }
4928
4929 init_tmp_table_share(thd, &share, db->str, 0, table_name->str, path);
4930
4931 /* prepare everything for discovery */
4932 share.field= &no_fields;
4933 share.db_plugin= ha_lock_engine(thd, hton);
4934 share.option_list= create_info->option_list;
4935 share.connect_string= create_info->connect_string;
4936
4937 if (parse_engine_table_options(thd, hton, &share))
4938 goto err;
4939
4940 ha_err= hton->discover_table_structure(hton, thd, &share, create_info);
4941
4942 /*
4943 if discovery failed, the plugin will be auto-unlocked, as it
4944 was locked on the THD, see above.
4945 if discovery succeeded, the plugin was replaced by a globally
4946 locked plugin, that will be unlocked by free_table_share()
4947 */
4948 if (ha_err)
4949 share.db_plugin= 0; // will be auto-freed, locked above on the THD
4950
4951 free_table_share(&share);
4952
4953 if (ha_err)
4954 {
4955 my_error(ER_GET_ERRNO, MYF(0), ha_err, hton_name(hton)->str);
4956 goto err;
4957 }
4958 }
4959 else
4960 {
4961 file= mysql_create_frm_image(thd, orig_db, orig_table_name, create_info,
4962 alter_info, create_table_mode, key_info,
4963 key_count, frm);
4964 if (!file)
4965 goto err;
4966 if (rea_create_table(thd, frm, path, db->str, table_name->str, create_info,
4967 file, frm_only))
4968 goto err;
4969 }
4970
4971 create_info->table= 0;
4972 if (!frm_only && create_info->tmp_table())
4973 {
4974 TABLE *table= thd->create_and_open_tmp_table(create_info->db_type, frm,
4975 path, db->str,
4976 table_name->str, true,
4977 false);
4978
4979 if (!table)
4980 {
4981 (void) thd->rm_temporary_table(create_info->db_type, path);
4982 goto err;
4983 }
4984
4985 if (is_trans != NULL)
4986 *is_trans= table->file->has_transactions();
4987
4988 thd->thread_specific_used= TRUE;
4989 create_info->table= table; // Store pointer to table
4990 }
4991#ifdef WITH_PARTITION_STORAGE_ENGINE
4992 else if (thd->work_part_info && frm_only)
4993 {
4994 /*
4995 For partitioned tables we can't find some problems with table
4996 until table is opened. Therefore in order to disallow creation
4997 of corrupted tables we have to try to open table as the part
4998 of its creation process.
4999 In cases when both .FRM and SE part of table are created table
5000 is implicitly open in ha_create_table() call.
5001 In cases when we create .FRM without SE part we have to open
5002 table explicitly.
5003 */
5004 TABLE table;
5005 TABLE_SHARE share;
5006
5007 init_tmp_table_share(thd, &share, db->str, 0, table_name->str, path);
5008
5009 bool result= (open_table_def(thd, &share, GTS_TABLE) ||
5010 open_table_from_share(thd, &share, &empty_clex_str, 0,
5011 (uint) READ_ALL, 0, &table, true));
5012 if (!result)
5013 (void) closefrm(&table);
5014
5015 free_table_share(&share);
5016
5017 if (result)
5018 {
5019 char frm_name[FN_REFLEN];
5020 strxnmov(frm_name, sizeof(frm_name), path, reg_ext, NullS);
5021 (void) mysql_file_delete(key_file_frm, frm_name, MYF(0));
5022 (void) file->ha_create_partitioning_metadata(path, NULL, CHF_DELETE_FLAG);
5023 goto err;
5024 }
5025 }
5026#endif
5027
5028 error= 0;
5029err:
5030 THD_STAGE_INFO(thd, stage_after_create);
5031 delete file;
5032 DBUG_PRINT("exit", ("return: %d", error));
5033 DBUG_RETURN(error);
5034
5035warn:
5036 error= -1;
5037 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
5038 ER_TABLE_EXISTS_ERROR,
5039 ER_THD(thd, ER_TABLE_EXISTS_ERROR),
5040 alias->str);
5041 goto err;
5042}
5043
5044/**
5045 Simple wrapper around create_table_impl() to be used
5046 in various version of CREATE TABLE statement.
5047*/
5048
5049int mysql_create_table_no_lock(THD *thd,
5050 const LEX_CSTRING *db,
5051 const LEX_CSTRING *table_name,
5052 Table_specification_st *create_info,
5053 Alter_info *alter_info, bool *is_trans,
5054 int create_table_mode,
5055 TABLE_LIST *table_list)
5056{
5057 KEY *not_used_1;
5058 uint not_used_2;
5059 int res;
5060 char path[FN_REFLEN + 1];
5061 LEX_CUSTRING frm= {0,0};
5062
5063 if (create_info->tmp_table())
5064 build_tmptable_filename(thd, path, sizeof(path));
5065 else
5066 {
5067 int length;
5068 const LEX_CSTRING *alias= table_case_name(create_info, table_name);
5069 length= build_table_filename(path, sizeof(path) - 1, db->str, alias->str, "", 0);
5070 // Check if we hit FN_REFLEN bytes along with file extension.
5071 if (length+reg_ext_length > FN_REFLEN)
5072 {
5073 my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), (int) sizeof(path)-1,
5074 path);
5075 return true;
5076 }
5077 }
5078
5079 res= create_table_impl(thd, db, table_name, db, table_name, path,
5080 *create_info, create_info,
5081 alter_info, create_table_mode,
5082 is_trans, &not_used_1, &not_used_2, &frm);
5083 my_free(const_cast<uchar*>(frm.str));
5084
5085 if (!res && create_info->sequence)
5086 {
5087 /* Set create_info.table if temporary table */
5088 if (create_info->tmp_table())
5089 table_list->table= create_info->table;
5090 else
5091 table_list->table= 0;
5092 res= sequence_insert(thd, thd->lex, table_list);
5093 }
5094
5095 return res;
5096}
5097
5098/**
5099 Implementation of SQLCOM_CREATE_TABLE.
5100
5101 Take the metadata locks (including a shared lock on the affected
5102 schema) and create the table. Is written to be called from
5103 mysql_execute_command(), to which it delegates the common parts
5104 with other commands (i.e. implicit commit before and after,
5105 close of thread tables.
5106*/
5107
5108bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
5109 Table_specification_st *create_info,
5110 Alter_info *alter_info)
5111{
5112 bool is_trans= FALSE;
5113 bool result;
5114 int create_table_mode;
5115 TABLE_LIST *pos_in_locked_tables= 0;
5116 MDL_ticket *mdl_ticket= 0;
5117 DBUG_ENTER("mysql_create_table");
5118
5119 DBUG_ASSERT(create_table == thd->lex->query_tables);
5120
5121 /* Copy temporarily the statement flags to thd for lock_table_names() */
5122 uint save_thd_create_info_options= thd->lex->create_info.options;
5123 thd->lex->create_info.options|= create_info->options;
5124
5125 /* Open or obtain an exclusive metadata lock on table being created */
5126 result= open_and_lock_tables(thd, *create_info, create_table, FALSE, 0);
5127
5128 thd->lex->create_info.options= save_thd_create_info_options;
5129
5130 if (result)
5131 {
5132 /* is_error() may be 0 if table existed and we generated a warning */
5133 DBUG_RETURN(thd->is_error());
5134 }
5135 /* The following is needed only in case of lock tables */
5136 if ((create_info->table= create_table->table))
5137 {
5138 pos_in_locked_tables= create_info->table->pos_in_locked_tables;
5139 mdl_ticket= create_table->table->mdl_ticket;
5140 }
5141
5142 /* Got lock. */
5143 DEBUG_SYNC(thd, "locked_table_name");
5144
5145 if (alter_info->create_list.elements || alter_info->key_list.elements)
5146 create_table_mode= C_ORDINARY_CREATE;
5147 else
5148 create_table_mode= C_ASSISTED_DISCOVERY;
5149
5150 if (!opt_explicit_defaults_for_timestamp)
5151 promote_first_timestamp_column(&alter_info->create_list);
5152
5153 if (mysql_create_table_no_lock(thd, &create_table->db,
5154 &create_table->table_name, create_info,
5155 alter_info,
5156 &is_trans, create_table_mode,
5157 create_table) > 0)
5158 {
5159 result= 1;
5160 goto err;
5161 }
5162
5163 /*
5164 Check if we are doing CREATE OR REPLACE TABLE under LOCK TABLES
5165 on a non temporary table
5166 */
5167 if (thd->locked_tables_mode && pos_in_locked_tables &&
5168 create_info->or_replace())
5169 {
5170 DBUG_ASSERT(thd->variables.option_bits & OPTION_TABLE_LOCK);
5171 /*
5172 Add back the deleted table and re-created table as a locked table
5173 This should always work as we have a meta lock on the table.
5174 */
5175 thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables);
5176 if (thd->locked_tables_list.reopen_tables(thd, false))
5177 {
5178 thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
5179 result= 1;
5180 goto err;
5181 }
5182 else
5183 {
5184 TABLE *table= pos_in_locked_tables->table;
5185 table->mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
5186 }
5187 }
5188
5189err:
5190 /* In RBR we don't need to log CREATE TEMPORARY TABLE */
5191 if (thd->is_current_stmt_binlog_format_row() && create_info->tmp_table())
5192 DBUG_RETURN(result);
5193
5194 if (create_info->tmp_table())
5195 thd->transaction.stmt.mark_created_temp_table();
5196
5197 /* Write log if no error or if we already deleted a table */
5198 if (likely(!result) || thd->log_current_statement)
5199 {
5200 if (unlikely(result) && create_info->table_was_deleted &&
5201 pos_in_locked_tables)
5202 {
5203 /*
5204 Possible locked table was dropped. We should remove meta data locks
5205 associated with it and do UNLOCK_TABLES if no more locked tables.
5206 */
5207 thd->locked_tables_list.unlock_locked_table(thd, mdl_ticket);
5208 }
5209 else if (likely(!result) && create_info->tmp_table() && create_info->table)
5210 {
5211 /*
5212 Remember that tmp table creation was logged so that we know if
5213 we should log a delete of it.
5214 */
5215 create_info->table->s->table_creation_was_logged= 1;
5216 }
5217 if (unlikely(write_bin_log(thd, result ? FALSE : TRUE, thd->query(),
5218 thd->query_length(), is_trans)))
5219 result= 1;
5220 }
5221 DBUG_RETURN(result);
5222}
5223
5224
5225/*
5226** Give the key name after the first field with an optional '_#' after
5227 @returns
5228 0 if keyname does not exists
5229 [1..) index + 1 of duplicate key name
5230**/
5231
5232static int
5233check_if_keyname_exists(const char *name, KEY *start, KEY *end)
5234{
5235 uint i= 1;
5236 for (KEY *key=start; key != end ; key++, i++)
5237 if (!my_strcasecmp(system_charset_info, name, key->name.str))
5238 return i;
5239 return 0;
5240}
5241
5242/**
5243 Returns 1 if field name exists otherwise 0
5244*/
5245static bool
5246check_if_field_name_exists(const char *name, List<Create_field> * fields)
5247{
5248 Create_field *fld;
5249 List_iterator<Create_field>it(*fields);
5250 while ((fld = it++))
5251 {
5252 if (!my_strcasecmp(system_charset_info, fld->field_name.str, name))
5253 return 1;
5254 }
5255 return 0;
5256}
5257
5258static char *
5259make_unique_key_name(THD *thd, const char *field_name,KEY *start,KEY *end)
5260{
5261 char buff[MAX_FIELD_NAME],*buff_end;
5262
5263 if (!check_if_keyname_exists(field_name,start,end) &&
5264 my_strcasecmp(system_charset_info,field_name,primary_key_name))
5265 return (char*) field_name; // Use fieldname
5266 buff_end=strmake(buff,field_name, sizeof(buff)-4);
5267
5268 /*
5269 Only 3 chars + '\0' left, so need to limit to 2 digit
5270 This is ok as we can't have more than 100 keys anyway
5271 */
5272 for (uint i=2 ; i< 100; i++)
5273 {
5274 *buff_end= '_';
5275 int10_to_str(i, buff_end+1, 10);
5276 if (!check_if_keyname_exists(buff,start,end))
5277 return thd->strdup(buff);
5278 }
5279 return (char*) "not_specified"; // Should never happen
5280}
5281
5282/**
5283 Make an unique name for constraints without a name
5284*/
5285
5286static void make_unique_constraint_name(THD *thd, LEX_CSTRING *name,
5287 List<Virtual_column_info> *vcol,
5288 uint *nr)
5289{
5290 char buff[MAX_FIELD_NAME], *end;
5291 List_iterator_fast<Virtual_column_info> it(*vcol);
5292
5293 end=strmov(buff, "CONSTRAINT_");
5294 for (;;)
5295 {
5296 Virtual_column_info *check;
5297 char *real_end= int10_to_str((*nr)++, end, 10);
5298 it.rewind();
5299 while ((check= it++))
5300 {
5301 if (check->name.str &&
5302 !my_strcasecmp(system_charset_info, buff, check->name.str))
5303 break;
5304 }
5305 if (!check) // Found unique name
5306 {
5307 name->length= (size_t) (real_end - buff);
5308 name->str= thd->strmake(buff, name->length);
5309 return;
5310 }
5311 }
5312}
5313
5314/**
5315 INVISIBLE_FULL are internally created. They are completely invisible
5316 to Alter command (Opposite of SYSTEM_INVISIBLE which throws an
5317 error when same name column is added by Alter). So in the case of when
5318 user added a same column name as of INVISIBLE_FULL , we change
5319 INVISIBLE_FULL column name.
5320*/
5321static const
5322char * make_unique_invisible_field_name(THD *thd, const char *field_name,
5323 List<Create_field> *fields)
5324{
5325 if (!check_if_field_name_exists(field_name, fields))
5326 return field_name;
5327 char buff[MAX_FIELD_NAME], *buff_end;
5328 buff_end= strmake_buf(buff, field_name);
5329 if (buff_end - buff < 5)
5330 return NULL; // Should not happen
5331
5332 for (uint i=1 ; i < 10000; i++)
5333 {
5334 char *real_end= int10_to_str(i, buff_end, 10);
5335 if (check_if_field_name_exists(buff, fields))
5336 continue;
5337 return (const char *)thd->strmake(buff, real_end - buff);
5338 }
5339 return NULL; //Should not happen
5340}
5341
5342/****************************************************************************
5343** Alter a table definition
5344****************************************************************************/
5345
5346bool operator!=(const MYSQL_TIME &lhs, const MYSQL_TIME &rhs)
5347{
5348 return lhs.year != rhs.year || lhs.month != rhs.month || lhs.day != rhs.day ||
5349 lhs.hour != rhs.hour || lhs.minute != rhs.minute ||
5350 lhs.second_part != rhs.second_part || lhs.neg != rhs.neg ||
5351 lhs.time_type != rhs.time_type;
5352}
5353
5354/**
5355 Rename a table.
5356
5357 @param base The handlerton handle.
5358 @param old_db The old database name.
5359 @param old_name The old table name.
5360 @param new_db The new database name.
5361 @param new_name The new table name.
5362 @param flags flags
5363 FN_FROM_IS_TMP old_name is temporary.
5364 FN_TO_IS_TMP new_name is temporary.
5365 NO_FRM_RENAME Don't rename the FRM file
5366 but only the table in the storage engine.
5367 NO_HA_TABLE Don't rename table in engine.
5368 NO_FK_CHECKS Don't check FK constraints during rename.
5369
5370 @return false OK
5371 @return true Error
5372*/
5373
5374bool
5375mysql_rename_table(handlerton *base, const LEX_CSTRING *old_db,
5376 const LEX_CSTRING *old_name, const LEX_CSTRING *new_db,
5377 const LEX_CSTRING *new_name, uint flags)
5378{
5379 THD *thd= current_thd;
5380 char from[FN_REFLEN + 1], to[FN_REFLEN + 1],
5381 lc_from[FN_REFLEN + 1], lc_to[FN_REFLEN + 1];
5382 char *from_base= from, *to_base= to;
5383 char tmp_name[SAFE_NAME_LEN+1], tmp_db_name[SAFE_NAME_LEN+1];
5384 handler *file;
5385 int error=0;
5386 ulonglong save_bits= thd->variables.option_bits;
5387 int length;
5388 DBUG_ENTER("mysql_rename_table");
5389 DBUG_ASSERT(base);
5390 DBUG_PRINT("enter", ("old: '%s'.'%s' new: '%s'.'%s'",
5391 old_db->str, old_name->str, new_db->str, new_name->str));
5392
5393 // Temporarily disable foreign key checks
5394 if (flags & NO_FK_CHECKS)
5395 thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS;
5396
5397 file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base);
5398
5399 build_table_filename(from, sizeof(from) - 1, old_db->str, old_name->str, "",
5400 flags & FN_FROM_IS_TMP);
5401 length= build_table_filename(to, sizeof(to) - 1, new_db->str, new_name->str, "",
5402 flags & FN_TO_IS_TMP);
5403 // Check if we hit FN_REFLEN bytes along with file extension.
5404 if (length+reg_ext_length > FN_REFLEN)
5405 {
5406 my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), (int) sizeof(to)-1, to);
5407 DBUG_RETURN(TRUE);
5408 }
5409
5410 /*
5411 If lower_case_table_names == 2 (case-preserving but case-insensitive
5412 file system) and the storage is not HA_FILE_BASED, we need to provide
5413 a lowercase file name, but we leave the .frm in mixed case.
5414 */
5415 if (lower_case_table_names == 2 && file &&
5416 !(file->ha_table_flags() & HA_FILE_BASED))
5417 {
5418 strmov(tmp_name, old_name->str);
5419 my_casedn_str(files_charset_info, tmp_name);
5420 strmov(tmp_db_name, old_db->str);
5421 my_casedn_str(files_charset_info, tmp_db_name);
5422
5423 build_table_filename(lc_from, sizeof(lc_from) - 1, tmp_db_name, tmp_name,
5424 "", flags & FN_FROM_IS_TMP);
5425 from_base= lc_from;
5426
5427 strmov(tmp_name, new_name->str);
5428 my_casedn_str(files_charset_info, tmp_name);
5429 strmov(tmp_db_name, new_db->str);
5430 my_casedn_str(files_charset_info, tmp_db_name);
5431
5432 build_table_filename(lc_to, sizeof(lc_to) - 1, tmp_db_name, tmp_name, "",
5433 flags & FN_TO_IS_TMP);
5434 to_base= lc_to;
5435 }
5436
5437 if (flags & NO_HA_TABLE)
5438 {
5439 if (rename_file_ext(from,to,reg_ext))
5440 error= my_errno;
5441 (void) file->ha_create_partitioning_metadata(to, from, CHF_RENAME_FLAG);
5442 }
5443 else if (!file || likely(!(error=file->ha_rename_table(from_base, to_base))))
5444 {
5445 if (!(flags & NO_FRM_RENAME) && unlikely(rename_file_ext(from,to,reg_ext)))
5446 {
5447 error=my_errno;
5448 if (file)
5449 {
5450 if (error == ENOENT)
5451 error= 0; // this is ok if file->ha_rename_table() succeeded
5452 else
5453 file->ha_rename_table(to_base, from_base); // Restore old file name
5454 }
5455 }
5456 }
5457 delete file;
5458
5459 if (unlikely(error))
5460 {
5461 if (error == HA_ERR_WRONG_COMMAND)
5462 my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
5463 else
5464 my_error(ER_ERROR_ON_RENAME, MYF(0), from, to, error);
5465 }
5466 else if (!(flags & FN_IS_TMP))
5467 mysql_audit_rename_table(thd, old_db, old_name, new_db, new_name);
5468
5469 /*
5470 Remove the old table share from the pfs table share array. The new table
5471 share will be created when the renamed table is first accessed.
5472 */
5473 if (likely(error == 0))
5474 {
5475 PSI_CALL_drop_table_share(flags & FN_FROM_IS_TMP,
5476 old_db->str, (uint)old_db->length,
5477 old_name->str, (uint)old_name->length);
5478 }
5479
5480 // Restore options bits to the original value
5481 thd->variables.option_bits= save_bits;
5482
5483 DBUG_RETURN(error != 0);
5484}
5485
5486
5487/*
5488 Create a table identical to the specified table
5489
5490 SYNOPSIS
5491 mysql_create_like_table()
5492 thd Thread object
5493 table Table list element for target table
5494 src_table Table list element for source table
5495 create_info Create info
5496
5497 RETURN VALUES
5498 FALSE OK
5499 TRUE error
5500*/
5501
5502bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
5503 TABLE_LIST* src_table,
5504 Table_specification_st *create_info)
5505{
5506 Table_specification_st local_create_info;
5507 TABLE_LIST *pos_in_locked_tables= 0;
5508 Alter_info local_alter_info;
5509 Alter_table_ctx local_alter_ctx; // Not used
5510 bool res= TRUE;
5511 bool is_trans= FALSE;
5512 bool do_logging= FALSE;
5513 uint not_used;
5514 int create_res;
5515 DBUG_ENTER("mysql_create_like_table");
5516
5517#ifdef WITH_WSREP
5518 if (WSREP_ON && !thd->wsrep_applier &&
5519 wsrep_create_like_table(thd, table, src_table, create_info))
5520 DBUG_RETURN(res);
5521#endif
5522
5523 /*
5524 We the open source table to get its description in HA_CREATE_INFO
5525 and Alter_info objects. This also acquires a shared metadata lock
5526 on this table which ensures that no concurrent DDL operation will
5527 mess with it.
5528 Also in case when we create non-temporary table open_tables()
5529 call obtains an exclusive metadata lock on target table ensuring
5530 that we can safely perform table creation.
5531 Thus by holding both these locks we ensure that our statement is
5532 properly isolated from all concurrent operations which matter.
5533 */
5534
5535 /* Copy temporarily the statement flags to thd for lock_table_names() */
5536 // QQ: is this really needed???
5537 uint save_thd_create_info_options= thd->lex->create_info.options;
5538 thd->lex->create_info.options|= create_info->options;
5539 res= open_tables(thd, &thd->lex->query_tables, &not_used, 0);
5540 thd->lex->create_info.options= save_thd_create_info_options;
5541
5542 if (res)
5543 {
5544 /* is_error() may be 0 if table existed and we generated a warning */
5545 res= thd->is_error();
5546 goto err;
5547 }
5548 /* Ensure we don't try to create something from which we select from */
5549 if (create_info->or_replace() && !create_info->tmp_table())
5550 {
5551 TABLE_LIST *duplicate;
5552 if ((duplicate= unique_table(thd, table, src_table, 0)))
5553 {
5554 update_non_unique_table_error(src_table, "CREATE", duplicate);
5555 goto err;
5556 }
5557 }
5558
5559 src_table->table->use_all_columns();
5560
5561 DEBUG_SYNC(thd, "create_table_like_after_open");
5562
5563 /*
5564 Fill Table_specification_st and Alter_info with the source table description.
5565 Set OR REPLACE and IF NOT EXISTS option as in the CREATE TABLE LIKE
5566 statement.
5567 */
5568 local_create_info.init(create_info->create_like_options());
5569 local_create_info.db_type= src_table->table->s->db_type();
5570 local_create_info.row_type= src_table->table->s->row_type;
5571 if (mysql_prepare_alter_table(thd, src_table->table, &local_create_info,
5572 &local_alter_info, &local_alter_ctx))
5573 goto err;
5574#ifdef WITH_PARTITION_STORAGE_ENGINE
5575 /* Partition info is not handled by mysql_prepare_alter_table() call. */
5576 if (src_table->table->part_info)
5577 thd->work_part_info= src_table->table->part_info->get_clone(thd);
5578#endif
5579
5580 /*
5581 Adjust description of source table before using it for creation of
5582 target table.
5583
5584 Similarly to SHOW CREATE TABLE we ignore MAX_ROWS attribute of
5585 temporary table which represents I_S table.
5586 */
5587 if (src_table->schema_table)
5588 local_create_info.max_rows= 0;
5589 /* Replace type of source table with one specified in the statement. */
5590 local_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
5591 local_create_info.options|= create_info->options;
5592 /* Reset auto-increment counter for the new table. */
5593 local_create_info.auto_increment_value= 0;
5594 /*
5595 Do not inherit values of DATA and INDEX DIRECTORY options from
5596 the original table. This is documented behavior.
5597 */
5598 local_create_info.data_file_name= local_create_info.index_file_name= NULL;
5599
5600 if (src_table->table->versioned() &&
5601 local_create_info.vers_info.fix_create_like(local_alter_info, local_create_info,
5602 *src_table, *table))
5603 {
5604 goto err;
5605 }
5606
5607 /* The following is needed only in case of lock tables */
5608 if ((local_create_info.table= thd->lex->query_tables->table))
5609 pos_in_locked_tables= local_create_info.table->pos_in_locked_tables;
5610
5611 res= ((create_res=
5612 mysql_create_table_no_lock(thd, &table->db, &table->table_name,
5613 &local_create_info, &local_alter_info,
5614 &is_trans, C_ORDINARY_CREATE,
5615 table)) > 0);
5616 /* Remember to log if we deleted something */
5617 do_logging= thd->log_current_statement;
5618 if (res)
5619 goto err;
5620
5621 /*
5622 Check if we are doing CREATE OR REPLACE TABLE under LOCK TABLES
5623 on a non temporary table
5624 */
5625 if (thd->locked_tables_mode && pos_in_locked_tables &&
5626 create_info->or_replace())
5627 {
5628 /*
5629 Add back the deleted table and re-created table as a locked table
5630 This should always work as we have a meta lock on the table.
5631 */
5632 thd->locked_tables_list.add_back_last_deleted_lock(pos_in_locked_tables);
5633 if (thd->locked_tables_list.reopen_tables(thd, false))
5634 {
5635 thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
5636 res= 1; // We got an error
5637 }
5638 else
5639 {
5640 /*
5641 Get pointer to the newly opened table. We need this to ensure we
5642 don't reopen the table when doing statment logging below.
5643 */
5644 table->table= pos_in_locked_tables->table;
5645 table->table->mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
5646 }
5647 }
5648 else
5649 {
5650 /*
5651 Ensure that we have an exclusive lock on target table if we are creating
5652 non-temporary table.
5653 */
5654 DBUG_ASSERT((create_info->tmp_table()) ||
5655 thd->mdl_context.is_lock_owner(MDL_key::TABLE, table->db.str,
5656 table->table_name.str,
5657 MDL_EXCLUSIVE));
5658 }
5659
5660 DEBUG_SYNC(thd, "create_table_like_before_binlog");
5661
5662 /*
5663 We have to write the query before we unlock the tables.
5664 */
5665 if (thd->is_current_stmt_binlog_disabled())
5666 goto err;
5667
5668 if (thd->is_current_stmt_binlog_format_row())
5669 {
5670 /*
5671 Since temporary tables are not replicated under row-based
5672 replication, CREATE TABLE ... LIKE ... needs special
5673 treatement. We have four cases to consider, according to the
5674 following decision table:
5675
5676 ==== ========= ========= ==============================
5677 Case Target Source Write to binary log
5678 ==== ========= ========= ==============================
5679 1 normal normal Original statement
5680 2 normal temporary Generated statement if the table
5681 was created.
5682 3 temporary normal Nothing
5683 4 temporary temporary Nothing
5684 ==== ========= ========= ==============================
5685 */
5686 if (!(create_info->tmp_table()))
5687 {
5688 if (src_table->table->s->tmp_table) // Case 2
5689 {
5690 char buf[2048];
5691 String query(buf, sizeof(buf), system_charset_info);
5692 query.length(0); // Have to zero it since constructor doesn't
5693 Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN |
5694 MYSQL_OPEN_IGNORE_KILLED);
5695 bool new_table= FALSE; // Whether newly created table is open.
5696
5697 if (create_res != 0)
5698 {
5699 /*
5700 Table or view with same name already existed and we where using
5701 IF EXISTS. Continue without logging anything.
5702 */
5703 do_logging= 0;
5704 goto err;
5705 }
5706 if (!table->table)
5707 {
5708 TABLE_LIST::enum_open_strategy save_open_strategy;
5709 int open_res;
5710 /* Force the newly created table to be opened */
5711 save_open_strategy= table->open_strategy;
5712 table->open_strategy= TABLE_LIST::OPEN_NORMAL;
5713
5714 /*
5715 In order for show_create_table() to work we need to open
5716 destination table if it is not already open (i.e. if it
5717 has not existed before). We don't need acquire metadata
5718 lock in order to do this as we already hold exclusive
5719 lock on this table. The table will be closed by
5720 close_thread_table() at the end of this branch.
5721 */
5722 open_res= open_table(thd, table, &ot_ctx);
5723 /* Restore */
5724 table->open_strategy= save_open_strategy;
5725 if (open_res)
5726 {
5727 res= 1;
5728 goto err;
5729 }
5730 new_table= TRUE;
5731 }
5732 /*
5733 We have to re-test if the table was a view as the view may not
5734 have been opened until just above.
5735 */
5736 if (!table->view)
5737 {
5738 /*
5739 After opening a MERGE table add the children to the query list of
5740 tables, so that children tables info can be used on "CREATE TABLE"
5741 statement generation by the binary log.
5742 Note that placeholders don't have the handler open.
5743 */
5744 if (table->table->file->extra(HA_EXTRA_ADD_CHILDREN_LIST))
5745 goto err;
5746
5747 /*
5748 As the reference table is temporary and may not exist on slave, we must
5749 force the ENGINE to be present into CREATE TABLE.
5750 */
5751 create_info->used_fields|= HA_CREATE_USED_ENGINE;
5752
5753 int result __attribute__((unused))=
5754 show_create_table(thd, table, &query, create_info, WITH_DB_NAME);
5755
5756 DBUG_ASSERT(result == 0); // show_create_table() always return 0
5757 do_logging= FALSE;
5758 if (write_bin_log(thd, TRUE, query.ptr(), query.length()))
5759 {
5760 res= 1;
5761 do_logging= 0;
5762 goto err;
5763 }
5764
5765 if (new_table)
5766 {
5767 DBUG_ASSERT(thd->open_tables == table->table);
5768 /*
5769 When opening the table, we ignored the locked tables
5770 (MYSQL_OPEN_GET_NEW_TABLE). Now we can close the table
5771 without risking to close some locked table.
5772 */
5773 close_thread_table(thd, &thd->open_tables);
5774 }
5775 }
5776 }
5777 else // Case 1
5778 do_logging= TRUE;
5779 }
5780 /*
5781 Case 3 and 4 does nothing under RBR
5782 */
5783 }
5784 else
5785 {
5786 DBUG_PRINT("info",
5787 ("res: %d tmp_table: %d create_info->table: %p",
5788 res, create_info->tmp_table(), local_create_info.table));
5789 if (create_info->tmp_table())
5790 {
5791 thd->transaction.stmt.mark_created_temp_table();
5792 if (!res && local_create_info.table)
5793 {
5794 /*
5795 Remember that tmp table creation was logged so that we know if
5796 we should log a delete of it.
5797 */
5798 local_create_info.table->s->table_creation_was_logged= 1;
5799 }
5800 }
5801 do_logging= TRUE;
5802 }
5803
5804err:
5805 if (do_logging)
5806 {
5807 if (res && create_info->table_was_deleted)
5808 {
5809 /*
5810 Table was not deleted. Original table was deleted.
5811 We have to log it.
5812 */
5813 log_drop_table(thd, &table->db, &table->table_name, create_info->tmp_table());
5814 }
5815 else if (write_bin_log(thd, res ? FALSE : TRUE, thd->query(),
5816 thd->query_length(), is_trans))
5817 res= 1;
5818 }
5819
5820 DBUG_RETURN(res);
5821}
5822
5823
5824/* table_list should contain just one table */
5825int mysql_discard_or_import_tablespace(THD *thd,
5826 TABLE_LIST *table_list,
5827 bool discard)
5828{
5829 Alter_table_prelocking_strategy alter_prelocking_strategy;
5830 int error;
5831 DBUG_ENTER("mysql_discard_or_import_tablespace");
5832
5833 mysql_audit_alter_table(thd, table_list);
5834
5835 /*
5836 Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
5837 ALTER TABLE
5838 */
5839
5840 THD_STAGE_INFO(thd, stage_discard_or_import_tablespace);
5841
5842 /*
5843 We set this flag so that ha_innobase::open and ::external_lock() do
5844 not complain when we lock the table
5845 */
5846 thd->tablespace_op= TRUE;
5847 /*
5848 Adjust values of table-level and metadata which was set in parser
5849 for the case general ALTER TABLE.
5850 */
5851 table_list->mdl_request.set_type(MDL_EXCLUSIVE);
5852 table_list->lock_type= TL_WRITE;
5853 /* Do not open views. */
5854 table_list->required_type= TABLE_TYPE_NORMAL;
5855
5856 if (open_and_lock_tables(thd, table_list, FALSE, 0,
5857 &alter_prelocking_strategy))
5858 {
5859 thd->tablespace_op=FALSE;
5860 DBUG_RETURN(-1);
5861 }
5862
5863 error= table_list->table->file->ha_discard_or_import_tablespace(discard);
5864
5865 THD_STAGE_INFO(thd, stage_end);
5866
5867 if (unlikely(error))
5868 goto err;
5869
5870 /*
5871 The 0 in the call below means 'not in a transaction', which means
5872 immediate invalidation; that is probably what we wish here
5873 */
5874 query_cache_invalidate3(thd, table_list, 0);
5875
5876 /* The ALTER TABLE is always in its own transaction */
5877 error= trans_commit_stmt(thd);
5878 if (unlikely(trans_commit_implicit(thd)))
5879 error=1;
5880 if (likely(!error))
5881 error= write_bin_log(thd, FALSE, thd->query(), thd->query_length());
5882
5883err:
5884 thd->tablespace_op=FALSE;
5885
5886 if (likely(error == 0))
5887 {
5888 my_ok(thd);
5889 DBUG_RETURN(0);
5890 }
5891
5892 table_list->table->file->print_error(error, MYF(0));
5893
5894 DBUG_RETURN(-1);
5895}
5896
5897
5898/**
5899 Check if key is a candidate key, i.e. a unique index with no index
5900 fields partial or nullable.
5901*/
5902
5903static bool is_candidate_key(KEY *key)
5904{
5905 KEY_PART_INFO *key_part;
5906 KEY_PART_INFO *key_part_end= key->key_part + key->user_defined_key_parts;
5907
5908 if (!(key->flags & HA_NOSAME) || (key->flags & HA_NULL_PART_KEY))
5909 return false;
5910
5911 for (key_part= key->key_part; key_part < key_part_end; key_part++)
5912 {
5913 if (key_part->key_part_flag & HA_PART_KEY_SEG)
5914 return false;
5915 }
5916 return true;
5917}
5918
5919
5920/*
5921 Preparation for table creation
5922
5923 SYNOPSIS
5924 handle_if_exists_option()
5925 thd Thread object.
5926 table The altered table.
5927 alter_info List of columns and indexes to create
5928
5929 DESCRIPTION
5930 Looks for the IF [NOT] EXISTS options, checks the states and remove items
5931 from the list if existing found.
5932
5933 RETURN VALUES
5934 NONE
5935*/
5936
5937static void
5938handle_if_exists_options(THD *thd, TABLE *table, Alter_info *alter_info)
5939{
5940 Field **f_ptr;
5941 DBUG_ENTER("handle_if_exists_option");
5942
5943 /* Handle ADD COLUMN IF NOT EXISTS. */
5944 {
5945 List_iterator<Create_field> it(alter_info->create_list);
5946 Create_field *sql_field;
5947
5948 while ((sql_field=it++))
5949 {
5950 if (!sql_field->create_if_not_exists || sql_field->change.str)
5951 continue;
5952 /*
5953 If there is a field with the same name in the table already,
5954 remove the sql_field from the list.
5955 */
5956 for (f_ptr=table->field; *f_ptr; f_ptr++)
5957 {
5958 if (lex_string_cmp(system_charset_info,
5959 &sql_field->field_name,
5960 &(*f_ptr)->field_name) == 0)
5961 goto drop_create_field;
5962 }
5963 {
5964 /*
5965 If in the ADD list there is a field with the same name,
5966 remove the sql_field from the list.
5967 */
5968 List_iterator<Create_field> chk_it(alter_info->create_list);
5969 Create_field *chk_field;
5970 while ((chk_field= chk_it++) && chk_field != sql_field)
5971 {
5972 if (lex_string_cmp(system_charset_info,
5973 &sql_field->field_name,
5974 &chk_field->field_name) == 0)
5975 goto drop_create_field;
5976 }
5977 }
5978 continue;
5979drop_create_field:
5980 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
5981 ER_DUP_FIELDNAME, ER_THD(thd, ER_DUP_FIELDNAME),
5982 sql_field->field_name.str);
5983 it.remove();
5984 if (alter_info->create_list.is_empty())
5985 {
5986 alter_info->flags&= ~ALTER_PARSER_ADD_COLUMN;
5987 if (alter_info->key_list.is_empty())
5988 alter_info->flags&= ~(ALTER_ADD_INDEX | ALTER_ADD_FOREIGN_KEY);
5989 }
5990 }
5991 }
5992
5993 /* Handle MODIFY COLUMN IF EXISTS. */
5994 {
5995 List_iterator<Create_field> it(alter_info->create_list);
5996 Create_field *sql_field;
5997
5998 while ((sql_field=it++))
5999 {
6000 if (!sql_field->create_if_not_exists || !sql_field->change.str)
6001 continue;
6002 /*
6003 If there is NO field with the same name in the table already,
6004 remove the sql_field from the list.
6005 */
6006 for (f_ptr=table->field; *f_ptr; f_ptr++)
6007 {
6008 if (lex_string_cmp(system_charset_info,
6009 &sql_field->change,
6010 &(*f_ptr)->field_name) == 0)
6011 {
6012 break;
6013 }
6014 }
6015 if (unlikely(*f_ptr == NULL))
6016 {
6017 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
6018 ER_BAD_FIELD_ERROR,
6019 ER_THD(thd, ER_BAD_FIELD_ERROR),
6020 sql_field->change.str, table->s->table_name.str);
6021 it.remove();
6022 if (alter_info->create_list.is_empty())
6023 {
6024 alter_info->flags&= ~(ALTER_PARSER_ADD_COLUMN | ALTER_CHANGE_COLUMN);
6025 if (alter_info->key_list.is_empty())
6026 alter_info->flags&= ~ALTER_ADD_INDEX;
6027 }
6028 }
6029 }
6030 }
6031
6032 /* Handle ALTER COLUMN IF EXISTS SET/DROP DEFAULT. */
6033 {
6034 List_iterator<Alter_column> it(alter_info->alter_list);
6035 Alter_column *acol;
6036
6037 while ((acol=it++))
6038 {
6039 if (!acol->alter_if_exists)
6040 continue;
6041 /*
6042 If there is NO field with the same name in the table already,
6043 remove the acol from the list.
6044 */
6045 for (f_ptr=table->field; *f_ptr; f_ptr++)
6046 {
6047 if (my_strcasecmp(system_charset_info,
6048 acol->name, (*f_ptr)->field_name.str) == 0)
6049 break;
6050 }
6051 if (unlikely(*f_ptr == NULL))
6052 {
6053 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
6054 ER_BAD_FIELD_ERROR,
6055 ER_THD(thd, ER_BAD_FIELD_ERROR),
6056 acol->name, table->s->table_name.str);
6057 it.remove();
6058 if (alter_info->alter_list.is_empty())
6059 {
6060 alter_info->flags&= ~(ALTER_CHANGE_COLUMN_DEFAULT);
6061 }
6062 }
6063 }
6064 }
6065
6066 /* Handle DROP COLUMN/KEY IF EXISTS. */
6067 {
6068 List_iterator<Alter_drop> drop_it(alter_info->drop_list);
6069 Alter_drop *drop;
6070 bool remove_drop;
6071 while ((drop= drop_it++))
6072 {
6073 if (!drop->drop_if_exists)
6074 continue;
6075 remove_drop= TRUE;
6076 if (drop->type == Alter_drop::COLUMN)
6077 {
6078 /*
6079 If there is NO field with that name in the table,
6080 remove the 'drop' from the list.
6081 */
6082 for (f_ptr=table->field; *f_ptr; f_ptr++)
6083 {
6084 if (my_strcasecmp(system_charset_info,
6085 drop->name, (*f_ptr)->field_name.str) == 0)
6086 {
6087 remove_drop= FALSE;
6088 break;
6089 }
6090 }
6091 }
6092 else if (drop->type == Alter_drop::CHECK_CONSTRAINT)
6093 {
6094 for (uint i=table->s->field_check_constraints;
6095 i < table->s->table_check_constraints;
6096 i++)
6097 {
6098 if (my_strcasecmp(system_charset_info, drop->name,
6099 table->check_constraints[i]->name.str) == 0)
6100 {
6101 remove_drop= FALSE;
6102 break;
6103 }
6104 }
6105 }
6106 else /* Alter_drop::KEY and Alter_drop::FOREIGN_KEY */
6107 {
6108 uint n_key;
6109 if (drop->type != Alter_drop::FOREIGN_KEY)
6110 {
6111 for (n_key=0; n_key < table->s->keys; n_key++)
6112 {
6113 if (my_strcasecmp(system_charset_info,
6114 drop->name,
6115 table->key_info[n_key].name.str) == 0)
6116 {
6117 remove_drop= FALSE;
6118 break;
6119 }
6120 }
6121 }
6122 else
6123 {
6124 List <FOREIGN_KEY_INFO> fk_child_key_list;
6125 FOREIGN_KEY_INFO *f_key;
6126 table->file->get_foreign_key_list(thd, &fk_child_key_list);
6127 List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
6128 while ((f_key= fk_key_it++))
6129 {
6130 if (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
6131 drop->name) == 0)
6132 {
6133 remove_drop= FALSE;
6134 break;
6135 }
6136 }
6137 }
6138 }
6139
6140 if (!remove_drop)
6141 {
6142 /*
6143 Check if the name appears twice in the DROP list.
6144 */
6145 List_iterator<Alter_drop> chk_it(alter_info->drop_list);
6146 Alter_drop *chk_drop;
6147 while ((chk_drop= chk_it++) && chk_drop != drop)
6148 {
6149 if (drop->type == chk_drop->type &&
6150 my_strcasecmp(system_charset_info,
6151 drop->name, chk_drop->name) == 0)
6152 {
6153 remove_drop= TRUE;
6154 break;
6155 }
6156 }
6157 }
6158
6159 if (remove_drop)
6160 {
6161 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
6162 ER_CANT_DROP_FIELD_OR_KEY,
6163 ER_THD(thd, ER_CANT_DROP_FIELD_OR_KEY),
6164 drop->type_name(), drop->name);
6165 drop_it.remove();
6166 if (alter_info->drop_list.is_empty())
6167 alter_info->flags&= ~(ALTER_PARSER_DROP_COLUMN |
6168 ALTER_DROP_INDEX |
6169 ALTER_DROP_FOREIGN_KEY);
6170 }
6171 }
6172 }
6173
6174 /* ALTER TABLE ADD KEY IF NOT EXISTS */
6175 /* ALTER TABLE ADD FOREIGN KEY IF NOT EXISTS */
6176 {
6177 Key *key;
6178 List_iterator<Key> key_it(alter_info->key_list);
6179 uint n_key;
6180 const char *keyname= NULL;
6181 while ((key=key_it++))
6182 {
6183 if (!key->if_not_exists() && !key->or_replace())
6184 continue;
6185
6186 /* Check if the table already has a PRIMARY KEY */
6187 bool dup_primary_key= key->type == Key::PRIMARY &&
6188 table->s->primary_key != MAX_KEY;
6189 if (dup_primary_key)
6190 goto remove_key;
6191
6192 /* If the name of the key is not specified, */
6193 /* let us check the name of the first key part. */
6194 if ((keyname= key->name.str) == NULL)
6195 {
6196 if (key->type == Key::PRIMARY)
6197 keyname= primary_key_name;
6198 else
6199 {
6200 List_iterator<Key_part_spec> part_it(key->columns);
6201 Key_part_spec *kp;
6202 if ((kp= part_it++))
6203 keyname= kp->field_name.str;
6204 if (keyname == NULL)
6205 continue;
6206 }
6207 }
6208 if (key->type != Key::FOREIGN_KEY)
6209 {
6210 for (n_key=0; n_key < table->s->keys; n_key++)
6211 {
6212 if (my_strcasecmp(system_charset_info,
6213 keyname, table->key_info[n_key].name.str) == 0)
6214 {
6215 goto remove_key;
6216 }
6217 }
6218 }
6219 else
6220 {
6221 List <FOREIGN_KEY_INFO> fk_child_key_list;
6222 FOREIGN_KEY_INFO *f_key;
6223 table->file->get_foreign_key_list(thd, &fk_child_key_list);
6224 List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
6225 while ((f_key= fk_key_it++))
6226 {
6227 if (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
6228 keyname) == 0)
6229 goto remove_key;
6230 }
6231 }
6232
6233 {
6234 Key *chk_key;
6235 List_iterator<Key> chk_it(alter_info->key_list);
6236 const char *chkname;
6237 while ((chk_key=chk_it++) && chk_key != key)
6238 {
6239 if ((chkname= chk_key->name.str) == NULL)
6240 {
6241 List_iterator<Key_part_spec> part_it(chk_key->columns);
6242 Key_part_spec *kp;
6243 if ((kp= part_it++))
6244 chkname= kp->field_name.str;
6245 if (keyname == NULL)
6246 continue;
6247 }
6248 if (key->type == chk_key->type &&
6249 my_strcasecmp(system_charset_info, keyname, chkname) == 0)
6250 goto remove_key;
6251 }
6252 }
6253 continue;
6254
6255remove_key:
6256 if (key->if_not_exists())
6257 {
6258 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
6259 ER_DUP_KEYNAME, ER_THD(thd, dup_primary_key
6260 ? ER_MULTIPLE_PRI_KEY : ER_DUP_KEYNAME), keyname);
6261 key_it.remove();
6262 if (key->type == Key::FOREIGN_KEY)
6263 {
6264 /* ADD FOREIGN KEY appends two items. */
6265 key_it.remove();
6266 }
6267 if (alter_info->key_list.is_empty())
6268 alter_info->flags&= ~(ALTER_ADD_INDEX | ALTER_ADD_FOREIGN_KEY);
6269 }
6270 else
6271 {
6272 DBUG_ASSERT(key->or_replace());
6273 Alter_drop::drop_type type= (key->type == Key::FOREIGN_KEY) ?
6274 Alter_drop::FOREIGN_KEY : Alter_drop::KEY;
6275 Alter_drop *ad= new Alter_drop(type, key->name.str, FALSE);
6276 if (ad != NULL)
6277 {
6278 // Adding the index into the drop list for replacing
6279 alter_info->flags |= ALTER_DROP_INDEX;
6280 alter_info->drop_list.push_back(ad, thd->mem_root);
6281 }
6282 }
6283 }
6284 }
6285
6286#ifdef WITH_PARTITION_STORAGE_ENGINE
6287 partition_info *tab_part_info= table->part_info;
6288 thd->work_part_info= thd->lex->part_info;
6289 if (tab_part_info)
6290 {
6291 /* ALTER TABLE ADD PARTITION IF NOT EXISTS */
6292 if ((alter_info->partition_flags & ALTER_PARTITION_ADD) &&
6293 thd->lex->create_info.if_not_exists())
6294 {
6295 partition_info *alt_part_info= thd->lex->part_info;
6296 if (alt_part_info)
6297 {
6298 List_iterator<partition_element> new_part_it(alt_part_info->partitions);
6299 partition_element *pe;
6300 while ((pe= new_part_it++))
6301 {
6302 if (!tab_part_info->has_unique_name(pe))
6303 {
6304 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
6305 ER_SAME_NAME_PARTITION,
6306 ER_THD(thd, ER_SAME_NAME_PARTITION),
6307 pe->partition_name);
6308 alter_info->partition_flags&= ~ALTER_PARTITION_ADD;
6309 thd->work_part_info= NULL;
6310 break;
6311 }
6312 }
6313 }
6314 }
6315 /* ALTER TABLE DROP PARTITION IF EXISTS */
6316 if ((alter_info->partition_flags & ALTER_PARTITION_DROP) &&
6317 thd->lex->if_exists())
6318 {
6319 List_iterator<const char> names_it(alter_info->partition_names);
6320 const char *name;
6321
6322 while ((name= names_it++))
6323 {
6324 List_iterator<partition_element> part_it(tab_part_info->partitions);
6325 partition_element *part_elem;
6326 while ((part_elem= part_it++))
6327 {
6328 if (my_strcasecmp(system_charset_info,
6329 part_elem->partition_name, name) == 0)
6330 break;
6331 }
6332 if (!part_elem)
6333 {
6334 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
6335 ER_DROP_PARTITION_NON_EXISTENT,
6336 ER_THD(thd, ER_DROP_PARTITION_NON_EXISTENT),
6337 "DROP");
6338 names_it.remove();
6339 }
6340 }
6341 if (alter_info->partition_names.elements == 0)
6342 alter_info->partition_flags&= ~ALTER_PARTITION_DROP;
6343 }
6344 }
6345#endif /*WITH_PARTITION_STORAGE_ENGINE*/
6346
6347 /* ADD CONSTRAINT IF NOT EXISTS. */
6348 {
6349 List_iterator<Virtual_column_info> it(alter_info->check_constraint_list);
6350 Virtual_column_info *check;
6351 TABLE_SHARE *share= table->s;
6352 uint c;
6353 while ((check=it++))
6354 {
6355 if (!(check->flags & Alter_info::CHECK_CONSTRAINT_IF_NOT_EXISTS) &&
6356 check->name.length)
6357 continue;
6358 check->flags= 0;
6359 for (c= share->field_check_constraints;
6360 c < share->table_check_constraints ; c++)
6361 {
6362 Virtual_column_info *dup= table->check_constraints[c];
6363 if (dup->name.length == check->name.length &&
6364 lex_string_cmp(system_charset_info,
6365 &check->name, &dup->name) == 0)
6366 {
6367 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
6368 ER_DUP_CONSTRAINT_NAME, ER_THD(thd, ER_DUP_CONSTRAINT_NAME),
6369 "CHECK", check->name.str);
6370 it.remove();
6371 if (alter_info->check_constraint_list.elements == 0)
6372 alter_info->flags&= ~ALTER_ADD_CHECK_CONSTRAINT;
6373
6374 break;
6375 }
6376 }
6377 }
6378 }
6379
6380 DBUG_VOID_RETURN;
6381}
6382
6383
6384/**
6385 Get Create_field object for newly created table by field index.
6386
6387 @param alter_info Alter_info describing newly created table.
6388 @param idx Field index.
6389*/
6390
6391static Create_field *get_field_by_index(Alter_info *alter_info, uint idx)
6392{
6393 List_iterator_fast<Create_field> field_it(alter_info->create_list);
6394 uint field_idx= 0;
6395 Create_field *field;
6396
6397 while ((field= field_it++) && field_idx < idx)
6398 { field_idx++; }
6399
6400 return field;
6401}
6402
6403
6404static int compare_uint(const uint *s, const uint *t)
6405{
6406 return (*s < *t) ? -1 : ((*s > *t) ? 1 : 0);
6407}
6408
6409
6410/**
6411 Compare original and new versions of a table and fill Alter_inplace_info
6412 describing differences between those versions.
6413
6414 @param thd Thread
6415 @param table The original table.
6416 @param varchar Indicates that new definition has new
6417 VARCHAR column.
6418 @param[in/out] ha_alter_info Data structure which already contains
6419 basic information about create options,
6420 field and keys for the new version of
6421 table and which should be completed with
6422 more detailed information needed for
6423 in-place ALTER.
6424
6425 First argument 'table' contains information of the original
6426 table, which includes all corresponding parts that the new
6427 table has in arguments create_list, key_list and create_info.
6428
6429 Compare the changes between the original and new table definitions.
6430 The result of this comparison is then passed to SE which determines
6431 whether it can carry out these changes in-place.
6432
6433 Mark any changes detected in the ha_alter_flags.
6434 We generally try to specify handler flags only if there are real
6435 changes. But in cases when it is cumbersome to determine if some
6436 attribute has really changed we might choose to set flag
6437 pessimistically, for example, relying on parser output only.
6438
6439 If there are no data changes, but index changes, 'index_drop_buffer'
6440 and/or 'index_add_buffer' are populated with offsets into
6441 table->key_info or key_info_buffer respectively for the indexes
6442 that need to be dropped and/or (re-)created.
6443
6444 Note that this function assumes that it is OK to change Alter_info
6445 and HA_CREATE_INFO which it gets. It is caller who is responsible
6446 for creating copies for this structures if he needs them unchanged.
6447
6448 @retval true error
6449 @retval false success
6450*/
6451
6452static bool fill_alter_inplace_info(THD *thd,
6453 TABLE *table,
6454 bool varchar,
6455 Alter_inplace_info *ha_alter_info)
6456{
6457 Field **f_ptr, *field;
6458 List_iterator_fast<Create_field> new_field_it;
6459 Create_field *new_field;
6460 KEY_PART_INFO *key_part, *new_part;
6461 KEY_PART_INFO *end;
6462 uint candidate_key_count= 0;
6463 Alter_info *alter_info= ha_alter_info->alter_info;
6464 DBUG_ENTER("fill_alter_inplace_info");
6465 DBUG_PRINT("info", ("alter_info->flags: %llu", alter_info->flags));
6466
6467 /* Allocate result buffers. */
6468 if (! (ha_alter_info->index_drop_buffer=
6469 (KEY**) thd->alloc(sizeof(KEY*) * table->s->keys)) ||
6470 ! (ha_alter_info->index_add_buffer=
6471 (uint*) thd->alloc(sizeof(uint) *
6472 alter_info->key_list.elements)))
6473 DBUG_RETURN(true);
6474
6475 /*
6476 Copy parser flags, but remove some flags that handlers doesn't
6477 need to care about (old engines may not ignore these parser flags).
6478 ALTER_RENAME_COLUMN is replaced by ALTER_COLUMN_NAME.
6479 ALTER_CHANGE_COLUMN_DEFAULT is replaced by ALTER_CHANGE_COLUMN
6480 ALTER_PARSE_ADD_COLUMN, ALTER_PARSE_DROP_COLUMN, ALTER_ADD_INDEX and
6481 ALTER_DROP_INDEX are replaced with versions that have higher granuality.
6482 */
6483
6484 ha_alter_info->handler_flags|= (alter_info->flags &
6485 ~(ALTER_ADD_INDEX |
6486 ALTER_DROP_INDEX |
6487 ALTER_PARSER_ADD_COLUMN |
6488 ALTER_PARSER_DROP_COLUMN |
6489 ALTER_COLUMN_ORDER |
6490 ALTER_RENAME_COLUMN |
6491 ALTER_CHANGE_COLUMN |
6492 ALTER_COLUMN_UNVERSIONED));
6493 /*
6494 Comparing new and old default values of column is cumbersome.
6495 So instead of using such a comparison for detecting if default
6496 has really changed we rely on flags set by parser to get an
6497 approximate value for storage engine flag.
6498 */
6499 if (alter_info->flags & ALTER_CHANGE_COLUMN)
6500 ha_alter_info->handler_flags|= ALTER_COLUMN_DEFAULT;
6501
6502 /*
6503 If we altering table with old VARCHAR fields we will be automatically
6504 upgrading VARCHAR column types.
6505 */
6506 if (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar)
6507 ha_alter_info->handler_flags|= ALTER_STORED_COLUMN_TYPE;
6508
6509 DBUG_PRINT("info", ("handler_flags: %llu", ha_alter_info->handler_flags));
6510
6511 /*
6512 Go through fields in old version of table and detect changes to them.
6513 We don't want to rely solely on Alter_info flags for this since:
6514 a) new definition of column can be fully identical to the old one
6515 despite the fact that this column is mentioned in MODIFY clause.
6516 b) even if new column type differs from its old column from metadata
6517 point of view, it might be identical from storage engine point
6518 of view (e.g. when ENUM('a','b') is changed to ENUM('a','b',c')).
6519 c) flags passed to storage engine contain more detailed information
6520 about nature of changes than those provided from parser.
6521 */
6522 bool maybe_alter_vcol= false;
6523 uint field_stored_index= 0;
6524 for (f_ptr= table->field; (field= *f_ptr); f_ptr++,
6525 field_stored_index+= field->stored_in_db())
6526 {
6527 /* Clear marker for renamed or dropped field
6528 which we are going to set later. */
6529 field->flags&= ~(FIELD_IS_RENAMED | FIELD_IS_DROPPED);
6530
6531 /* Use transformed info to evaluate flags for storage engine. */
6532 uint new_field_index= 0, new_field_stored_index= 0;
6533 new_field_it.init(alter_info->create_list);
6534 while ((new_field= new_field_it++))
6535 {
6536 if (new_field->field == field)
6537 break;
6538 new_field_index++;
6539 new_field_stored_index+= new_field->stored_in_db();
6540 }
6541
6542 if (new_field)
6543 {
6544 /* Field is not dropped. Evaluate changes bitmap for it. */
6545
6546 /*
6547 Check if type of column has changed to some incompatible type.
6548 */
6549 uint is_equal= field->is_equal(new_field);
6550 switch (is_equal)
6551 {
6552 case IS_EQUAL_NO:
6553 /* New column type is incompatible with old one. */
6554 if (field->stored_in_db())
6555 ha_alter_info->handler_flags|= ALTER_STORED_COLUMN_TYPE;
6556 else
6557 ha_alter_info->handler_flags|= ALTER_VIRTUAL_COLUMN_TYPE;
6558 if (table->s->tmp_table == NO_TMP_TABLE)
6559 {
6560 delete_statistics_for_column(thd, table, field);
6561 KEY *key_info= table->key_info;
6562 for (uint i=0; i < table->s->keys; i++, key_info++)
6563 {
6564 if (field->part_of_key.is_set(i))
6565 {
6566 uint key_parts= table->actual_n_key_parts(key_info);
6567 for (uint j= 0; j < key_parts; j++)
6568 {
6569 if (key_info->key_part[j].fieldnr-1 == field->field_index)
6570 {
6571 delete_statistics_for_index(thd, table, key_info,
6572 j >= key_info->user_defined_key_parts);
6573 break;
6574 }
6575 }
6576 }
6577 }
6578 }
6579 break;
6580 case IS_EQUAL_YES:
6581 /*
6582 New column is the same as the old one or the fully compatible with
6583 it (for example, ENUM('a','b') was changed to ENUM('a','b','c')).
6584 Such a change if any can ALWAYS be carried out by simply updating
6585 data-dictionary without even informing storage engine.
6586 No flag is set in this case.
6587 */
6588 break;
6589 case IS_EQUAL_PACK_LENGTH:
6590 /*
6591 New column type differs from the old one, but has compatible packed
6592 data representation. Depending on storage engine, such a change can
6593 be carried out by simply updating data dictionary without changing
6594 actual data (for example, VARCHAR(300) is changed to VARCHAR(400)).
6595 */
6596 ha_alter_info->handler_flags|= ALTER_COLUMN_EQUAL_PACK_LENGTH;
6597 break;
6598 default:
6599 DBUG_ASSERT(0);
6600 /* Safety. */
6601 ha_alter_info->handler_flags|= ALTER_STORED_COLUMN_TYPE;
6602 }
6603
6604 if (field->vcol_info || new_field->vcol_info)
6605 {
6606 /* base <-> virtual or stored <-> virtual */
6607 if (field->stored_in_db() != new_field->stored_in_db())
6608 ha_alter_info->handler_flags|= ( ALTER_STORED_COLUMN_TYPE |
6609 ALTER_VIRTUAL_COLUMN_TYPE);
6610 if (field->vcol_info && new_field->vcol_info)
6611 {
6612 bool value_changes= is_equal == IS_EQUAL_NO;
6613 alter_table_operations alter_expr;
6614 if (field->stored_in_db())
6615 alter_expr= ALTER_STORED_GCOL_EXPR;
6616 else
6617 alter_expr= ALTER_VIRTUAL_GCOL_EXPR;
6618 if (!field->vcol_info->is_equal(new_field->vcol_info))
6619 {
6620 ha_alter_info->handler_flags|= alter_expr;
6621 value_changes= true;
6622 }
6623
6624 if ((ha_alter_info->handler_flags & ALTER_COLUMN_DEFAULT)
6625 && !(ha_alter_info->handler_flags & alter_expr))
6626 { /*
6627 a DEFAULT value of a some column was changed. see if this vcol
6628 uses DEFAULT() function. The check is kind of expensive, so don't
6629 do it if ALTER_COLUMN_VCOL is already set.
6630 */
6631 if (field->vcol_info->expr->walk(
6632 &Item::check_func_default_processor, 0, 0))
6633 {
6634 ha_alter_info->handler_flags|= alter_expr;
6635 value_changes= true;
6636 }
6637 }
6638
6639 if (field->vcol_info->is_in_partitioning_expr() ||
6640 field->flags & PART_KEY_FLAG)
6641 {
6642 if (value_changes)
6643 ha_alter_info->handler_flags|= ALTER_COLUMN_VCOL;
6644 else
6645 maybe_alter_vcol= true;
6646 }
6647 }
6648 else /* base <-> stored */
6649 ha_alter_info->handler_flags|= ALTER_STORED_COLUMN_TYPE;
6650 }
6651
6652 /* Check if field was renamed */
6653 if (lex_string_cmp(system_charset_info, &field->field_name,
6654 &new_field->field_name))
6655 {
6656 field->flags|= FIELD_IS_RENAMED;
6657 ha_alter_info->handler_flags|= ALTER_COLUMN_NAME;
6658 rename_column_in_stat_tables(thd, table, field,
6659 new_field->field_name.str);
6660 }
6661
6662 /* Check that NULL behavior is same for old and new fields */
6663 if ((new_field->flags & NOT_NULL_FLAG) !=
6664 (uint) (field->flags & NOT_NULL_FLAG))
6665 {
6666 if (new_field->flags & NOT_NULL_FLAG)
6667 ha_alter_info->handler_flags|= ALTER_COLUMN_NOT_NULLABLE;
6668 else
6669 ha_alter_info->handler_flags|= ALTER_COLUMN_NULLABLE;
6670 }
6671
6672 /*
6673 We do not detect changes to default values in this loop.
6674 See comment above for more details.
6675 */
6676
6677 /*
6678 Detect changes in column order.
6679 */
6680 if (field->stored_in_db())
6681 {
6682 if (field_stored_index != new_field_stored_index)
6683 ha_alter_info->handler_flags|= ALTER_STORED_COLUMN_ORDER;
6684 }
6685 else
6686 {
6687 if (field->field_index != new_field_index)
6688 ha_alter_info->handler_flags|= ALTER_VIRTUAL_COLUMN_ORDER;
6689 }
6690
6691 /* Detect changes in storage type of column */
6692 if (new_field->field_storage_type() != field->field_storage_type())
6693 ha_alter_info->handler_flags|= ALTER_COLUMN_STORAGE_TYPE;
6694
6695 /* Detect changes in column format of column */
6696 if (new_field->column_format() != field->column_format())
6697 ha_alter_info->handler_flags|= ALTER_COLUMN_COLUMN_FORMAT;
6698
6699 if (engine_options_differ(field->option_struct, new_field->option_struct,
6700 table->file->ht->field_options))
6701 {
6702 ha_alter_info->handler_flags|= ALTER_COLUMN_OPTION;
6703 ha_alter_info->create_info->fields_option_struct[f_ptr - table->field]=
6704 new_field->option_struct;
6705 }
6706
6707 }
6708 else
6709 {
6710 // Field is not present in new version of table and therefore was dropped.
6711 field->flags|= FIELD_IS_DROPPED;
6712 if (field->stored_in_db())
6713 ha_alter_info->handler_flags|= ALTER_DROP_STORED_COLUMN;
6714 else
6715 ha_alter_info->handler_flags|= ALTER_DROP_VIRTUAL_COLUMN;
6716 }
6717 }
6718
6719 if (maybe_alter_vcol)
6720 {
6721 /*
6722 What if one of the normal columns was altered and it was part of the some
6723 virtual column expression? Currently we don't detect this correctly
6724 (FIXME), so let's just say that a vcol *might* be affected if any other
6725 column was altered.
6726 */
6727 if (ha_alter_info->handler_flags & (ALTER_STORED_COLUMN_TYPE |
6728 ALTER_VIRTUAL_COLUMN_TYPE |
6729 ALTER_COLUMN_NOT_NULLABLE |
6730 ALTER_COLUMN_OPTION))
6731 ha_alter_info->handler_flags|= ALTER_COLUMN_VCOL;
6732 }
6733
6734 new_field_it.init(alter_info->create_list);
6735 while ((new_field= new_field_it++))
6736 {
6737 if (! new_field->field)
6738 {
6739 // Field is not present in old version of table and therefore was added.
6740 if (new_field->vcol_info)
6741 {
6742 if (new_field->stored_in_db())
6743 ha_alter_info->handler_flags|= ALTER_ADD_STORED_GENERATED_COLUMN;
6744 else
6745 ha_alter_info->handler_flags|= ALTER_ADD_VIRTUAL_COLUMN;
6746 }
6747 else
6748 ha_alter_info->handler_flags|= ALTER_ADD_STORED_BASE_COLUMN;
6749 }
6750 }
6751
6752 /*
6753 Go through keys and check if the original ones are compatible
6754 with new table.
6755 */
6756 KEY *table_key;
6757 KEY *table_key_end= table->key_info + table->s->keys;
6758 KEY *new_key;
6759 KEY *new_key_end=
6760 ha_alter_info->key_info_buffer + ha_alter_info->key_count;
6761
6762 DBUG_PRINT("info", ("index count old: %d new: %d",
6763 table->s->keys, ha_alter_info->key_count));
6764
6765 /*
6766 Step through all keys of the old table and search matching new keys.
6767 */
6768 ha_alter_info->index_drop_count= 0;
6769 ha_alter_info->index_add_count= 0;
6770 for (table_key= table->key_info; table_key < table_key_end; table_key++)
6771 {
6772 /* Search a new key with the same name. */
6773 for (new_key= ha_alter_info->key_info_buffer;
6774 new_key < new_key_end;
6775 new_key++)
6776 {
6777 if (!lex_string_cmp(system_charset_info, &table_key->name,
6778 &new_key->name))
6779 break;
6780 }
6781 if (new_key >= new_key_end)
6782 {
6783 /* Key not found. Add the key to the drop buffer. */
6784 ha_alter_info->index_drop_buffer
6785 [ha_alter_info->index_drop_count++]=
6786 table_key;
6787 DBUG_PRINT("info", ("index dropped: '%s'", table_key->name.str));
6788 continue;
6789 }
6790
6791 /* Check that the key types are compatible between old and new tables. */
6792 if ((table_key->algorithm != new_key->algorithm) ||
6793 ((table_key->flags & HA_KEYFLAG_MASK) !=
6794 (new_key->flags & HA_KEYFLAG_MASK)) ||
6795 (table_key->user_defined_key_parts !=
6796 new_key->user_defined_key_parts))
6797 goto index_changed;
6798
6799 if (table_key->block_size != new_key->block_size)
6800 goto index_changed;
6801
6802 if (engine_options_differ(table_key->option_struct, new_key->option_struct,
6803 table->file->ht->index_options))
6804 goto index_changed;
6805
6806 /*
6807 Check that the key parts remain compatible between the old and
6808 new tables.
6809 */
6810 end= table_key->key_part + table_key->user_defined_key_parts;
6811 for (key_part= table_key->key_part, new_part= new_key->key_part;
6812 key_part < end;
6813 key_part++, new_part++)
6814 {
6815 /*
6816 Key definition has changed if we are using a different field or
6817 if the used key part length is different. It makes sense to
6818 check lengths first as in case when fields differ it is likely
6819 that lengths differ too and checking fields is more expensive
6820 in general case.
6821 */
6822 if (key_part->length != new_part->length)
6823 goto index_changed;
6824
6825 new_field= get_field_by_index(alter_info, new_part->fieldnr);
6826
6827 /*
6828 For prefix keys KEY_PART_INFO::field points to cloned Field
6829 object with adjusted length. So below we have to check field
6830 indexes instead of simply comparing pointers to Field objects.
6831 */
6832 if (! new_field->field ||
6833 new_field->field->field_index != key_part->fieldnr - 1)
6834 goto index_changed;
6835 }
6836
6837 /* Check that key comment is not changed. */
6838 if (table_key->comment.length != new_key->comment.length ||
6839 (table_key->comment.length &&
6840 memcmp(table_key->comment.str, new_key->comment.str,
6841 table_key->comment.length) != 0))
6842 goto index_changed;
6843
6844 continue;
6845
6846 index_changed:
6847 /* Key modified. Add the key / key offset to both buffers. */
6848 ha_alter_info->index_drop_buffer
6849 [ha_alter_info->index_drop_count++]=
6850 table_key;
6851 ha_alter_info->index_add_buffer
6852 [ha_alter_info->index_add_count++]=
6853 (uint)(new_key - ha_alter_info->key_info_buffer);
6854 /* Mark all old fields which are used in newly created index. */
6855 DBUG_PRINT("info", ("index changed: '%s'", table_key->name.str));
6856 }
6857 /*end of for (; table_key < table_key_end;) */
6858
6859 /*
6860 Step through all keys of the new table and find matching old keys.
6861 */
6862 for (new_key= ha_alter_info->key_info_buffer;
6863 new_key < new_key_end;
6864 new_key++)
6865 {
6866 /* Search an old key with the same name. */
6867 for (table_key= table->key_info; table_key < table_key_end; table_key++)
6868 {
6869 if (!lex_string_cmp(system_charset_info, &table_key->name,
6870 &new_key->name))
6871 break;
6872 }
6873 if (table_key >= table_key_end)
6874 {
6875 /* Key not found. Add the offset of the key to the add buffer. */
6876 ha_alter_info->index_add_buffer
6877 [ha_alter_info->index_add_count++]=
6878 (uint)(new_key - ha_alter_info->key_info_buffer);
6879 DBUG_PRINT("info", ("index added: '%s'", new_key->name.str));
6880 }
6881 else
6882 ha_alter_info->create_info->indexes_option_struct[table_key - table->key_info]=
6883 new_key->option_struct;
6884 }
6885
6886 /*
6887 Sort index_add_buffer according to how key_info_buffer is sorted.
6888 I.e. with primary keys first - see sort_keys().
6889 */
6890 my_qsort(ha_alter_info->index_add_buffer,
6891 ha_alter_info->index_add_count,
6892 sizeof(uint), (qsort_cmp) compare_uint);
6893
6894 /* Now let us calculate flags for storage engine API. */
6895
6896 /* Count all existing candidate keys. */
6897 for (table_key= table->key_info; table_key < table_key_end; table_key++)
6898 {
6899 /*
6900 Check if key is a candidate key, This key is either already primary key
6901 or could be promoted to primary key if the original primary key is
6902 dropped.
6903 In MySQL one is allowed to create primary key with partial fields (i.e.
6904 primary key which is not considered candidate). For simplicity we count
6905 such key as a candidate key here.
6906 */
6907 if (((uint) (table_key - table->key_info) == table->s->primary_key) ||
6908 is_candidate_key(table_key))
6909 candidate_key_count++;
6910 }
6911
6912 /* Figure out what kind of indexes we are dropping. */
6913 KEY **dropped_key;
6914 KEY **dropped_key_end= ha_alter_info->index_drop_buffer +
6915 ha_alter_info->index_drop_count;
6916
6917 for (dropped_key= ha_alter_info->index_drop_buffer;
6918 dropped_key < dropped_key_end; dropped_key++)
6919 {
6920 table_key= *dropped_key;
6921
6922 if (table_key->flags & HA_NOSAME)
6923 {
6924 /*
6925 Unique key. Check for PRIMARY KEY. Also see comment about primary
6926 and candidate keys above.
6927 */
6928 if ((uint) (table_key - table->key_info) == table->s->primary_key)
6929 {
6930 ha_alter_info->handler_flags|= ALTER_DROP_PK_INDEX;
6931 candidate_key_count--;
6932 }
6933 else
6934 {
6935 ha_alter_info->handler_flags|= ALTER_DROP_UNIQUE_INDEX;
6936 if (is_candidate_key(table_key))
6937 candidate_key_count--;
6938 }
6939 }
6940 else
6941 ha_alter_info->handler_flags|= ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX;
6942 }
6943
6944 /* Now figure out what kind of indexes we are adding. */
6945 for (uint add_key_idx= 0; add_key_idx < ha_alter_info->index_add_count; add_key_idx++)
6946 {
6947 new_key= ha_alter_info->key_info_buffer + ha_alter_info->index_add_buffer[add_key_idx];
6948
6949 if (new_key->flags & HA_NOSAME)
6950 {
6951 bool is_pk= !my_strcasecmp(system_charset_info,
6952 new_key->name.str, primary_key_name);
6953
6954 if ((!(new_key->flags & HA_KEY_HAS_PART_KEY_SEG) &&
6955 !(new_key->flags & HA_NULL_PART_KEY)) ||
6956 is_pk)
6957 {
6958 /* Candidate key or primary key! */
6959 if (candidate_key_count == 0 || is_pk)
6960 ha_alter_info->handler_flags|= ALTER_ADD_PK_INDEX;
6961 else
6962 ha_alter_info->handler_flags|= ALTER_ADD_UNIQUE_INDEX;
6963 candidate_key_count++;
6964 }
6965 else
6966 {
6967 ha_alter_info->handler_flags|= ALTER_ADD_UNIQUE_INDEX;
6968 }
6969 }
6970 else
6971 ha_alter_info->handler_flags|= ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX;
6972 }
6973
6974 DBUG_PRINT("exit", ("handler_flags: %llu", ha_alter_info->handler_flags));
6975 DBUG_RETURN(false);
6976}
6977
6978
6979/**
6980 Mark fields participating in newly added indexes in TABLE object which
6981 corresponds to new version of altered table.
6982
6983 @param ha_alter_info Alter_inplace_info describing in-place ALTER.
6984 @param altered_table TABLE object for new version of TABLE in which
6985 fields should be marked.
6986*/
6987
6988static void update_altered_table(const Alter_inplace_info &ha_alter_info,
6989 TABLE *altered_table)
6990{
6991 uint field_idx, add_key_idx;
6992 KEY *key;
6993 KEY_PART_INFO *end, *key_part;
6994
6995 /*
6996 Clear marker for all fields, as we are going to set it only
6997 for fields which participate in new indexes.
6998 */
6999 for (field_idx= 0; field_idx < altered_table->s->fields; ++field_idx)
7000 altered_table->field[field_idx]->flags&= ~FIELD_IN_ADD_INDEX;
7001
7002 /*
7003 Go through array of newly added indexes and mark fields
7004 participating in them.
7005 */
7006 for (add_key_idx= 0; add_key_idx < ha_alter_info.index_add_count;
7007 add_key_idx++)
7008 {
7009 key= ha_alter_info.key_info_buffer +
7010 ha_alter_info.index_add_buffer[add_key_idx];
7011
7012 end= key->key_part + key->user_defined_key_parts;
7013 for (key_part= key->key_part; key_part < end; key_part++)
7014 altered_table->field[key_part->fieldnr]->flags|= FIELD_IN_ADD_INDEX;
7015 }
7016}
7017
7018
7019/**
7020 Compare two tables to see if their metadata are compatible.
7021 One table specified by a TABLE instance, the other using Alter_info
7022 and HA_CREATE_INFO.
7023
7024 @param[in] table The first table.
7025 @param[in] alter_info Alter options, fields and keys for the
7026 second table.
7027 @param[in] create_info Create options for the second table.
7028 @param[out] metadata_equal Result of comparison.
7029
7030 @retval true error
7031 @retval false success
7032*/
7033
7034bool mysql_compare_tables(TABLE *table,
7035 Alter_info *alter_info,
7036 HA_CREATE_INFO *create_info,
7037 bool *metadata_equal)
7038{
7039 DBUG_ENTER("mysql_compare_tables");
7040
7041 uint changes= IS_EQUAL_NO;
7042 uint key_count;
7043 List_iterator_fast<Create_field> tmp_new_field_it;
7044 THD *thd= table->in_use;
7045 *metadata_equal= false;
7046
7047 /*
7048 Create a copy of alter_info.
7049 To compare definitions, we need to "prepare" the definition - transform it
7050 from parser output to a format that describes the table layout (all column
7051 defaults are initialized, duplicate columns are removed). This is done by
7052 mysql_prepare_create_table. Unfortunately, mysql_prepare_create_table
7053 performs its transformations "in-place", that is, modifies the argument.
7054 Since we would like to keep mysql_compare_tables() idempotent (not altering
7055 any of the arguments) we create a copy of alter_info here and pass it to
7056 mysql_prepare_create_table, then use the result to compare the tables, and
7057 then destroy the copy.
7058 */
7059 Alter_info tmp_alter_info(*alter_info, thd->mem_root);
7060 uint db_options= 0; /* not used */
7061 KEY *key_info_buffer= NULL;
7062
7063 /* Create the prepared information. */
7064 int create_table_mode= table->s->tmp_table == NO_TMP_TABLE ?
7065 C_ORDINARY_CREATE : C_ALTER_TABLE;
7066 if (mysql_prepare_create_table(thd, create_info, &tmp_alter_info,
7067 &db_options, table->file, &key_info_buffer,
7068 &key_count, create_table_mode))
7069 DBUG_RETURN(1);
7070
7071 /* Some very basic checks. */
7072 if (table->s->fields != alter_info->create_list.elements ||
7073 table->s->db_type() != create_info->db_type ||
7074 table->s->tmp_table ||
7075 (table->s->row_type != create_info->row_type))
7076 DBUG_RETURN(false);
7077
7078 /* Go through fields and check if they are compatible. */
7079 tmp_new_field_it.init(tmp_alter_info.create_list);
7080 for (Field **f_ptr= table->field; *f_ptr; f_ptr++)
7081 {
7082 Field *field= *f_ptr;
7083 Create_field *tmp_new_field= tmp_new_field_it++;
7084
7085 /* Check that NULL behavior is the same. */
7086 if ((tmp_new_field->flags & NOT_NULL_FLAG) !=
7087 (uint) (field->flags & NOT_NULL_FLAG))
7088 DBUG_RETURN(false);
7089
7090 /*
7091 mysql_prepare_alter_table() clears HA_OPTION_PACK_RECORD bit when
7092 preparing description of existing table. In ALTER TABLE it is later
7093 updated to correct value by create_table_impl() call.
7094 So to get correct value of this bit in this function we have to
7095 mimic behavior of create_table_impl().
7096 */
7097 if (create_info->row_type == ROW_TYPE_DYNAMIC ||
7098 create_info->row_type == ROW_TYPE_PAGE ||
7099 (tmp_new_field->flags & BLOB_FLAG) ||
7100 (tmp_new_field->real_field_type() == MYSQL_TYPE_VARCHAR &&
7101 create_info->row_type != ROW_TYPE_FIXED))
7102 create_info->table_options|= HA_OPTION_PACK_RECORD;
7103
7104 /* Check if field was renamed */
7105 if (lex_string_cmp(system_charset_info,
7106 &field->field_name,
7107 &tmp_new_field->field_name))
7108 DBUG_RETURN(false);
7109
7110 /* Evaluate changes bitmap and send to check_if_incompatible_data() */
7111 uint field_changes= field->is_equal(tmp_new_field);
7112 if (field_changes != IS_EQUAL_YES)
7113 DBUG_RETURN(false);
7114
7115 changes|= field_changes;
7116 }
7117
7118 /* Check if changes are compatible with current handler. */
7119 if (table->file->check_if_incompatible_data(create_info, changes))
7120 DBUG_RETURN(false);
7121
7122 /* Go through keys and check if they are compatible. */
7123 KEY *table_key;
7124 KEY *table_key_end= table->key_info + table->s->keys;
7125 KEY *new_key;
7126 KEY *new_key_end= key_info_buffer + key_count;
7127
7128 /* Step through all keys of the first table and search matching keys. */
7129 for (table_key= table->key_info; table_key < table_key_end; table_key++)
7130 {
7131 /* Search a key with the same name. */
7132 for (new_key= key_info_buffer; new_key < new_key_end; new_key++)
7133 {
7134 if (!lex_string_cmp(system_charset_info, &table_key->name,
7135 &new_key->name))
7136 break;
7137 }
7138 if (new_key >= new_key_end)
7139 DBUG_RETURN(false);
7140
7141 /* Check that the key types are compatible. */
7142 if ((table_key->algorithm != new_key->algorithm) ||
7143 ((table_key->flags & HA_KEYFLAG_MASK) !=
7144 (new_key->flags & HA_KEYFLAG_MASK)) ||
7145 (table_key->user_defined_key_parts !=
7146 new_key->user_defined_key_parts))
7147 DBUG_RETURN(false);
7148
7149 /* Check that the key parts remain compatible. */
7150 KEY_PART_INFO *table_part;
7151 KEY_PART_INFO *table_part_end= table_key->key_part + table_key->user_defined_key_parts;
7152 KEY_PART_INFO *new_part;
7153 for (table_part= table_key->key_part, new_part= new_key->key_part;
7154 table_part < table_part_end;
7155 table_part++, new_part++)
7156 {
7157 /*
7158 Key definition is different if we are using a different field or
7159 if the used key part length is different. We know that the fields
7160 are equal. Comparing field numbers is sufficient.
7161 */
7162 if ((table_part->length != new_part->length) ||
7163 (table_part->fieldnr - 1 != new_part->fieldnr))
7164 DBUG_RETURN(false);
7165 }
7166 }
7167
7168 /* Step through all keys of the second table and find matching keys. */
7169 for (new_key= key_info_buffer; new_key < new_key_end; new_key++)
7170 {
7171 /* Search a key with the same name. */
7172 for (table_key= table->key_info; table_key < table_key_end; table_key++)
7173 {
7174 if (!lex_string_cmp(system_charset_info, &table_key->name,
7175 &new_key->name))
7176 break;
7177 }
7178 if (table_key >= table_key_end)
7179 DBUG_RETURN(false);
7180 }
7181
7182 *metadata_equal= true; // Tables are compatible
7183 DBUG_RETURN(false);
7184}
7185
7186
7187/*
7188 Manages enabling/disabling of indexes for ALTER TABLE
7189
7190 SYNOPSIS
7191 alter_table_manage_keys()
7192 table Target table
7193 indexes_were_disabled Whether the indexes of the from table
7194 were disabled
7195 keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
7196
7197 RETURN VALUES
7198 FALSE OK
7199 TRUE Error
7200*/
7201
7202static
7203bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
7204 Alter_info::enum_enable_or_disable keys_onoff)
7205{
7206 int error= 0;
7207 DBUG_ENTER("alter_table_manage_keys");
7208 DBUG_PRINT("enter", ("table=%p were_disabled=%d on_off=%d",
7209 table, indexes_were_disabled, keys_onoff));
7210
7211 switch (keys_onoff) {
7212 case Alter_info::ENABLE:
7213 DEBUG_SYNC(table->in_use, "alter_table_enable_indexes");
7214 error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
7215 break;
7216 case Alter_info::LEAVE_AS_IS:
7217 if (!indexes_were_disabled)
7218 break;
7219 /* fall through */
7220 case Alter_info::DISABLE:
7221 error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
7222 }
7223
7224 if (unlikely(error))
7225 {
7226 if (error == HA_ERR_WRONG_COMMAND)
7227 {
7228 THD *thd= table->in_use;
7229 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
7230 ER_ILLEGAL_HA, ER_THD(thd, ER_ILLEGAL_HA),
7231 table->file->table_type(),
7232 table->s->db.str, table->s->table_name.str);
7233 error= 0;
7234 }
7235 else
7236 table->file->print_error(error, MYF(0));
7237 }
7238 DBUG_RETURN(error);
7239}
7240
7241
7242/**
7243 Check if the pending ALTER TABLE operations support the in-place
7244 algorithm based on restrictions in the SQL layer or given the
7245 nature of the operations themselves. If in-place isn't supported,
7246 it won't be necessary to check with the storage engine.
7247
7248 @param table The original TABLE.
7249 @param create_info Information from the parsing phase about new
7250 table properties.
7251 @param alter_info Data related to detected changes.
7252
7253 @return false In-place is possible, check with storage engine.
7254 @return true Incompatible operations, must use table copy.
7255*/
7256
7257static bool is_inplace_alter_impossible(TABLE *table,
7258 HA_CREATE_INFO *create_info,
7259 const Alter_info *alter_info)
7260{
7261 DBUG_ENTER("is_inplace_alter_impossible");
7262
7263 /* At the moment we can't handle altering temporary tables without a copy. */
7264 if (table->s->tmp_table)
7265 DBUG_RETURN(true);
7266
7267 /*
7268 For the ALTER TABLE tbl_name ORDER BY ... we always use copy
7269 algorithm. In theory, this operation can be done in-place by some
7270 engine, but since a) no current engine does this and b) our current
7271 API lacks infrastructure for passing information about table ordering
7272 to storage engine we simply always do copy now.
7273
7274 ENABLE/DISABLE KEYS is a MyISAM/Heap specific operation that is
7275 not supported for in-place in combination with other operations.
7276 Alone, it will be done by simple_rename_or_index_change().
7277 */
7278 if (alter_info->flags & (ALTER_ORDER | ALTER_KEYS_ONOFF))
7279 DBUG_RETURN(true);
7280
7281 /*
7282 If the table engine is changed explicitly (using ENGINE clause)
7283 or implicitly (e.g. when non-partitioned table becomes
7284 partitioned) a regular alter table (copy) needs to be
7285 performed.
7286 */
7287 if (create_info->db_type != table->s->db_type())
7288 DBUG_RETURN(true);
7289
7290 /*
7291 There was a bug prior to mysql-4.0.25. Number of null fields was
7292 calculated incorrectly. As a result frm and data files gets out of
7293 sync after fast alter table. There is no way to determine by which
7294 mysql version (in 4.0 and 4.1 branches) table was created, thus we
7295 disable fast alter table for all tables created by mysql versions
7296 prior to 5.0 branch.
7297 See BUG#6236.
7298 */
7299 if (!table->s->mysql_version)
7300 DBUG_RETURN(true);
7301
7302 /*
7303 If we are using a MySQL 5.7 table with virtual fields, ALTER TABLE must
7304 recreate the table as we need to rewrite generated fields
7305 */
7306 if (table->s->mysql_version > 50700 && table->s->mysql_version < 100000 &&
7307 table->s->virtual_fields)
7308 DBUG_RETURN(TRUE);
7309
7310 DBUG_RETURN(false);
7311}
7312
7313
7314/**
7315 Perform in-place alter table.
7316
7317 @param thd Thread handle.
7318 @param table_list TABLE_LIST for the table to change.
7319 @param table The original TABLE.
7320 @param altered_table TABLE object for new version of the table.
7321 @param ha_alter_info Structure describing ALTER TABLE to be carried
7322 out and serving as a storage place for data
7323 used during different phases.
7324 @param inplace_supported Enum describing the locking requirements.
7325 @param target_mdl_request Metadata request/lock on the target table name.
7326 @param alter_ctx ALTER TABLE runtime context.
7327
7328 @retval true Error
7329 @retval false Success
7330
7331 @note
7332 If mysql_alter_table does not need to copy the table, it is
7333 either an alter table where the storage engine does not
7334 need to know about the change, only the frm will change,
7335 or the storage engine supports performing the alter table
7336 operation directly, in-place without mysql having to copy
7337 the table.
7338
7339 @note This function frees the TABLE object associated with the new version of
7340 the table and removes the .FRM file for it in case of both success and
7341 failure.
7342*/
7343
7344static bool mysql_inplace_alter_table(THD *thd,
7345 TABLE_LIST *table_list,
7346 TABLE *table,
7347 TABLE *altered_table,
7348 Alter_inplace_info *ha_alter_info,
7349 enum_alter_inplace_result inplace_supported,
7350 MDL_request *target_mdl_request,
7351 Alter_table_ctx *alter_ctx)
7352{
7353 Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN | MYSQL_OPEN_IGNORE_KILLED);
7354 handlerton *db_type= table->s->db_type();
7355 MDL_ticket *mdl_ticket= table->mdl_ticket;
7356 HA_CREATE_INFO *create_info= ha_alter_info->create_info;
7357 Alter_info *alter_info= ha_alter_info->alter_info;
7358 bool reopen_tables= false;
7359 bool res;
7360
7361 DBUG_ENTER("mysql_inplace_alter_table");
7362
7363 /*
7364 Upgrade to EXCLUSIVE lock if:
7365 - This is requested by the storage engine
7366 - Or the storage engine needs exclusive lock for just the prepare
7367 phase
7368 - Or requested by the user
7369
7370 Note that we handle situation when storage engine needs exclusive
7371 lock for prepare phase under LOCK TABLES in the same way as when
7372 exclusive lock is required for duration of the whole statement.
7373 */
7374 if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
7375 ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
7376 inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
7377 inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK ||
7378 inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
7379 inplace_supported == HA_ALTER_INPLACE_INSTANT) &&
7380 (thd->locked_tables_mode == LTM_LOCK_TABLES ||
7381 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) ||
7382 alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)
7383 {
7384 if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
7385 goto cleanup;
7386 /*
7387 Get rid of all TABLE instances belonging to this thread
7388 except one to be used for in-place ALTER TABLE.
7389
7390 This is mostly needed to satisfy InnoDB assumptions/asserts.
7391 */
7392 close_all_tables_for_name(thd, table->s,
7393 alter_ctx->is_table_renamed() ?
7394 HA_EXTRA_PREPARE_FOR_RENAME :
7395 HA_EXTRA_NOT_USED,
7396 table);
7397 /*
7398 If we are under LOCK TABLES we will need to reopen tables which we
7399 just have closed in case of error.
7400 */
7401 reopen_tables= true;
7402 }
7403 else if (inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
7404 inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
7405 inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
7406 inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK ||
7407 inplace_supported == HA_ALTER_INPLACE_INSTANT)
7408 {
7409 /*
7410 Storage engine has requested exclusive lock only for prepare phase
7411 and we are not under LOCK TABLES.
7412 Don't mark TABLE_SHARE as old in this case, as this won't allow opening
7413 of table by other threads during main phase of in-place ALTER TABLE.
7414 */
7415 if (thd->mdl_context.upgrade_shared_lock(table->mdl_ticket, MDL_EXCLUSIVE,
7416 thd->variables.lock_wait_timeout))
7417 goto cleanup;
7418
7419 tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE,
7420 table->s->db.str, table->s->table_name.str,
7421 false);
7422 }
7423
7424 /*
7425 Upgrade to SHARED_NO_WRITE lock if:
7426 - The storage engine needs writes blocked for the whole duration
7427 - Or this is requested by the user
7428 Note that under LOCK TABLES, we will already have SHARED_NO_READ_WRITE.
7429 */
7430 if ((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK ||
7431 alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED) &&
7432 thd->mdl_context.upgrade_shared_lock(table->mdl_ticket,
7433 MDL_SHARED_NO_WRITE,
7434 thd->variables.lock_wait_timeout))
7435 {
7436 goto cleanup;
7437 }
7438
7439 // It's now safe to take the table level lock.
7440 if (lock_tables(thd, table_list, alter_ctx->tables_opened, 0))
7441 goto cleanup;
7442
7443 DEBUG_SYNC(thd, "alter_table_inplace_after_lock_upgrade");
7444 THD_STAGE_INFO(thd, stage_alter_inplace_prepare);
7445
7446 switch (inplace_supported) {
7447 case HA_ALTER_ERROR:
7448 case HA_ALTER_INPLACE_NOT_SUPPORTED:
7449 DBUG_ASSERT(0);
7450 // fall through
7451 case HA_ALTER_INPLACE_NO_LOCK:
7452 case HA_ALTER_INPLACE_INSTANT:
7453 case HA_ALTER_INPLACE_COPY_NO_LOCK:
7454 case HA_ALTER_INPLACE_NOCOPY_NO_LOCK:
7455 switch (alter_info->requested_lock) {
7456 case Alter_info::ALTER_TABLE_LOCK_DEFAULT:
7457 case Alter_info::ALTER_TABLE_LOCK_NONE:
7458 ha_alter_info->online= true;
7459 break;
7460 case Alter_info::ALTER_TABLE_LOCK_SHARED:
7461 case Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE:
7462 break;
7463 }
7464 break;
7465 case HA_ALTER_INPLACE_EXCLUSIVE_LOCK:
7466 case HA_ALTER_INPLACE_SHARED_LOCK:
7467 case HA_ALTER_INPLACE_COPY_LOCK:
7468 case HA_ALTER_INPLACE_NOCOPY_LOCK:
7469 break;
7470 }
7471
7472 if (table->file->ha_prepare_inplace_alter_table(altered_table,
7473 ha_alter_info))
7474 {
7475 goto rollback;
7476 }
7477
7478 /*
7479 Downgrade the lock if storage engine has told us that exclusive lock was
7480 necessary only for prepare phase (unless we are not under LOCK TABLES) and
7481 user has not explicitly requested exclusive lock.
7482 */
7483 if ((inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
7484 inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
7485 inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
7486 inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK) &&
7487 !(thd->locked_tables_mode == LTM_LOCK_TABLES ||
7488 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) &&
7489 (alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE))
7490 {
7491 /* If storage engine or user requested shared lock downgrade to SNW. */
7492 if (inplace_supported == HA_ALTER_INPLACE_COPY_LOCK ||
7493 inplace_supported == HA_ALTER_INPLACE_NOCOPY_LOCK ||
7494 alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED)
7495 table->mdl_ticket->downgrade_lock(MDL_SHARED_NO_WRITE);
7496 else
7497 {
7498 DBUG_ASSERT(inplace_supported == HA_ALTER_INPLACE_COPY_NO_LOCK ||
7499 inplace_supported == HA_ALTER_INPLACE_NOCOPY_NO_LOCK);
7500 table->mdl_ticket->downgrade_lock(MDL_SHARED_UPGRADABLE);
7501 }
7502 }
7503
7504 DEBUG_SYNC(thd, "alter_table_inplace_after_lock_downgrade");
7505 THD_STAGE_INFO(thd, stage_alter_inplace);
7506
7507 /* We can abort alter table for any table type */
7508 thd->abort_on_warning= !ha_alter_info->ignore && thd->is_strict_mode();
7509 res= table->file->ha_inplace_alter_table(altered_table, ha_alter_info);
7510 thd->abort_on_warning= false;
7511 if (res)
7512 goto rollback;
7513
7514 // Upgrade to EXCLUSIVE before commit.
7515 if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
7516 goto rollback;
7517
7518 /*
7519 If we are killed after this point, we should ignore and continue.
7520 We have mostly completed the operation at this point, there should
7521 be no long waits left.
7522 */
7523
7524 DBUG_EXECUTE_IF("alter_table_rollback_new_index", {
7525 table->file->ha_commit_inplace_alter_table(altered_table,
7526 ha_alter_info,
7527 false);
7528 my_error(ER_UNKNOWN_ERROR, MYF(0));
7529 goto cleanup;
7530 });
7531
7532 DEBUG_SYNC(thd, "alter_table_inplace_before_commit");
7533 THD_STAGE_INFO(thd, stage_alter_inplace_commit);
7534
7535 {
7536 TR_table trt(thd, true);
7537 if (trt != *table_list && table->file->ht->prepare_commit_versioned)
7538 {
7539 ulonglong trx_start_id= 0;
7540 ulonglong trx_end_id= table->file->ht->prepare_commit_versioned(thd, &trx_start_id);
7541 if (trx_end_id)
7542 {
7543 if (!TR_table::use_transaction_registry)
7544 {
7545 my_error(ER_VERS_TRT_IS_DISABLED, MYF(0));
7546 goto rollback;
7547 }
7548 if (trt.update(trx_start_id, trx_end_id))
7549 {
7550 goto rollback;
7551 }
7552 }
7553 }
7554
7555 if (table->file->ha_commit_inplace_alter_table(altered_table,
7556 ha_alter_info,
7557 true))
7558 {
7559 goto rollback;
7560 }
7561
7562 thd->drop_temporary_table(altered_table, NULL, false);
7563 }
7564
7565 close_all_tables_for_name(thd, table->s,
7566 alter_ctx->is_table_renamed() ?
7567 HA_EXTRA_PREPARE_FOR_RENAME :
7568 HA_EXTRA_NOT_USED,
7569 NULL);
7570 table_list->table= table= NULL;
7571
7572 /*
7573 Replace the old .FRM with the new .FRM, but keep the old name for now.
7574 Rename to the new name (if needed) will be handled separately below.
7575 */
7576 if (mysql_rename_table(db_type, &alter_ctx->new_db, &alter_ctx->tmp_name,
7577 &alter_ctx->db, &alter_ctx->alias,
7578 FN_FROM_IS_TMP | NO_HA_TABLE))
7579 {
7580 // Since changes were done in-place, we can't revert them.
7581 (void) quick_rm_table(thd, db_type,
7582 &alter_ctx->new_db, &alter_ctx->tmp_name,
7583 FN_IS_TMP | NO_HA_TABLE);
7584 DBUG_RETURN(true);
7585 }
7586
7587 table_list->mdl_request.ticket= mdl_ticket;
7588 if (open_table(thd, table_list, &ot_ctx))
7589 DBUG_RETURN(true);
7590
7591 /*
7592 Tell the handler that the changed frm is on disk and table
7593 has been re-opened
7594 */
7595 table_list->table->file->ha_notify_table_changed();
7596
7597 /*
7598 We might be going to reopen table down on the road, so we have to
7599 restore state of the TABLE object which we used for obtaining of
7600 handler object to make it usable for later reopening.
7601 */
7602 close_thread_table(thd, &thd->open_tables);
7603 table_list->table= NULL;
7604
7605 // Rename altered table if requested.
7606 if (alter_ctx->is_table_renamed())
7607 {
7608 // Remove TABLE and TABLE_SHARE for old name from TDC.
7609 tdc_remove_table(thd, TDC_RT_REMOVE_ALL,
7610 alter_ctx->db.str, alter_ctx->table_name.str, false);
7611
7612 if (mysql_rename_table(db_type, &alter_ctx->db, &alter_ctx->table_name,
7613 &alter_ctx->new_db, &alter_ctx->new_alias, 0))
7614 {
7615 /*
7616 If the rename fails we will still have a working table
7617 with the old name, but with other changes applied.
7618 */
7619 DBUG_RETURN(true);
7620 }
7621 if (Table_triggers_list::change_table_name(thd,
7622 &alter_ctx->db,
7623 &alter_ctx->alias,
7624 &alter_ctx->table_name,
7625 &alter_ctx->new_db,
7626 &alter_ctx->new_alias))
7627 {
7628 /*
7629 If the rename of trigger files fails, try to rename the table
7630 back so we at least have matching table and trigger files.
7631 */
7632 (void) mysql_rename_table(db_type,
7633 &alter_ctx->new_db, &alter_ctx->new_alias,
7634 &alter_ctx->db, &alter_ctx->alias, NO_FK_CHECKS);
7635 DBUG_RETURN(true);
7636 }
7637 rename_table_in_stat_tables(thd, &alter_ctx->db, &alter_ctx->alias,
7638 &alter_ctx->new_db, &alter_ctx->new_alias);
7639 }
7640
7641 DBUG_RETURN(false);
7642
7643 rollback:
7644 table->file->ha_commit_inplace_alter_table(altered_table,
7645 ha_alter_info,
7646 false);
7647 cleanup:
7648 if (reopen_tables)
7649 {
7650 /* Close the only table instance which is still around. */
7651 close_all_tables_for_name(thd, table->s,
7652 alter_ctx->is_table_renamed() ?
7653 HA_EXTRA_PREPARE_FOR_RENAME :
7654 HA_EXTRA_NOT_USED,
7655 NULL);
7656 if (thd->locked_tables_list.reopen_tables(thd, false))
7657 thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
7658 /* QQ; do something about metadata locks ? */
7659 }
7660 thd->drop_temporary_table(altered_table, NULL, false);
7661 // Delete temporary .frm/.par
7662 (void) quick_rm_table(thd, create_info->db_type, &alter_ctx->new_db,
7663 &alter_ctx->tmp_name, FN_IS_TMP | NO_HA_TABLE);
7664 DBUG_RETURN(true);
7665}
7666
7667/**
7668 maximum possible length for certain blob types.
7669
7670 @param[in] type Blob type (e.g. MYSQL_TYPE_TINY_BLOB)
7671
7672 @return
7673 length
7674*/
7675
7676static uint
7677blob_length_by_type(enum_field_types type)
7678{
7679 switch (type)
7680 {
7681 case MYSQL_TYPE_TINY_BLOB:
7682 return 255;
7683 case MYSQL_TYPE_BLOB:
7684 return 65535;
7685 case MYSQL_TYPE_MEDIUM_BLOB:
7686 return 16777215;
7687 case MYSQL_TYPE_LONG_BLOB:
7688 return (uint) UINT_MAX32;
7689 default:
7690 DBUG_ASSERT(0); // we should never go here
7691 return 0;
7692 }
7693}
7694
7695
7696static void append_drop_column(THD *thd, bool dont, String *str,
7697 Field *field)
7698{
7699 if (!dont)
7700 {
7701 if (str->length())
7702 str->append(STRING_WITH_LEN(", "));
7703 str->append(STRING_WITH_LEN("DROP COLUMN "));
7704 append_identifier(thd, str, &field->field_name);
7705 }
7706}
7707
7708
7709/**
7710 Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
7711
7712 This function transforms parse output of ALTER TABLE - lists of
7713 columns and keys to add, drop or modify into, essentially,
7714 CREATE TABLE definition - a list of columns and keys of the new
7715 table. While doing so, it also performs some (bug not all)
7716 semantic checks.
7717
7718 This function is invoked when we know that we're going to
7719 perform ALTER TABLE via a temporary table -- i.e. in-place ALTER TABLE
7720 is not possible, perhaps because the ALTER statement contains
7721 instructions that require change in table data, not only in
7722 table definition or indexes.
7723
7724 @param[in,out] thd thread handle. Used as a memory pool
7725 and source of environment information.
7726 @param[in] table the source table, open and locked
7727 Used as an interface to the storage engine
7728 to acquire additional information about
7729 the original table.
7730 @param[in,out] create_info A blob with CREATE/ALTER TABLE
7731 parameters
7732 @param[in,out] alter_info Another blob with ALTER/CREATE parameters.
7733 Originally create_info was used only in
7734 CREATE TABLE and alter_info only in ALTER TABLE.
7735 But since ALTER might end-up doing CREATE,
7736 this distinction is gone and we just carry
7737 around two structures.
7738 @param[in,out] alter_ctx Runtime context for ALTER TABLE.
7739
7740 @return
7741 Fills various create_info members based on information retrieved
7742 from the storage engine.
7743 Sets create_info->varchar if the table has a VARCHAR column.
7744 Prepares alter_info->create_list and alter_info->key_list with
7745 columns and keys of the new table.
7746
7747 @retval TRUE error, out of memory or a semantical error in ALTER
7748 TABLE instructions
7749 @retval FALSE success
7750*/
7751
7752bool
7753mysql_prepare_alter_table(THD *thd, TABLE *table,
7754 HA_CREATE_INFO *create_info,
7755 Alter_info *alter_info,
7756 Alter_table_ctx *alter_ctx)
7757{
7758 /* New column definitions are added here */
7759 List<Create_field> new_create_list;
7760 /* New key definitions are added here */
7761 List<Key> new_key_list;
7762 List_iterator<Alter_drop> drop_it(alter_info->drop_list);
7763 List_iterator<Create_field> def_it(alter_info->create_list);
7764 List_iterator<Alter_column> alter_it(alter_info->alter_list);
7765 List_iterator<Key> key_it(alter_info->key_list);
7766 List_iterator<Create_field> find_it(new_create_list);
7767 List_iterator<Create_field> field_it(new_create_list);
7768 List<Key_part_spec> key_parts;
7769 List<Virtual_column_info> new_constraint_list;
7770 uint db_create_options= (table->s->db_create_options
7771 & ~(HA_OPTION_PACK_RECORD));
7772 Item::func_processor_rename column_rename_param;
7773 uint used_fields, dropped_sys_vers_fields= 0;
7774 KEY *key_info=table->key_info;
7775 bool rc= TRUE;
7776 bool modified_primary_key= FALSE;
7777 Create_field *def;
7778 Field **f_ptr,*field;
7779 MY_BITMAP *dropped_fields= NULL; // if it's NULL - no dropped fields
7780 DBUG_ENTER("mysql_prepare_alter_table");
7781
7782 /*
7783 Merge incompatible changes flag in case of upgrade of a table from an
7784 old MariaDB or MySQL version. This ensures that we don't try to do an
7785 online alter table if field packing or character set changes are required.
7786 */
7787 create_info->used_fields|= table->s->incompatible_version;
7788 used_fields= create_info->used_fields;
7789
7790 create_info->varchar= FALSE;
7791 /* Let new create options override the old ones */
7792 if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
7793 create_info->min_rows= table->s->min_rows;
7794 if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
7795 create_info->max_rows= table->s->max_rows;
7796 if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
7797 create_info->avg_row_length= table->s->avg_row_length;
7798 if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
7799 create_info->default_table_charset= table->s->table_charset;
7800 if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
7801 {
7802 /* Table has an autoincrement, copy value to new table */
7803 table->file->info(HA_STATUS_AUTO);
7804 create_info->auto_increment_value= table->file->stats.auto_increment_value;
7805 }
7806
7807 if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
7808 create_info->key_block_size= table->s->key_block_size;
7809
7810 if (!(used_fields & HA_CREATE_USED_STATS_SAMPLE_PAGES))
7811 create_info->stats_sample_pages= table->s->stats_sample_pages;
7812
7813 if (!(used_fields & HA_CREATE_USED_STATS_AUTO_RECALC))
7814 create_info->stats_auto_recalc= table->s->stats_auto_recalc;
7815
7816 if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
7817 create_info->transactional= table->s->transactional;
7818
7819 if (!(used_fields & HA_CREATE_USED_CONNECTION))
7820 create_info->connect_string= table->s->connect_string;
7821
7822 if (!(used_fields & HA_CREATE_USED_SEQUENCE))
7823 create_info->sequence= table->s->table_type == TABLE_TYPE_SEQUENCE;
7824
7825 column_rename_param.db_name= table->s->db;
7826 column_rename_param.table_name= table->s->table_name;
7827 if (column_rename_param.fields.copy(&alter_info->create_list, thd->mem_root))
7828 DBUG_RETURN(1); // OOM
7829
7830 restore_record(table, s->default_values); // Empty record for DEFAULT
7831
7832 if ((create_info->fields_option_struct= (ha_field_option_struct**)
7833 thd->calloc(sizeof(void*) * table->s->fields)) == NULL ||
7834 (create_info->indexes_option_struct= (ha_index_option_struct**)
7835 thd->calloc(sizeof(void*) * table->s->keys)) == NULL)
7836 DBUG_RETURN(1);
7837
7838 create_info->option_list= merge_engine_table_options(table->s->option_list,
7839 create_info->option_list, thd->mem_root);
7840
7841 /*
7842 First collect all fields from table which isn't in drop_list
7843 */
7844 bitmap_clear_all(&table->tmp_set);
7845 for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
7846 {
7847 if (field->invisible == INVISIBLE_FULL)
7848 continue;
7849 Alter_drop *drop;
7850 if (field->type() == MYSQL_TYPE_VARCHAR)
7851 create_info->varchar= TRUE;
7852 /* Check if field should be dropped */
7853 drop_it.rewind();
7854 while ((drop=drop_it++))
7855 {
7856 if (drop->type == Alter_drop::COLUMN &&
7857 !my_strcasecmp(system_charset_info,field->field_name.str, drop->name))
7858 break;
7859 }
7860 /*
7861 DROP COLULMN xxx
7862 1. it does not see INVISIBLE_SYSTEM columns
7863 2. otherwise, normally a column is dropped
7864 3. unless it's a system versioning column (but see below).
7865 */
7866 if (drop && field->invisible < INVISIBLE_SYSTEM &&
7867 !(field->flags & VERS_SYSTEM_FIELD &&
7868 !(alter_info->flags & ALTER_DROP_SYSTEM_VERSIONING)))
7869 {
7870 /* Reset auto_increment value if it was dropped */
7871 if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
7872 !(used_fields & HA_CREATE_USED_AUTO))
7873 {
7874 create_info->auto_increment_value=0;
7875 create_info->used_fields|=HA_CREATE_USED_AUTO;
7876 }
7877 if (table->s->tmp_table == NO_TMP_TABLE)
7878 (void) delete_statistics_for_column(thd, table, field);
7879 dropped_sys_vers_fields|= field->flags;
7880 drop_it.remove();
7881 dropped_fields= &table->tmp_set;
7882 bitmap_set_bit(dropped_fields, field->field_index);
7883 continue;
7884 }
7885
7886 /* invisible versioning column is dropped automatically on DROP SYSTEM VERSIONING */
7887 if (!drop && field->invisible >= INVISIBLE_SYSTEM &&
7888 field->flags & VERS_SYSTEM_FIELD &&
7889 alter_info->flags & ALTER_DROP_SYSTEM_VERSIONING)
7890 {
7891 if (table->s->tmp_table == NO_TMP_TABLE)
7892 (void) delete_statistics_for_column(thd, table, field);
7893 continue;
7894 }
7895
7896 /*
7897 If we are doing a rename of a column, update all references in virtual
7898 column expressions, constraints and defaults to use the new column name
7899 */
7900 if (alter_info->flags & ALTER_RENAME_COLUMN)
7901 {
7902 if (field->vcol_info)
7903 field->vcol_info->expr->walk(&Item::rename_fields_processor, 1,
7904 &column_rename_param);
7905 if (field->check_constraint)
7906 field->check_constraint->expr->walk(&Item::rename_fields_processor, 1,
7907 &column_rename_param);
7908 if (field->default_value)
7909 field->default_value->expr->walk(&Item::rename_fields_processor, 1,
7910 &column_rename_param);
7911 table->m_needs_reopen= 1; // because new column name is on thd->mem_root
7912 }
7913
7914 /* Check if field is changed */
7915 def_it.rewind();
7916 while ((def=def_it++))
7917 {
7918 if (def->change.str &&
7919 !lex_string_cmp(system_charset_info, &field->field_name,
7920 &def->change))
7921 break;
7922 }
7923 if (def && field->invisible < INVISIBLE_SYSTEM)
7924 { // Field is changed
7925 def->field=field;
7926 /*
7927 Add column being updated to the list of new columns.
7928 Note that columns with AFTER clauses are added to the end
7929 of the list for now. Their positions will be corrected later.
7930 */
7931 new_create_list.push_back(def, thd->mem_root);
7932 if (field->stored_in_db() != def->stored_in_db())
7933 {
7934 my_error(ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN, MYF(0));
7935 goto err;
7936 }
7937 if (!def->after.str)
7938 {
7939 /*
7940 If this ALTER TABLE doesn't have an AFTER clause for the modified
7941 column then remove this column from the list of columns to be
7942 processed. So later we can iterate over the columns remaining
7943 in this list and process modified columns with AFTER clause or
7944 add new columns.
7945 */
7946 def_it.remove();
7947 }
7948 }
7949 else if (alter_info->flags & ALTER_DROP_SYSTEM_VERSIONING &&
7950 field->flags & VERS_SYSTEM_FIELD &&
7951 field->invisible < INVISIBLE_SYSTEM)
7952 {
7953 StringBuffer<NAME_LEN*3> tmp;
7954 append_drop_column(thd, false, &tmp, field);
7955 my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr());
7956 goto err;
7957 }
7958 else if (drop && field->invisible < INVISIBLE_SYSTEM &&
7959 field->flags & VERS_SYSTEM_FIELD &&
7960 !(alter_info->flags & ALTER_DROP_SYSTEM_VERSIONING))
7961 {
7962 /* "dropping" a versioning field only hides it from the user */
7963 def= new (thd->mem_root) Create_field(thd, field, field);
7964 def->invisible= INVISIBLE_SYSTEM;
7965 alter_info->flags|= ALTER_CHANGE_COLUMN;
7966 if (field->flags & VERS_SYS_START_FLAG)
7967 create_info->vers_info.as_row.start= def->field_name= Vers_parse_info::default_start;
7968 else
7969 create_info->vers_info.as_row.end= def->field_name= Vers_parse_info::default_end;
7970 new_create_list.push_back(def, thd->mem_root);
7971 dropped_sys_vers_fields|= field->flags;
7972 drop_it.remove();
7973 }
7974 else
7975 {
7976 /*
7977 This field was not dropped and not changed, add it to the list
7978 for the new table.
7979 */
7980 def= new (thd->mem_root) Create_field(thd, field, field);
7981 new_create_list.push_back(def, thd->mem_root);
7982 alter_it.rewind(); // Change default if ALTER
7983 Alter_column *alter;
7984 while ((alter=alter_it++))
7985 {
7986 if (!my_strcasecmp(system_charset_info,field->field_name.str,
7987 alter->name))
7988 break;
7989 }
7990 if (alter)
7991 {
7992 if ((def->default_value= alter->default_value))
7993 def->flags&= ~NO_DEFAULT_VALUE_FLAG;
7994 else
7995 def->flags|= NO_DEFAULT_VALUE_FLAG;
7996 alter_it.remove();
7997 }
7998 }
7999 }
8000 dropped_sys_vers_fields &= VERS_SYSTEM_FIELD;
8001 if ((dropped_sys_vers_fields ||
8002 alter_info->flags & ALTER_DROP_PERIOD) &&
8003 dropped_sys_vers_fields != VERS_SYSTEM_FIELD)
8004 {
8005 StringBuffer<NAME_LEN*3> tmp;
8006 append_drop_column(thd, dropped_sys_vers_fields & VERS_SYS_START_FLAG,
8007 &tmp, table->vers_start_field());
8008 append_drop_column(thd, dropped_sys_vers_fields & VERS_SYS_END_FLAG,
8009 &tmp, table->vers_end_field());
8010 my_error(ER_MISSING, MYF(0), table->s->table_name.str, tmp.c_ptr());
8011 goto err;
8012 }
8013 alter_info->flags &= ~(ALTER_DROP_PERIOD | ALTER_ADD_PERIOD);
8014 def_it.rewind();
8015 while ((def=def_it++)) // Add new columns
8016 {
8017 Create_field *find;
8018 if (def->change.str && ! def->field)
8019 {
8020 /*
8021 Check if there is modify for newly added field.
8022 */
8023 find_it.rewind();
8024 while((find=find_it++))
8025 {
8026 if (!my_strcasecmp(system_charset_info,find->field_name.str,
8027 def->field_name.str))
8028 break;
8029 }
8030
8031 if (likely(find && !find->field))
8032 find_it.remove();
8033 else
8034 {
8035 my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change.str,
8036 table->s->table_name.str);
8037 goto err;
8038 }
8039 }
8040 /*
8041 Check that the DATE/DATETIME not null field we are going to add is
8042 either has a default value or the '0000-00-00' is allowed by the
8043 set sql mode.
8044 If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
8045 flag to allow ALTER TABLE only if the table to be altered is empty.
8046 */
8047 if ((def->real_field_type() == MYSQL_TYPE_DATE ||
8048 def->real_field_type() == MYSQL_TYPE_NEWDATE ||
8049 def->real_field_type() == MYSQL_TYPE_DATETIME ||
8050 def->real_field_type() == MYSQL_TYPE_DATETIME2) &&
8051 !alter_ctx->datetime_field &&
8052 !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
8053 thd->variables.sql_mode & MODE_NO_ZERO_DATE)
8054 {
8055 alter_ctx->datetime_field= def;
8056 alter_ctx->error_if_not_empty= TRUE;
8057 }
8058 if (def->flags & VERS_SYSTEM_FIELD &&
8059 !(alter_info->flags & ALTER_ADD_SYSTEM_VERSIONING))
8060 {
8061 my_error(ER_VERS_NOT_VERSIONED, MYF(0), table->s->table_name.str);
8062 goto err;
8063 }
8064 if (!def->after.str)
8065 new_create_list.push_back(def, thd->mem_root);
8066 else
8067 {
8068 if (def->change.str)
8069 {
8070 find_it.rewind();
8071 /*
8072 For columns being modified with AFTER clause we should first remove
8073 these columns from the list and then add them back at their correct
8074 positions.
8075 */
8076 while ((find=find_it++))
8077 {
8078 /*
8079 Create_fields representing changed columns are added directly
8080 from Alter_info::create_list to new_create_list. We can therefore
8081 safely use pointer equality rather than name matching here.
8082 This prevents removing the wrong column in case of column rename.
8083 */
8084 if (find == def)
8085 {
8086 find_it.remove();
8087 break;
8088 }
8089 }
8090 }
8091 if (def->after.str == first_keyword)
8092 new_create_list.push_front(def, thd->mem_root);
8093 else
8094 {
8095 find_it.rewind();
8096 while ((find=find_it++))
8097 {
8098 if (!lex_string_cmp(system_charset_info, &def->after,
8099 &find->field_name))
8100 break;
8101 }
8102 if (unlikely(!find))
8103 {
8104 my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after.str,
8105 table->s->table_name.str);
8106 goto err;
8107 }
8108 find_it.after(def); // Put column after this
8109 }
8110 }
8111 /*
8112 Check if there is alter for newly added field.
8113 */
8114 alter_it.rewind();
8115 Alter_column *alter;
8116 while ((alter=alter_it++))
8117 {
8118 if (!my_strcasecmp(system_charset_info,def->field_name.str,
8119 alter->name))
8120 break;
8121 }
8122 if (alter)
8123 {
8124 if (def->real_field_type() == MYSQL_TYPE_BLOB)
8125 {
8126 my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change.str);
8127 goto err;
8128 }
8129 if ((def->default_value= alter->default_value)) // Use new default
8130 def->flags&= ~NO_DEFAULT_VALUE_FLAG;
8131 else
8132 def->flags|= NO_DEFAULT_VALUE_FLAG;
8133 alter_it.remove();
8134 }
8135 }
8136 if (unlikely(alter_info->alter_list.elements))
8137 {
8138 my_error(ER_BAD_FIELD_ERROR, MYF(0),
8139 alter_info->alter_list.head()->name, table->s->table_name.str);
8140 goto err;
8141 }
8142 if (unlikely(!new_create_list.elements))
8143 {
8144 my_message(ER_CANT_REMOVE_ALL_FIELDS,
8145 ER_THD(thd, ER_CANT_REMOVE_ALL_FIELDS),
8146 MYF(0));
8147 goto err;
8148 }
8149
8150 /*
8151 Collect all keys which isn't in drop list. Add only those
8152 for which some fields exists.
8153 */
8154
8155 for (uint i=0 ; i < table->s->keys ; i++,key_info++)
8156 {
8157 if (key_info->flags & HA_INVISIBLE_KEY)
8158 continue;
8159 const char *key_name= key_info->name.str;
8160 Alter_drop *drop;
8161 drop_it.rewind();
8162 while ((drop=drop_it++))
8163 {
8164 if (drop->type == Alter_drop::KEY &&
8165 !my_strcasecmp(system_charset_info,key_name, drop->name))
8166 break;
8167 }
8168 if (drop)
8169 {
8170 if (table->s->tmp_table == NO_TMP_TABLE)
8171 {
8172 (void) delete_statistics_for_index(thd, table, key_info, FALSE);
8173 if (i == table->s->primary_key)
8174 {
8175 KEY *tab_key_info= table->key_info;
8176 for (uint j=0; j < table->s->keys; j++, tab_key_info++)
8177 {
8178 if (tab_key_info->user_defined_key_parts !=
8179 tab_key_info->ext_key_parts)
8180 (void) delete_statistics_for_index(thd, table, tab_key_info,
8181 TRUE);
8182 }
8183 }
8184 }
8185 drop_it.remove();
8186 continue;
8187 }
8188
8189 const char *dropped_key_part= NULL;
8190 KEY_PART_INFO *key_part= key_info->key_part;
8191 key_parts.empty();
8192 bool delete_index_stat= FALSE;
8193 for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++)
8194 {
8195 Field *kfield= key_part->field;
8196 if (!kfield)
8197 continue; // Wrong field (from UNIREG)
8198 const char *key_part_name=kfield->field_name.str;
8199 Create_field *cfield;
8200 uint key_part_length;
8201
8202 field_it.rewind();
8203 while ((cfield=field_it++))
8204 {
8205 if (cfield->change.str)
8206 {
8207 if (!my_strcasecmp(system_charset_info, key_part_name,
8208 cfield->change.str))
8209 break;
8210 }
8211 else if (!my_strcasecmp(system_charset_info,
8212 key_part_name, cfield->field_name.str))
8213 break;
8214 }
8215 if (!cfield)
8216 {
8217 if (table->s->primary_key == i)
8218 modified_primary_key= TRUE;
8219 delete_index_stat= TRUE;
8220 if (!(kfield->flags & VERS_SYSTEM_FIELD))
8221 dropped_key_part= key_part_name;
8222 continue; // Field is removed
8223 }
8224 key_part_length= key_part->length;
8225 if (cfield->field) // Not new field
8226 {
8227 /*
8228 If the field can't have only a part used in a key according to its
8229 new type, or should not be used partially according to its
8230 previous type, or the field length is less than the key part
8231 length, unset the key part length.
8232
8233 We also unset the key part length if it is the same as the
8234 old field's length, so the whole new field will be used.
8235
8236 BLOBs may have cfield->length == 0, which is why we test it before
8237 checking whether cfield->length < key_part_length (in chars).
8238
8239 In case of TEXTs we check the data type maximum length *in bytes*
8240 to key part length measured *in characters* (i.e. key_part_length
8241 devided to mbmaxlen). This is because it's OK to have:
8242 CREATE TABLE t1 (a tinytext, key(a(254)) character set utf8);
8243 In case of this example:
8244 - data type maximum length is 255.
8245 - key_part_length is 1016 (=254*4, where 4 is mbmaxlen)
8246 */
8247 if (!cfield->field->type_handler()->type_can_have_key_part() ||
8248 !cfield->type_handler()->type_can_have_key_part() ||
8249 /* spatial keys can't have sub-key length */
8250 (key_info->flags & HA_SPATIAL) ||
8251 (cfield->field->field_length == key_part_length &&
8252 !f_is_blob(key_part->key_type)) ||
8253 (cfield->length &&
8254 (((cfield->real_field_type() >= MYSQL_TYPE_TINY_BLOB &&
8255 cfield->real_field_type() <= MYSQL_TYPE_BLOB) ?
8256 blob_length_by_type(cfield->real_field_type()) :
8257 cfield->length) <
8258 key_part_length / kfield->charset()->mbmaxlen)))
8259 key_part_length= 0; // Use whole field
8260 }
8261 key_part_length /= kfield->charset()->mbmaxlen;
8262 key_parts.push_back(new Key_part_spec(&cfield->field_name,
8263 key_part_length),
8264 thd->mem_root);
8265 }
8266 if (table->s->tmp_table == NO_TMP_TABLE)
8267 {
8268 if (delete_index_stat)
8269 (void) delete_statistics_for_index(thd, table, key_info, FALSE);
8270 else if (modified_primary_key &&
8271 key_info->user_defined_key_parts != key_info->ext_key_parts)
8272 (void) delete_statistics_for_index(thd, table, key_info, TRUE);
8273 }
8274
8275 if (key_parts.elements)
8276 {
8277 KEY_CREATE_INFO key_create_info;
8278 Key *key;
8279 enum Key::Keytype key_type;
8280 LEX_CSTRING tmp_name;
8281 bzero((char*) &key_create_info, sizeof(key_create_info));
8282 key_create_info.algorithm= key_info->algorithm;
8283 /*
8284 We copy block size directly as some engines, like Area, sets this
8285 automatically
8286 */
8287 key_create_info.block_size= key_info->block_size;
8288 key_create_info.flags= key_info->flags; // HA_USE_BLOCK_SIZE
8289 if (key_info->flags & HA_USES_PARSER)
8290 key_create_info.parser_name= *plugin_name(key_info->parser);
8291 if (key_info->flags & HA_USES_COMMENT)
8292 key_create_info.comment= key_info->comment;
8293
8294 /*
8295 We're refreshing an already existing index. Since the index is not
8296 modified, there is no need to check for duplicate indexes again.
8297 */
8298 key_create_info.check_for_duplicate_indexes= false;
8299
8300 if (key_info->flags & HA_SPATIAL)
8301 key_type= Key::SPATIAL;
8302 else if (key_info->flags & HA_NOSAME)
8303 {
8304 if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
8305 key_type= Key::PRIMARY;
8306 else
8307 key_type= Key::UNIQUE;
8308 if (dropped_key_part)
8309 {
8310 my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), dropped_key_part);
8311 goto err;
8312 }
8313 }
8314 else if (key_info->flags & HA_FULLTEXT)
8315 key_type= Key::FULLTEXT;
8316 else
8317 key_type= Key::MULTIPLE;
8318
8319 tmp_name.str= key_name;
8320 tmp_name.length= strlen(key_name);
8321 key= new Key(key_type, &tmp_name, &key_create_info,
8322 MY_TEST(key_info->flags & HA_GENERATED_KEY),
8323 &key_parts, key_info->option_list, DDL_options());
8324 new_key_list.push_back(key, thd->mem_root);
8325 }
8326 }
8327 {
8328 Key *key;
8329 while ((key=key_it++)) // Add new keys
8330 {
8331 if (key->type == Key::FOREIGN_KEY &&
8332 ((Foreign_key *)key)->validate(new_create_list))
8333 goto err;
8334 new_key_list.push_back(key, thd->mem_root);
8335 if (key->name.str &&
8336 !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
8337 {
8338 my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
8339 goto err;
8340 }
8341 }
8342 }
8343
8344 /* Add all table level constraints which are not in the drop list */
8345 if (table->s->table_check_constraints)
8346 {
8347 TABLE_SHARE *share= table->s;
8348
8349 for (uint i= share->field_check_constraints;
8350 i < share->table_check_constraints ; i++)
8351 {
8352 Virtual_column_info *check= table->check_constraints[i];
8353 Alter_drop *drop;
8354 drop_it.rewind();
8355 while ((drop=drop_it++))
8356 {
8357 if (drop->type == Alter_drop::CHECK_CONSTRAINT &&
8358 !my_strcasecmp(system_charset_info, check->name.str, drop->name))
8359 {
8360 drop_it.remove();
8361 break;
8362 }
8363 }
8364 /* see if the constraint depends on *only* on dropped fields */
8365 if (!drop && dropped_fields)
8366 {
8367 table->default_column_bitmaps();
8368 bitmap_clear_all(table->read_set);
8369 check->expr->walk(&Item::register_field_in_read_map, 1, 0);
8370 if (bitmap_is_subset(table->read_set, dropped_fields))
8371 drop= (Alter_drop*)1;
8372 else if (bitmap_is_overlapping(dropped_fields, table->read_set))
8373 {
8374 bitmap_intersect(table->read_set, dropped_fields);
8375 uint field_nr= bitmap_get_first_set(table->read_set);
8376 my_error(ER_BAD_FIELD_ERROR, MYF(0),
8377 table->field[field_nr]->field_name.str, "CHECK");
8378 goto err;
8379 }
8380 }
8381 if (!drop)
8382 {
8383 check->expr->walk(&Item::rename_fields_processor, 1, &column_rename_param);
8384 new_constraint_list.push_back(check, thd->mem_root);
8385 }
8386 }
8387 }
8388 /* Add new constraints */
8389 new_constraint_list.append(&alter_info->check_constraint_list);
8390
8391 if (alter_info->drop_list.elements)
8392 {
8393 Alter_drop *drop;
8394 drop_it.rewind();
8395 while ((drop=drop_it++)) {
8396 switch (drop->type) {
8397 case Alter_drop::KEY:
8398 case Alter_drop::COLUMN:
8399 case Alter_drop::CHECK_CONSTRAINT:
8400 my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0), drop->type_name(),
8401 alter_info->drop_list.head()->name);
8402 goto err;
8403 case Alter_drop::FOREIGN_KEY:
8404 // Leave the DROP FOREIGN KEY names in the alter_info->drop_list.
8405 break;
8406 }
8407 }
8408 }
8409
8410 if (table->versioned() && !(alter_info->flags & ALTER_DROP_SYSTEM_VERSIONING) &&
8411 new_create_list.elements == VERSIONING_FIELDS)
8412 {
8413 my_error(ER_VERS_TABLE_MUST_HAVE_COLUMNS, MYF(0), table->s->table_name.str);
8414 goto err;
8415 }
8416
8417 if (!create_info->comment.str)
8418 {
8419 create_info->comment.str= table->s->comment.str;
8420 create_info->comment.length= table->s->comment.length;
8421 }
8422
8423 table->file->update_create_info(create_info);
8424 if ((create_info->table_options &
8425 (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
8426 (used_fields & HA_CREATE_USED_PACK_KEYS))
8427 db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
8428 if ((create_info->table_options &
8429 (HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT)) ||
8430 (used_fields & HA_CREATE_USED_STATS_PERSISTENT))
8431 db_create_options&= ~(HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT);
8432
8433 if (create_info->table_options &
8434 (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
8435 db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
8436 if (create_info->table_options &
8437 (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
8438 db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
8439 HA_OPTION_NO_DELAY_KEY_WRITE);
8440 create_info->table_options|= db_create_options;
8441
8442 if (table->s->tmp_table)
8443 create_info->options|=HA_LEX_CREATE_TMP_TABLE;
8444
8445 rc= FALSE;
8446 alter_info->create_list.swap(new_create_list);
8447 alter_info->key_list.swap(new_key_list);
8448 alter_info->check_constraint_list.swap(new_constraint_list);
8449err:
8450 DBUG_RETURN(rc);
8451}
8452
8453
8454/**
8455 Get Create_field object for newly created table by its name
8456 in the old version of table.
8457
8458 @param alter_info Alter_info describing newly created table.
8459 @param old_name Name of field in old table.
8460
8461 @returns Pointer to Create_field object, NULL - if field is
8462 not present in new version of table.
8463*/
8464
8465static Create_field *get_field_by_old_name(Alter_info *alter_info,
8466 const char *old_name)
8467{
8468 List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
8469 Create_field *new_field;
8470
8471 while ((new_field= new_field_it++))
8472 {
8473 if (new_field->field &&
8474 (my_strcasecmp(system_charset_info,
8475 new_field->field->field_name.str,
8476 old_name) == 0))
8477 break;
8478 }
8479 return new_field;
8480}
8481
8482
8483/** Type of change to foreign key column, */
8484
8485enum fk_column_change_type
8486{
8487 FK_COLUMN_NO_CHANGE, FK_COLUMN_DATA_CHANGE,
8488 FK_COLUMN_RENAMED, FK_COLUMN_DROPPED
8489};
8490
8491/**
8492 Check that ALTER TABLE's changes on columns of a foreign key are allowed.
8493
8494 @param[in] thd Thread context.
8495 @param[in] alter_info Alter_info describing changes to be done
8496 by ALTER TABLE.
8497 @param[in] fk_columns List of columns of the foreign key to check.
8498 @param[out] bad_column_name Name of field on which ALTER TABLE tries to
8499 do prohibited operation.
8500
8501 @note This function takes into account value of @@foreign_key_checks
8502 setting.
8503
8504 @retval FK_COLUMN_NO_CHANGE No significant changes are to be done on
8505 foreign key columns.
8506 @retval FK_COLUMN_DATA_CHANGE ALTER TABLE might result in value
8507 change in foreign key column (and
8508 foreign_key_checks is on).
8509 @retval FK_COLUMN_RENAMED Foreign key column is renamed.
8510 @retval FK_COLUMN_DROPPED Foreign key column is dropped.
8511*/
8512
8513static enum fk_column_change_type
8514fk_check_column_changes(THD *thd, Alter_info *alter_info,
8515 List<LEX_CSTRING> &fk_columns,
8516 const char **bad_column_name)
8517{
8518 List_iterator_fast<LEX_CSTRING> column_it(fk_columns);
8519 LEX_CSTRING *column;
8520
8521 *bad_column_name= NULL;
8522
8523 while ((column= column_it++))
8524 {
8525 Create_field *new_field= get_field_by_old_name(alter_info, column->str);
8526
8527 if (new_field)
8528 {
8529 Field *old_field= new_field->field;
8530
8531 if (lex_string_cmp(system_charset_info, &old_field->field_name,
8532 &new_field->field_name))
8533 {
8534 /*
8535 Copy algorithm doesn't support proper renaming of columns in
8536 the foreign key yet. At the moment we lack API which will tell
8537 SE that foreign keys should be updated to use new name of column
8538 like it happens in case of in-place algorithm.
8539 */
8540 *bad_column_name= column->str;
8541 return FK_COLUMN_RENAMED;
8542 }
8543
8544 if ((old_field->is_equal(new_field) == IS_EQUAL_NO) ||
8545 ((new_field->flags & NOT_NULL_FLAG) &&
8546 !(old_field->flags & NOT_NULL_FLAG)))
8547 {
8548 if (!(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS))
8549 {
8550 /*
8551 Column in a FK has changed significantly. Unless
8552 foreign_key_checks are off we prohibit this since this
8553 means values in this column might be changed by ALTER
8554 and thus referential integrity might be broken,
8555 */
8556 *bad_column_name= column->str;
8557 return FK_COLUMN_DATA_CHANGE;
8558 }
8559 }
8560 }
8561 else
8562 {
8563 /*
8564 Column in FK was dropped. Most likely this will break
8565 integrity constraints of InnoDB data-dictionary (and thus
8566 InnoDB will emit an error), so we prohibit this right away
8567 even if foreign_key_checks are off.
8568 This also includes a rare case when another field replaces
8569 field being dropped since it is easy to break referential
8570 integrity in this case.
8571 */
8572 *bad_column_name= column->str;
8573 return FK_COLUMN_DROPPED;
8574 }
8575 }
8576
8577 return FK_COLUMN_NO_CHANGE;
8578}
8579
8580
8581/**
8582 Check if ALTER TABLE we are about to execute using COPY algorithm
8583 is not supported as it might break referential integrity.
8584
8585 @note If foreign_key_checks is disabled (=0), we allow to break
8586 referential integrity. But we still disallow some operations
8587 like dropping or renaming columns in foreign key since they
8588 are likely to break consistency of InnoDB data-dictionary
8589 and thus will end-up in error anyway.
8590
8591 @param[in] thd Thread context.
8592 @param[in] table Table to be altered.
8593 @param[in] alter_info Lists of fields, keys to be changed, added
8594 or dropped.
8595 @param[out] alter_ctx ALTER TABLE runtime context.
8596 Alter_table_ctx::fk_error_if_delete flag
8597 is set if deletion during alter can break
8598 foreign key integrity.
8599
8600 @retval false Success.
8601 @retval true Error, ALTER - tries to do change which is not compatible
8602 with foreign key definitions on the table.
8603*/
8604
8605static bool fk_prepare_copy_alter_table(THD *thd, TABLE *table,
8606 Alter_info *alter_info,
8607 Alter_table_ctx *alter_ctx)
8608{
8609 List <FOREIGN_KEY_INFO> fk_parent_key_list;
8610 List <FOREIGN_KEY_INFO> fk_child_key_list;
8611 FOREIGN_KEY_INFO *f_key;
8612
8613 DBUG_ENTER("fk_prepare_copy_alter_table");
8614
8615 table->file->get_parent_foreign_key_list(thd, &fk_parent_key_list);
8616
8617 /* OOM when building list. */
8618 if (unlikely(thd->is_error()))
8619 DBUG_RETURN(true);
8620
8621 /*
8622 Remove from the list all foreign keys in which table participates as
8623 parent which are to be dropped by this ALTER TABLE. This is possible
8624 when a foreign key has the same table as child and parent.
8625 */
8626 List_iterator<FOREIGN_KEY_INFO> fk_parent_key_it(fk_parent_key_list);
8627
8628 while ((f_key= fk_parent_key_it++))
8629 {
8630 Alter_drop *drop;
8631 List_iterator_fast<Alter_drop> drop_it(alter_info->drop_list);
8632
8633 while ((drop= drop_it++))
8634 {
8635 /*
8636 InnoDB treats foreign key names in case-insensitive fashion.
8637 So we do it here too. For database and table name type of
8638 comparison used depends on lower-case-table-names setting.
8639 For l_c_t_n = 0 we use case-sensitive comparison, for
8640 l_c_t_n > 0 modes case-insensitive comparison is used.
8641 */
8642 if ((drop->type == Alter_drop::FOREIGN_KEY) &&
8643 (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
8644 drop->name) == 0) &&
8645 (lex_string_cmp(table_alias_charset, f_key->foreign_db,
8646 &table->s->db) == 0) &&
8647 (lex_string_cmp(table_alias_charset, f_key->foreign_table,
8648 &table->s->table_name) == 0))
8649 fk_parent_key_it.remove();
8650 }
8651 }
8652
8653 /*
8654 If there are FKs in which this table is parent which were not
8655 dropped we need to prevent ALTER deleting rows from the table,
8656 as it might break referential integrity. OTOH it is OK to do
8657 so if foreign_key_checks are disabled.
8658 */
8659 if (!fk_parent_key_list.is_empty() &&
8660 !(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS))
8661 alter_ctx->set_fk_error_if_delete_row(fk_parent_key_list.head());
8662
8663 fk_parent_key_it.rewind();
8664 while ((f_key= fk_parent_key_it++))
8665 {
8666 enum fk_column_change_type changes;
8667 const char *bad_column_name;
8668
8669 changes= fk_check_column_changes(thd, alter_info,
8670 f_key->referenced_fields,
8671 &bad_column_name);
8672
8673 switch(changes)
8674 {
8675 case FK_COLUMN_NO_CHANGE:
8676 /* No significant changes. We can proceed with ALTER! */
8677 break;
8678 case FK_COLUMN_DATA_CHANGE:
8679 {
8680 char buff[NAME_LEN*2+2];
8681 strxnmov(buff, sizeof(buff)-1, f_key->foreign_db->str, ".",
8682 f_key->foreign_table->str, NullS);
8683 my_error(ER_FK_COLUMN_CANNOT_CHANGE_CHILD, MYF(0), bad_column_name,
8684 f_key->foreign_id->str, buff);
8685 DBUG_RETURN(true);
8686 }
8687 case FK_COLUMN_RENAMED:
8688 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
8689 "ALGORITHM=COPY",
8690 ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME),
8691 "ALGORITHM=INPLACE");
8692 DBUG_RETURN(true);
8693 case FK_COLUMN_DROPPED:
8694 {
8695 StringBuffer<NAME_LEN*2+2> buff(system_charset_info);
8696 LEX_CSTRING *db= f_key->foreign_db, *tbl= f_key->foreign_table;
8697
8698 append_identifier(thd, &buff, db);
8699 buff.append('.');
8700 append_identifier(thd, &buff, tbl);
8701 my_error(ER_FK_COLUMN_CANNOT_DROP_CHILD, MYF(0), bad_column_name,
8702 f_key->foreign_id->str, buff.c_ptr());
8703 DBUG_RETURN(true);
8704 }
8705 default:
8706 DBUG_ASSERT(0);
8707 }
8708 }
8709
8710 table->file->get_foreign_key_list(thd, &fk_child_key_list);
8711
8712 /* OOM when building list. */
8713 if (unlikely(thd->is_error()))
8714 DBUG_RETURN(true);
8715
8716 /*
8717 Remove from the list all foreign keys which are to be dropped
8718 by this ALTER TABLE.
8719 */
8720 List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
8721
8722 while ((f_key= fk_key_it++))
8723 {
8724 Alter_drop *drop;
8725 List_iterator_fast<Alter_drop> drop_it(alter_info->drop_list);
8726
8727 while ((drop= drop_it++))
8728 {
8729 /* Names of foreign keys in InnoDB are case-insensitive. */
8730 if ((drop->type == Alter_drop::FOREIGN_KEY) &&
8731 (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
8732 drop->name) == 0))
8733 fk_key_it.remove();
8734 }
8735 }
8736
8737 fk_key_it.rewind();
8738 while ((f_key= fk_key_it++))
8739 {
8740 enum fk_column_change_type changes;
8741 const char *bad_column_name;
8742
8743 changes= fk_check_column_changes(thd, alter_info,
8744 f_key->foreign_fields,
8745 &bad_column_name);
8746
8747 switch(changes)
8748 {
8749 case FK_COLUMN_NO_CHANGE:
8750 /* No significant changes. We can proceed with ALTER! */
8751 break;
8752 case FK_COLUMN_DATA_CHANGE:
8753 my_error(ER_FK_COLUMN_CANNOT_CHANGE, MYF(0), bad_column_name,
8754 f_key->foreign_id->str);
8755 DBUG_RETURN(true);
8756 case FK_COLUMN_RENAMED:
8757 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
8758 "ALGORITHM=COPY",
8759 ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME),
8760 "ALGORITHM=INPLACE");
8761 DBUG_RETURN(true);
8762 case FK_COLUMN_DROPPED:
8763 my_error(ER_FK_COLUMN_CANNOT_DROP, MYF(0), bad_column_name,
8764 f_key->foreign_id->str);
8765 DBUG_RETURN(true);
8766 default:
8767 DBUG_ASSERT(0);
8768 }
8769 }
8770
8771 DBUG_RETURN(false);
8772}
8773
8774/**
8775 Rename temporary table and/or turn indexes on/off without touching .FRM.
8776 Its a variant of simple_rename_or_index_change() to be used exclusively
8777 for temporary tables.
8778
8779 @param thd Thread handler
8780 @param table_list TABLE_LIST for the table to change
8781 @param keys_onoff ENABLE or DISABLE KEYS?
8782 @param alter_ctx ALTER TABLE runtime context.
8783
8784 @return Operation status
8785 @retval false Success
8786 @retval true Failure
8787*/
8788static bool
8789simple_tmp_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
8790 Alter_info::enum_enable_or_disable keys_onoff,
8791 Alter_table_ctx *alter_ctx)
8792{
8793 DBUG_ENTER("simple_tmp_rename_or_index_change");
8794
8795 TABLE *table= table_list->table;
8796 bool error= false;
8797
8798 DBUG_ASSERT(table->s->tmp_table);
8799
8800 if (keys_onoff != Alter_info::LEAVE_AS_IS)
8801 {
8802 THD_STAGE_INFO(thd, stage_manage_keys);
8803 error= alter_table_manage_keys(table, table->file->indexes_are_disabled(),
8804 keys_onoff);
8805 }
8806
8807 if (likely(!error) && alter_ctx->is_table_renamed())
8808 {
8809 THD_STAGE_INFO(thd, stage_rename);
8810
8811 /*
8812 If THD::rename_temporary_table() fails, there is no need to rename it
8813 back to the original name (unlike the case for non-temporary tables),
8814 as it was an allocation error and the table was not renamed.
8815 */
8816 error= thd->rename_temporary_table(table, &alter_ctx->new_db,
8817 &alter_ctx->new_alias);
8818 }
8819
8820 if (likely(!error))
8821 {
8822 /*
8823 We do not replicate alter table statement on temporary tables under
8824 ROW-based replication.
8825 */
8826 if (!thd->is_current_stmt_binlog_format_row())
8827 {
8828 error= write_bin_log(thd, true, thd->query(), thd->query_length()) != 0;
8829 }
8830 if (likely(!error))
8831 my_ok(thd);
8832 }
8833
8834 DBUG_RETURN(error);
8835}
8836
8837
8838/**
8839 Rename table and/or turn indexes on/off without touching .FRM
8840
8841 @param thd Thread handler
8842 @param table_list TABLE_LIST for the table to change
8843 @param keys_onoff ENABLE or DISABLE KEYS?
8844 @param alter_ctx ALTER TABLE runtime context.
8845
8846 @return Operation status
8847 @retval false Success
8848 @retval true Failure
8849*/
8850
8851static bool
8852simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
8853 Alter_info::enum_enable_or_disable keys_onoff,
8854 Alter_table_ctx *alter_ctx)
8855{
8856 TABLE *table= table_list->table;
8857 MDL_ticket *mdl_ticket= table->mdl_ticket;
8858 int error= 0;
8859 enum ha_extra_function extra_func= thd->locked_tables_mode
8860 ? HA_EXTRA_NOT_USED
8861 : HA_EXTRA_FORCE_REOPEN;
8862 DBUG_ENTER("simple_rename_or_index_change");
8863
8864 if (keys_onoff != Alter_info::LEAVE_AS_IS)
8865 {
8866 if (wait_while_table_is_used(thd, table, extra_func))
8867 DBUG_RETURN(true);
8868
8869 // It's now safe to take the table level lock.
8870 if (lock_tables(thd, table_list, alter_ctx->tables_opened, 0))
8871 DBUG_RETURN(true);
8872
8873 THD_STAGE_INFO(thd, stage_manage_keys);
8874 error= alter_table_manage_keys(table,
8875 table->file->indexes_are_disabled(),
8876 keys_onoff);
8877 }
8878
8879 if (likely(!error) && alter_ctx->is_table_renamed())
8880 {
8881 THD_STAGE_INFO(thd, stage_rename);
8882 handlerton *old_db_type= table->s->db_type();
8883 /*
8884 Then do a 'simple' rename of the table. First we need to close all
8885 instances of 'source' table.
8886 Note that if wait_while_table_is_used() returns error here (i.e. if
8887 this thread was killed) then it must be that previous step of
8888 simple rename did nothing and therefore we can safely return
8889 without additional clean-up.
8890 */
8891 if (wait_while_table_is_used(thd, table, extra_func))
8892 DBUG_RETURN(true);
8893 close_all_tables_for_name(thd, table->s, HA_EXTRA_PREPARE_FOR_RENAME,
8894 NULL);
8895
8896 (void) rename_table_in_stat_tables(thd, &alter_ctx->db,
8897 &alter_ctx->table_name,
8898 &alter_ctx->new_db,
8899 &alter_ctx->new_alias);
8900
8901 if (mysql_rename_table(old_db_type, &alter_ctx->db, &alter_ctx->table_name,
8902 &alter_ctx->new_db, &alter_ctx->new_alias, 0))
8903 error= -1;
8904 else if (Table_triggers_list::change_table_name(thd,
8905 &alter_ctx->db,
8906 &alter_ctx->alias,
8907 &alter_ctx->table_name,
8908 &alter_ctx->new_db,
8909 &alter_ctx->new_alias))
8910 {
8911 (void) mysql_rename_table(old_db_type,
8912 &alter_ctx->new_db, &alter_ctx->new_alias,
8913 &alter_ctx->db, &alter_ctx->table_name,
8914 NO_FK_CHECKS);
8915 error= -1;
8916 }
8917 }
8918
8919 if (likely(!error))
8920 {
8921 error= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
8922
8923 if (likely(!error))
8924 my_ok(thd);
8925 }
8926 table_list->table= NULL; // For query cache
8927 query_cache_invalidate3(thd, table_list, 0);
8928
8929 if ((thd->locked_tables_mode == LTM_LOCK_TABLES ||
8930 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES))
8931 {
8932 /*
8933 Under LOCK TABLES we should adjust meta-data locks before finishing
8934 statement. Otherwise we can rely on them being released
8935 along with the implicit commit.
8936 */
8937 if (alter_ctx->is_table_renamed())
8938 thd->mdl_context.release_all_locks_for_name(mdl_ticket);
8939 else
8940 mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
8941 }
8942 DBUG_RETURN(error != 0);
8943}
8944
8945
8946/**
8947 Alter table
8948
8949 @param thd Thread handle
8950 @param new_db If there is a RENAME clause
8951 @param new_name If there is a RENAME clause
8952 @param create_info Information from the parsing phase about new
8953 table properties.
8954 @param table_list The table to change.
8955 @param alter_info Lists of fields, keys to be changed, added
8956 or dropped.
8957 @param order_num How many ORDER BY fields has been specified.
8958 @param order List of fields to ORDER BY.
8959 @param ignore Whether we have ALTER IGNORE TABLE
8960
8961 @retval true Error
8962 @retval false Success
8963
8964 This is a veery long function and is everything but the kitchen sink :)
8965 It is used to alter a table and not only by ALTER TABLE but also
8966 CREATE|DROP INDEX are mapped on this function.
8967
8968 When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
8969 or both, then this function short cuts its operation by renaming
8970 the table and/or enabling/disabling the keys. In this case, the FRM is
8971 not changed, directly by mysql_alter_table. However, if there is a
8972 RENAME + change of a field, or an index, the short cut is not used.
8973 See how `create_list` is used to generate the new FRM regarding the
8974 structure of the fields. The same is done for the indices of the table.
8975
8976 Altering a table can be done in two ways. The table can be modified
8977 directly using an in-place algorithm, or the changes can be done using
8978 an intermediate temporary table (copy). In-place is the preferred
8979 algorithm as it avoids copying table data. The storage engine
8980 selects which algorithm to use in check_if_supported_inplace_alter()
8981 based on information about the table changes from fill_alter_inplace_info().
8982*/
8983
8984bool mysql_alter_table(THD *thd, const LEX_CSTRING *new_db,
8985 const LEX_CSTRING *new_name,
8986 HA_CREATE_INFO *create_info,
8987 TABLE_LIST *table_list,
8988 Alter_info *alter_info,
8989 uint order_num, ORDER *order, bool ignore)
8990{
8991 DBUG_ENTER("mysql_alter_table");
8992
8993 /*
8994 Check if we attempt to alter mysql.slow_log or
8995 mysql.general_log table and return an error if
8996 it is the case.
8997 TODO: this design is obsolete and will be removed.
8998 */
8999 int table_kind= check_if_log_table(table_list, FALSE, NullS);
9000
9001 if (table_kind)
9002 {
9003 /* Disable alter of enabled log tables */
9004 if (logger.is_log_table_enabled(table_kind))
9005 {
9006 my_error(ER_BAD_LOG_STATEMENT, MYF(0), "ALTER");
9007 DBUG_RETURN(true);
9008 }
9009
9010 /* Disable alter of log tables to unsupported engine */
9011 if ((create_info->used_fields & HA_CREATE_USED_ENGINE) &&
9012 (!create_info->db_type || /* unknown engine */
9013 !(create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES)))
9014 {
9015 my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0),
9016 hton_name(create_info->db_type)->str);
9017 DBUG_RETURN(true);
9018 }
9019
9020#ifdef WITH_PARTITION_STORAGE_ENGINE
9021 if (alter_info->partition_flags & ALTER_PARTITION_INFO)
9022 {
9023 my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table");
9024 DBUG_RETURN(true);
9025 }
9026#endif
9027 }
9028
9029 THD_STAGE_INFO(thd, stage_init_update);
9030
9031 /*
9032 Code below can handle only base tables so ensure that we won't open a view.
9033 Note that RENAME TABLE the only ALTER clause which is supported for views
9034 has been already processed.
9035 */
9036 table_list->required_type= TABLE_TYPE_NORMAL;
9037
9038 Alter_table_prelocking_strategy alter_prelocking_strategy;
9039
9040 DEBUG_SYNC(thd, "alter_table_before_open_tables");
9041 uint tables_opened;
9042
9043 thd->open_options|= HA_OPEN_FOR_ALTER;
9044 bool error= open_tables(thd, &table_list, &tables_opened, 0,
9045 &alter_prelocking_strategy);
9046 thd->open_options&= ~HA_OPEN_FOR_ALTER;
9047
9048 TABLE *table= table_list->table;
9049 bool versioned= table && table->versioned();
9050
9051 if (versioned)
9052 {
9053 if (handlerton *hton1= create_info->db_type)
9054 {
9055 handlerton *hton2= table->file->partition_ht();
9056 if (hton1 != hton2 &&
9057 (ha_check_storage_engine_flag(hton1, HTON_NATIVE_SYS_VERSIONING) ||
9058 ha_check_storage_engine_flag(hton2, HTON_NATIVE_SYS_VERSIONING)))
9059 {
9060 my_error(ER_VERS_ALTER_ENGINE_PROHIBITED, MYF(0), table_list->db.str,
9061 table_list->table_name.str);
9062 DBUG_RETURN(true);
9063 }
9064 }
9065 if (alter_info->data_modifying() && !thd->slave_thread &&
9066 thd->variables.vers_alter_history == VERS_ALTER_HISTORY_ERROR)
9067 {
9068 my_error(ER_VERS_ALTER_NOT_ALLOWED, MYF(0),
9069 table_list->db.str, table_list->table_name.str);
9070 DBUG_RETURN(true);
9071 }
9072 }
9073
9074 DEBUG_SYNC(thd, "alter_opened_table");
9075
9076#ifdef WITH_WSREP
9077 DBUG_EXECUTE_IF("sync.alter_opened_table",
9078 {
9079 const char act[]=
9080 "now "
9081 "wait_for signal.alter_opened_table";
9082 DBUG_ASSERT(!debug_sync_set_action(thd,
9083 STRING_WITH_LEN(act)));
9084 };);
9085#endif // WITH_WSREP
9086
9087 if (unlikely(error))
9088 DBUG_RETURN(true);
9089
9090 table->use_all_columns();
9091 MDL_ticket *mdl_ticket= table->mdl_ticket;
9092
9093 /*
9094 Prohibit changing of the UNION list of a non-temporary MERGE table
9095 under LOCK tables. It would be quite difficult to reuse a shrinked
9096 set of tables from the old table or to open a new TABLE object for
9097 an extended list and verify that they belong to locked tables.
9098 */
9099 if ((thd->locked_tables_mode == LTM_LOCK_TABLES ||
9100 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) &&
9101 (create_info->used_fields & HA_CREATE_USED_UNION) &&
9102 (table->s->tmp_table == NO_TMP_TABLE))
9103 {
9104 my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
9105 DBUG_RETURN(true);
9106 }
9107
9108 Alter_table_ctx alter_ctx(thd, table_list, tables_opened, new_db, new_name);
9109
9110 MDL_request target_mdl_request;
9111
9112 /* Check that we are not trying to rename to an existing table */
9113 if (alter_ctx.is_table_renamed())
9114 {
9115 if (table->s->tmp_table != NO_TMP_TABLE)
9116 {
9117 /*
9118 Check whether a temporary table exists with same requested new name.
9119 If such table exists, there must be a corresponding TABLE_SHARE in
9120 THD::all_temp_tables list.
9121 */
9122 if (thd->find_tmp_table_share(alter_ctx.new_db.str, alter_ctx.new_name.str))
9123 {
9124 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alter_ctx.new_alias.str);
9125 DBUG_RETURN(true);
9126 }
9127 }
9128 else
9129 {
9130 MDL_request_list mdl_requests;
9131 MDL_request target_db_mdl_request;
9132
9133 target_mdl_request.init(MDL_key::TABLE,
9134 alter_ctx.new_db.str, alter_ctx.new_name.str,
9135 MDL_EXCLUSIVE, MDL_TRANSACTION);
9136 mdl_requests.push_front(&target_mdl_request);
9137
9138 /*
9139 If we are moving the table to a different database, we also
9140 need IX lock on the database name so that the target database
9141 is protected by MDL while the table is moved.
9142 */
9143 if (alter_ctx.is_database_changed())
9144 {
9145 target_db_mdl_request.init(MDL_key::SCHEMA, alter_ctx.new_db.str, "",
9146 MDL_INTENTION_EXCLUSIVE,
9147 MDL_TRANSACTION);
9148 mdl_requests.push_front(&target_db_mdl_request);
9149 }
9150
9151 /*
9152 Global intention exclusive lock must have been already acquired when
9153 table to be altered was open, so there is no need to do it here.
9154 */
9155 DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::GLOBAL,
9156 "", "",
9157 MDL_INTENTION_EXCLUSIVE));
9158
9159 if (thd->mdl_context.acquire_locks(&mdl_requests,
9160 thd->variables.lock_wait_timeout))
9161 DBUG_RETURN(true);
9162
9163 DEBUG_SYNC(thd, "locked_table_name");
9164 /*
9165 Table maybe does not exist, but we got an exclusive lock
9166 on the name, now we can safely try to find out for sure.
9167 */
9168 if (ha_table_exists(thd, &alter_ctx.new_db, &alter_ctx.new_name))
9169 {
9170 /* Table will be closed in do_command() */
9171 my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alter_ctx.new_alias.str);
9172 DBUG_RETURN(true);
9173 }
9174 }
9175 }
9176
9177 if (!create_info->db_type)
9178 {
9179#ifdef WITH_PARTITION_STORAGE_ENGINE
9180 if (table->part_info &&
9181 create_info->used_fields & HA_CREATE_USED_ENGINE)
9182 {
9183 /*
9184 This case happens when the user specified
9185 ENGINE = x where x is a non-existing storage engine
9186 We set create_info->db_type to default_engine_type
9187 to ensure we don't change underlying engine type
9188 due to a erroneously given engine name.
9189 */
9190 create_info->db_type= table->part_info->default_engine_type;
9191 }
9192 else
9193#endif
9194 create_info->db_type= table->s->db_type();
9195 }
9196
9197 if (check_engine(thd, alter_ctx.new_db.str, alter_ctx.new_name.str, create_info))
9198 DBUG_RETURN(true);
9199
9200 if (create_info->vers_info.fix_alter_info(thd, alter_info, create_info, table))
9201 {
9202 DBUG_RETURN(true);
9203 }
9204
9205 if ((create_info->db_type != table->s->db_type() ||
9206 (alter_info->partition_flags & ALTER_PARTITION_INFO)) &&
9207 !table->file->can_switch_engines())
9208 {
9209 my_error(ER_ROW_IS_REFERENCED, MYF(0));
9210 DBUG_RETURN(true);
9211 }
9212
9213 /*
9214 If foreign key is added then check permission to access parent table.
9215
9216 In function "check_fk_parent_table_access", create_info->db_type is used
9217 to identify whether engine supports FK constraint or not. Since
9218 create_info->db_type is set here, check to parent table access is delayed
9219 till this point for the alter operation.
9220 */
9221 if ((alter_info->flags & ALTER_ADD_FOREIGN_KEY) &&
9222 check_fk_parent_table_access(thd, create_info, alter_info, new_db->str))
9223 DBUG_RETURN(true);
9224
9225 /*
9226 If this is an ALTER TABLE and no explicit row type specified reuse
9227 the table's row type.
9228 Note: this is the same as if the row type was specified explicitly.
9229 */
9230 if (create_info->row_type == ROW_TYPE_NOT_USED)
9231 {
9232 /* ALTER TABLE without explicit row type */
9233 create_info->row_type= table->s->row_type;
9234 }
9235 else
9236 {
9237 /* ALTER TABLE with specific row type */
9238 create_info->used_fields |= HA_CREATE_USED_ROW_FORMAT;
9239 }
9240
9241 DBUG_PRINT("info", ("old type: %s new type: %s",
9242 ha_resolve_storage_engine_name(table->s->db_type()),
9243 ha_resolve_storage_engine_name(create_info->db_type)));
9244 if (ha_check_storage_engine_flag(table->s->db_type(), HTON_ALTER_NOT_SUPPORTED))
9245 {
9246 DBUG_PRINT("info", ("doesn't support alter"));
9247 my_error(ER_ILLEGAL_HA, MYF(0), hton_name(table->s->db_type())->str,
9248 alter_ctx.db.str, alter_ctx.table_name.str);
9249 DBUG_RETURN(true);
9250 }
9251
9252 if (ha_check_storage_engine_flag(create_info->db_type,
9253 HTON_ALTER_NOT_SUPPORTED))
9254 {
9255 DBUG_PRINT("info", ("doesn't support alter"));
9256 my_error(ER_ILLEGAL_HA, MYF(0), hton_name(create_info->db_type)->str,
9257 alter_ctx.new_db.str, alter_ctx.new_name.str);
9258 DBUG_RETURN(true);
9259 }
9260
9261 if (table->s->tmp_table == NO_TMP_TABLE)
9262 mysql_audit_alter_table(thd, table_list);
9263
9264 THD_STAGE_INFO(thd, stage_setup);
9265
9266 handle_if_exists_options(thd, table, alter_info);
9267
9268 /*
9269 Look if we have to do anything at all.
9270 ALTER can become NOOP after handling
9271 the IF (NOT) EXISTS options.
9272 */
9273 if (alter_info->flags == 0 && alter_info->partition_flags == 0)
9274 {
9275 my_snprintf(alter_ctx.tmp_buff, sizeof(alter_ctx.tmp_buff),
9276 ER_THD(thd, ER_INSERT_INFO), 0L, 0L,
9277 thd->get_stmt_da()->current_statement_warn_count());
9278 my_ok(thd, 0L, 0L, alter_ctx.tmp_buff);
9279
9280 /* We don't replicate alter table statement on temporary tables */
9281 if (table->s->tmp_table == NO_TMP_TABLE ||
9282 !thd->is_current_stmt_binlog_format_row())
9283 {
9284 if (write_bin_log(thd, true, thd->query(), thd->query_length()))
9285 DBUG_RETURN(true);
9286 }
9287
9288 DBUG_RETURN(false);
9289 }
9290
9291 /*
9292 Test if we are only doing RENAME or KEYS ON/OFF. This works
9293 as we are testing if flags == 0 above.
9294 */
9295 if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
9296 alter_info->partition_flags == 0 &&
9297 alter_info->requested_algorithm !=
9298 Alter_info::ALTER_TABLE_ALGORITHM_COPY) // No need to touch frm.
9299 {
9300 bool res;
9301
9302 if (!table->s->tmp_table)
9303 {
9304 // This requires X-lock, no other lock levels supported.
9305 if (alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_DEFAULT &&
9306 alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)
9307 {
9308 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
9309 "LOCK=NONE/SHARED", "LOCK=EXCLUSIVE");
9310 DBUG_RETURN(true);
9311 }
9312 res= simple_rename_or_index_change(thd, table_list,
9313 alter_info->keys_onoff,
9314 &alter_ctx);
9315 }
9316 else
9317 {
9318 res= simple_tmp_rename_or_index_change(thd, table_list,
9319 alter_info->keys_onoff,
9320 &alter_ctx);
9321 }
9322 DBUG_RETURN(res);
9323 }
9324
9325 /* We have to do full alter table. */
9326
9327#ifdef WITH_PARTITION_STORAGE_ENGINE
9328 bool partition_changed= false;
9329 bool fast_alter_partition= false;
9330 {
9331 if (prep_alter_part_table(thd, table, alter_info, create_info,
9332 &alter_ctx, &partition_changed,
9333 &fast_alter_partition))
9334 {
9335 DBUG_RETURN(true);
9336 }
9337 }
9338#endif
9339
9340 if (mysql_prepare_alter_table(thd, table, create_info, alter_info,
9341 &alter_ctx))
9342 {
9343 DBUG_RETURN(true);
9344 }
9345
9346 set_table_default_charset(thd, create_info, &alter_ctx.db);
9347
9348 if (!opt_explicit_defaults_for_timestamp)
9349 promote_first_timestamp_column(&alter_info->create_list);
9350
9351#ifdef WITH_PARTITION_STORAGE_ENGINE
9352 if (fast_alter_partition)
9353 {
9354 /*
9355 ALGORITHM and LOCK clauses are generally not allowed by the
9356 parser for operations related to partitioning.
9357 The exceptions are ALTER_PARTITION_INFO and ALTER_PARTITION_REMOVE.
9358 For consistency, we report ER_ALTER_OPERATION_NOT_SUPPORTED here.
9359 */
9360 if (alter_info->requested_lock !=
9361 Alter_info::ALTER_TABLE_LOCK_DEFAULT)
9362 {
9363 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
9364 "LOCK=NONE/SHARED/EXCLUSIVE",
9365 ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_PARTITION),
9366 "LOCK=DEFAULT");
9367 DBUG_RETURN(true);
9368 }
9369 else if (alter_info->requested_algorithm !=
9370 Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT)
9371 {
9372 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
9373 "ALGORITHM=COPY/INPLACE",
9374 ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_PARTITION),
9375 "ALGORITHM=DEFAULT");
9376 DBUG_RETURN(true);
9377 }
9378
9379 /*
9380 Upgrade from MDL_SHARED_UPGRADABLE to MDL_SHARED_NO_WRITE.
9381 Afterwards it's safe to take the table level lock.
9382 */
9383 if ((thd->mdl_context.upgrade_shared_lock(mdl_ticket, MDL_SHARED_NO_WRITE,
9384 thd->variables.lock_wait_timeout)) ||
9385 lock_tables(thd, table_list, alter_ctx.tables_opened, 0))
9386 {
9387 DBUG_RETURN(true);
9388 }
9389
9390 // In-place execution of ALTER TABLE for partitioning.
9391 DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info,
9392 create_info, table_list,
9393 &alter_ctx.db,
9394 &alter_ctx.table_name));
9395 }
9396#endif
9397
9398 /*
9399 Use copy algorithm if:
9400 - old_alter_table system variable is set without in-place requested using
9401 the ALGORITHM clause.
9402 - Or if in-place is impossible for given operation.
9403 - Changes to partitioning which were not handled by fast_alter_part_table()
9404 needs to be handled using table copying algorithm unless the engine
9405 supports auto-partitioning as such engines can do some changes
9406 using in-place API.
9407 */
9408 if ((thd->variables.alter_algorithm == Alter_info::ALTER_TABLE_ALGORITHM_COPY &&
9409 alter_info->requested_algorithm !=
9410 Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
9411 || is_inplace_alter_impossible(table, create_info, alter_info)
9412 || IF_PARTITIONING((partition_changed &&
9413 !(table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION)), 0))
9414 {
9415 if (alter_info->requested_algorithm ==
9416 Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
9417 {
9418 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
9419 "ALGORITHM=INPLACE", "ALGORITHM=COPY");
9420 DBUG_RETURN(true);
9421 }
9422 alter_info->requested_algorithm= Alter_info::ALTER_TABLE_ALGORITHM_COPY;
9423 }
9424
9425 /*
9426 ALTER TABLE ... ENGINE to the same engine is a common way to
9427 request table rebuild. Set ALTER_RECREATE flag to force table
9428 rebuild.
9429 */
9430 if (create_info->db_type == table->s->db_type() &&
9431 create_info->used_fields & HA_CREATE_USED_ENGINE)
9432 alter_info->flags|= ALTER_RECREATE;
9433
9434 /*
9435 If the old table had partitions and we are doing ALTER TABLE ...
9436 engine= <new_engine>, the new table must preserve the original
9437 partitioning. This means that the new engine is still the
9438 partitioning engine, not the engine specified in the parser.
9439 This is discovered in prep_alter_part_table, which in such case
9440 updates create_info->db_type.
9441 It's therefore important that the assignment below is done
9442 after prep_alter_part_table.
9443 */
9444 handlerton *new_db_type= create_info->db_type;
9445 handlerton *old_db_type= table->s->db_type();
9446 TABLE *new_table= NULL;
9447 ha_rows copied=0,deleted=0;
9448
9449 /*
9450 Handling of symlinked tables:
9451 If no rename:
9452 Create new data file and index file on the same disk as the
9453 old data and index files.
9454 Copy data.
9455 Rename new data file over old data file and new index file over
9456 old index file.
9457 Symlinks are not changed.
9458
9459 If rename:
9460 Create new data file and index file on the same disk as the
9461 old data and index files. Create also symlinks to point at
9462 the new tables.
9463 Copy data.
9464 At end, rename intermediate tables, and symlinks to intermediate
9465 table, to final table name.
9466 Remove old table and old symlinks
9467
9468 If rename is made to another database:
9469 Create new tables in new database.
9470 Copy data.
9471 Remove old table and symlinks.
9472 */
9473 char index_file[FN_REFLEN], data_file[FN_REFLEN];
9474
9475 if (!alter_ctx.is_database_changed())
9476 {
9477 if (create_info->index_file_name)
9478 {
9479 /* Fix index_file_name to have 'tmp_name' as basename */
9480 strmov(index_file, alter_ctx.tmp_name.str);
9481 create_info->index_file_name=fn_same(index_file,
9482 create_info->index_file_name,
9483 1);
9484 }
9485 if (create_info->data_file_name)
9486 {
9487 /* Fix data_file_name to have 'tmp_name' as basename */
9488 strmov(data_file, alter_ctx.tmp_name.str);
9489 create_info->data_file_name=fn_same(data_file,
9490 create_info->data_file_name,
9491 1);
9492 }
9493 }
9494 else
9495 {
9496 /* Ignore symlink if db is changed. */
9497 create_info->data_file_name=create_info->index_file_name=0;
9498 }
9499
9500 DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock");
9501 /* We can abort alter table for any table type */
9502 thd->abort_on_warning= !ignore && thd->is_strict_mode();
9503
9504 /*
9505 Create .FRM for new version of table with a temporary name.
9506 We don't log the statement, it will be logged later.
9507
9508 Keep information about keys in newly created table as it
9509 will be used later to construct Alter_inplace_info object
9510 and by fill_alter_inplace_info() call.
9511 */
9512 KEY *key_info;
9513 uint key_count;
9514 /*
9515 Remember if the new definition has new VARCHAR column;
9516 create_info->varchar will be reset in create_table_impl()/
9517 mysql_prepare_create_table().
9518 */
9519 bool varchar= create_info->varchar;
9520 LEX_CUSTRING frm= {0,0};
9521
9522 tmp_disable_binlog(thd);
9523 create_info->options|=HA_CREATE_TMP_ALTER;
9524 error= create_table_impl(thd,
9525 &alter_ctx.db, &alter_ctx.table_name,
9526 &alter_ctx.new_db, &alter_ctx.tmp_name,
9527 alter_ctx.get_tmp_path(),
9528 thd->lex->create_info, create_info, alter_info,
9529 C_ALTER_TABLE_FRM_ONLY, NULL,
9530 &key_info, &key_count, &frm);
9531 reenable_binlog(thd);
9532 thd->abort_on_warning= false;
9533 if (unlikely(error))
9534 {
9535 my_free(const_cast<uchar*>(frm.str));
9536 DBUG_RETURN(true);
9537 }
9538
9539 /* Remember that we have not created table in storage engine yet. */
9540 bool no_ha_table= true;
9541
9542 if (alter_info->requested_algorithm != Alter_info::ALTER_TABLE_ALGORITHM_COPY)
9543 {
9544 Alter_inplace_info ha_alter_info(create_info, alter_info,
9545 key_info, key_count,
9546 IF_PARTITIONING(thd->work_part_info, NULL),
9547 ignore);
9548 TABLE *altered_table= NULL;
9549 bool use_inplace= true;
9550
9551 /* Fill the Alter_inplace_info structure. */
9552 if (fill_alter_inplace_info(thd, table, varchar, &ha_alter_info))
9553 goto err_new_table_cleanup;
9554
9555 /*
9556 We can ignore ALTER_COLUMN_ORDER and instead check
9557 ALTER_STORED_COLUMN_ORDER & ALTER_VIRTUAL_COLUMN_ORDER. This
9558 is ok as ALTER_COLUMN_ORDER may be wrong if we use AFTER last_field
9559 ALTER_COLUMN_NAME is set if field really was renamed.
9560 */
9561
9562 if (!(ha_alter_info.handler_flags &
9563 ~(ALTER_COLUMN_ORDER | ALTER_RENAME_COLUMN)))
9564 {
9565 /*
9566 No-op ALTER, no need to call handler API functions.
9567
9568 If this code path is entered for an ALTER statement that
9569 should not be a real no-op, new handler flags should be added
9570 and fill_alter_inplace_info() adjusted.
9571
9572 Note that we can end up here if an ALTER statement has clauses
9573 that cancel each other out (e.g. ADD/DROP identically index).
9574
9575 Also note that we ignore the LOCK clause here.
9576
9577 TODO don't create the frm in the first place
9578 */
9579 const char *path= alter_ctx.get_tmp_path();
9580 table->file->ha_create_partitioning_metadata(path, NULL, CHF_DELETE_FLAG);
9581 deletefrm(path);
9582 my_free(const_cast<uchar*>(frm.str));
9583 goto end_inplace;
9584 }
9585
9586 // We assume that the table is non-temporary.
9587 DBUG_ASSERT(!table->s->tmp_table);
9588
9589 if (!(altered_table=
9590 thd->create_and_open_tmp_table(new_db_type, &frm,
9591 alter_ctx.get_tmp_path(),
9592 alter_ctx.new_db.str,
9593 alter_ctx.tmp_name.str,
9594 false, true)))
9595 goto err_new_table_cleanup;
9596
9597 /* Set markers for fields in TABLE object for altered table. */
9598 update_altered_table(ha_alter_info, altered_table);
9599
9600 /*
9601 Mark all columns in 'altered_table' as used to allow usage
9602 of its record[0] buffer and Field objects during in-place
9603 ALTER TABLE.
9604 */
9605 altered_table->column_bitmaps_set_no_signal(&altered_table->s->all_set,
9606 &altered_table->s->all_set);
9607 restore_record(altered_table, s->default_values); // Create empty record
9608 /* Check that we can call default functions with default field values */
9609 thd->count_cuted_fields= CHECK_FIELD_EXPRESSION;
9610 altered_table->reset_default_fields();
9611 if (altered_table->default_field &&
9612 altered_table->update_default_fields(0, 1))
9613 goto err_new_table_cleanup;
9614 thd->count_cuted_fields= CHECK_FIELD_IGNORE;
9615
9616 if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE)
9617 ha_alter_info.online= true;
9618 // Ask storage engine whether to use copy or in-place
9619 enum_alter_inplace_result inplace_supported=
9620 table->file->check_if_supported_inplace_alter(altered_table,
9621 &ha_alter_info);
9622
9623 if (alter_info->supports_algorithm(thd, inplace_supported, &ha_alter_info) ||
9624 alter_info->supports_lock(thd, inplace_supported, &ha_alter_info))
9625 {
9626 thd->drop_temporary_table(altered_table, NULL, false);
9627 goto err_new_table_cleanup;
9628 }
9629
9630 // If SHARED lock and no particular algorithm was requested, use COPY.
9631 if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK &&
9632 alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED &&
9633 alter_info->requested_algorithm ==
9634 Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT &&
9635 thd->variables.alter_algorithm ==
9636 Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT)
9637 use_inplace= false;
9638
9639 if (inplace_supported == HA_ALTER_INPLACE_NOT_SUPPORTED)
9640 use_inplace= false;
9641
9642 if (use_inplace)
9643 {
9644 table->s->frm_image= &frm;
9645 int res= mysql_inplace_alter_table(thd, table_list, table, altered_table,
9646 &ha_alter_info, inplace_supported,
9647 &target_mdl_request, &alter_ctx);
9648 my_free(const_cast<uchar*>(frm.str));
9649
9650 if (res)
9651 DBUG_RETURN(true);
9652
9653 goto end_inplace;
9654 }
9655 else
9656 {
9657 thd->drop_temporary_table(altered_table, NULL, false);
9658 }
9659 }
9660
9661 /* ALTER TABLE using copy algorithm. */
9662
9663 /* Check if ALTER TABLE is compatible with foreign key definitions. */
9664 if (fk_prepare_copy_alter_table(thd, table, alter_info, &alter_ctx))
9665 goto err_new_table_cleanup;
9666
9667 if (!table->s->tmp_table)
9668 {
9669 // COPY algorithm doesn't work with concurrent writes.
9670 if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE)
9671 {
9672 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
9673 "LOCK=NONE",
9674 ER_THD(thd, ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COPY),
9675 "LOCK=SHARED");
9676 goto err_new_table_cleanup;
9677 }
9678
9679 // If EXCLUSIVE lock is requested, upgrade already.
9680 if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE &&
9681 wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
9682 goto err_new_table_cleanup;
9683
9684 /*
9685 Otherwise upgrade to SHARED_NO_WRITE.
9686 Note that under LOCK TABLES, we will already have SHARED_NO_READ_WRITE.
9687 */
9688 if (alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE &&
9689 thd->mdl_context.upgrade_shared_lock(mdl_ticket, MDL_SHARED_NO_WRITE,
9690 thd->variables.lock_wait_timeout))
9691 goto err_new_table_cleanup;
9692
9693 DEBUG_SYNC(thd, "alter_table_copy_after_lock_upgrade");
9694 }
9695
9696 // It's now safe to take the table level lock.
9697 if (lock_tables(thd, table_list, alter_ctx.tables_opened,
9698 MYSQL_LOCK_USE_MALLOC))
9699 goto err_new_table_cleanup;
9700
9701 if (ha_create_table(thd, alter_ctx.get_tmp_path(),
9702 alter_ctx.new_db.str, alter_ctx.tmp_name.str,
9703 create_info, &frm))
9704 goto err_new_table_cleanup;
9705
9706 /* Mark that we have created table in storage engine. */
9707 no_ha_table= false;
9708
9709 if (create_info->tmp_table())
9710 {
9711 TABLE *tmp_table=
9712 thd->create_and_open_tmp_table(new_db_type, &frm,
9713 alter_ctx.get_tmp_path(),
9714 alter_ctx.new_db.str,
9715 alter_ctx.tmp_name.str,
9716 true, true);
9717 if (!tmp_table)
9718 {
9719 goto err_new_table_cleanup;
9720 }
9721 /* in case of alter temp table send the tracker in OK packet */
9722 SESSION_TRACKER_CHANGED(thd, SESSION_STATE_CHANGE_TRACKER, NULL);
9723 }
9724
9725
9726 /* Open the table since we need to copy the data. */
9727 if (table->s->tmp_table != NO_TMP_TABLE)
9728 {
9729 TABLE_LIST tbl;
9730 tbl.init_one_table(&alter_ctx.new_db, &alter_ctx.tmp_name, 0, TL_READ_NO_INSERT);
9731 /*
9732 Table can be found in the list of open tables in THD::all_temp_tables
9733 list.
9734 */
9735 tbl.table= thd->find_temporary_table(&tbl);
9736 new_table= tbl.table;
9737 }
9738 else
9739 {
9740 /*
9741 table is a normal table: Create temporary table in same directory.
9742 Open our intermediate table.
9743 */
9744 new_table=
9745 thd->create_and_open_tmp_table(new_db_type, &frm,
9746 alter_ctx.get_tmp_path(),
9747 alter_ctx.new_db.str,
9748 alter_ctx.tmp_name.str,
9749 true, true);
9750 }
9751 if (!new_table)
9752 goto err_new_table_cleanup;
9753 new_table->s->orig_table_name= table->s->table_name.str;
9754 /*
9755 Note: In case of MERGE table, we do not attach children. We do not
9756 copy data for MERGE tables. Only the children have data.
9757 */
9758
9759 /* Copy the data if necessary. */
9760 thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
9761 thd->cuted_fields=0L;
9762
9763 /*
9764 We do not copy data for MERGE tables. Only the children have data.
9765 MERGE tables have HA_NO_COPY_ON_ALTER set.
9766 */
9767 if (!(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
9768 {
9769 new_table->next_number_field=new_table->found_next_number_field;
9770 THD_STAGE_INFO(thd, stage_copy_to_tmp_table);
9771 DBUG_EXECUTE_IF("abort_copy_table", {
9772 my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
9773 goto err_new_table_cleanup;
9774 });
9775 if (copy_data_between_tables(thd, table, new_table,
9776 alter_info->create_list, ignore,
9777 order_num, order, &copied, &deleted,
9778 alter_info->keys_onoff,
9779 &alter_ctx))
9780 {
9781 goto err_new_table_cleanup;
9782 }
9783 }
9784 else
9785 {
9786 if (!table->s->tmp_table &&
9787 wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
9788 goto err_new_table_cleanup;
9789 THD_STAGE_INFO(thd, stage_manage_keys);
9790 alter_table_manage_keys(table, table->file->indexes_are_disabled(),
9791 alter_info->keys_onoff);
9792 if (trans_commit_stmt(thd) || trans_commit_implicit(thd))
9793 goto err_new_table_cleanup;
9794 }
9795 thd->count_cuted_fields= CHECK_FIELD_IGNORE;
9796
9797 if (table->s->tmp_table != NO_TMP_TABLE)
9798 {
9799 /* Close lock if this is a transactional table */
9800 if (thd->lock)
9801 {
9802 if (thd->locked_tables_mode != LTM_LOCK_TABLES &&
9803 thd->locked_tables_mode != LTM_PRELOCKED_UNDER_LOCK_TABLES)
9804 {
9805 mysql_unlock_tables(thd, thd->lock);
9806 thd->lock= NULL;
9807 }
9808 else
9809 {
9810 /*
9811 If LOCK TABLES list is not empty and contains this table,
9812 unlock the table and remove the table from this list.
9813 */
9814 mysql_lock_remove(thd, thd->lock, table);
9815 }
9816 }
9817 new_table->s->table_creation_was_logged=
9818 table->s->table_creation_was_logged;
9819 /* Remove link to old table and rename the new one */
9820 thd->drop_temporary_table(table, NULL, true);
9821 /* Should pass the 'new_name' as we store table name in the cache */
9822 if (thd->rename_temporary_table(new_table, &alter_ctx.new_db,
9823 &alter_ctx.new_name))
9824 goto err_new_table_cleanup;
9825 /* We don't replicate alter table statement on temporary tables */
9826 if (!thd->is_current_stmt_binlog_format_row() &&
9827 write_bin_log(thd, true, thd->query(), thd->query_length()))
9828 DBUG_RETURN(true);
9829 my_free(const_cast<uchar*>(frm.str));
9830 goto end_temporary;
9831 }
9832
9833 /*
9834 Close the intermediate table that will be the new table, but do
9835 not delete it! Even though MERGE tables do not have their children
9836 attached here it is safe to call THD::drop_temporary_table().
9837 */
9838 thd->drop_temporary_table(new_table, NULL, false);
9839 new_table= NULL;
9840
9841 DEBUG_SYNC(thd, "alter_table_before_rename_result_table");
9842
9843 /*
9844 Data is copied. Now we:
9845 1) Wait until all other threads will stop using old version of table
9846 by upgrading shared metadata lock to exclusive one.
9847 2) Close instances of table open by this thread and replace them
9848 with placeholders to simplify reopen process.
9849 3) Rename the old table to a temp name, rename the new one to the
9850 old name.
9851 4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
9852 we reopen new version of table.
9853 5) Write statement to the binary log.
9854 6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
9855 remove placeholders and release metadata locks.
9856 7) If we are not not under LOCK TABLES we rely on the caller
9857 (mysql_execute_command()) to release metadata locks.
9858 */
9859
9860 THD_STAGE_INFO(thd, stage_rename_result_table);
9861
9862 if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
9863 goto err_new_table_cleanup;
9864
9865 close_all_tables_for_name(thd, table->s,
9866 alter_ctx.is_table_renamed() ?
9867 HA_EXTRA_PREPARE_FOR_RENAME:
9868 HA_EXTRA_NOT_USED,
9869 NULL);
9870 table_list->table= table= NULL; /* Safety */
9871 my_free(const_cast<uchar*>(frm.str));
9872
9873 /*
9874 Rename the old table to temporary name to have a backup in case
9875 anything goes wrong while renaming the new table.
9876 */
9877 char backup_name_buff[FN_LEN];
9878 LEX_CSTRING backup_name;
9879 backup_name.str= backup_name_buff;
9880
9881 backup_name.length= my_snprintf(backup_name_buff, sizeof(backup_name_buff),
9882 "%s2-%lx-%lx", tmp_file_prefix,
9883 current_pid, (long) thd->thread_id);
9884 if (lower_case_table_names)
9885 my_casedn_str(files_charset_info, backup_name_buff);
9886 if (mysql_rename_table(old_db_type, &alter_ctx.db, &alter_ctx.table_name,
9887 &alter_ctx.db, &backup_name, FN_TO_IS_TMP))
9888 {
9889 // Rename to temporary name failed, delete the new table, abort ALTER.
9890 (void) quick_rm_table(thd, new_db_type, &alter_ctx.new_db,
9891 &alter_ctx.tmp_name, FN_IS_TMP);
9892 goto err_with_mdl;
9893 }
9894
9895 // Rename the new table to the correct name.
9896 if (mysql_rename_table(new_db_type, &alter_ctx.new_db, &alter_ctx.tmp_name,
9897 &alter_ctx.new_db, &alter_ctx.new_alias,
9898 FN_FROM_IS_TMP))
9899 {
9900 // Rename failed, delete the temporary table.
9901 (void) quick_rm_table(thd, new_db_type, &alter_ctx.new_db,
9902 &alter_ctx.tmp_name, FN_IS_TMP);
9903
9904 // Restore the backup of the original table to the old name.
9905 (void) mysql_rename_table(old_db_type, &alter_ctx.db, &backup_name,
9906 &alter_ctx.db, &alter_ctx.alias,
9907 FN_FROM_IS_TMP | NO_FK_CHECKS);
9908 goto err_with_mdl;
9909 }
9910
9911 // Check if we renamed the table and if so update trigger files.
9912 if (alter_ctx.is_table_renamed())
9913 {
9914 if (Table_triggers_list::change_table_name(thd,
9915 &alter_ctx.db,
9916 &alter_ctx.alias,
9917 &alter_ctx.table_name,
9918 &alter_ctx.new_db,
9919 &alter_ctx.new_alias))
9920 {
9921 // Rename succeeded, delete the new table.
9922 (void) quick_rm_table(thd, new_db_type,
9923 &alter_ctx.new_db, &alter_ctx.new_alias, 0);
9924 // Restore the backup of the original table to the old name.
9925 (void) mysql_rename_table(old_db_type, &alter_ctx.db, &backup_name,
9926 &alter_ctx.db, &alter_ctx.alias,
9927 FN_FROM_IS_TMP | NO_FK_CHECKS);
9928 goto err_with_mdl;
9929 }
9930 rename_table_in_stat_tables(thd, &alter_ctx.db, &alter_ctx.alias,
9931 &alter_ctx.new_db, &alter_ctx.new_alias);
9932 }
9933
9934 // ALTER TABLE succeeded, delete the backup of the old table.
9935 if (quick_rm_table(thd, old_db_type, &alter_ctx.db, &backup_name, FN_IS_TMP))
9936 {
9937 /*
9938 The fact that deletion of the backup failed is not critical
9939 error, but still worth reporting as it might indicate serious
9940 problem with server.
9941 */
9942 goto err_with_mdl_after_alter;
9943 }
9944
9945end_inplace:
9946
9947 if (thd->locked_tables_list.reopen_tables(thd, false))
9948 goto err_with_mdl_after_alter;
9949
9950 THD_STAGE_INFO(thd, stage_end);
9951
9952 DEBUG_SYNC(thd, "alter_table_before_main_binlog");
9953
9954 DBUG_ASSERT(!(mysql_bin_log.is_open() &&
9955 thd->is_current_stmt_binlog_format_row() &&
9956 (create_info->tmp_table())));
9957 if (write_bin_log(thd, true, thd->query(), thd->query_length()))
9958 DBUG_RETURN(true);
9959
9960 table_list->table= NULL; // For query cache
9961 query_cache_invalidate3(thd, table_list, false);
9962
9963 if (thd->locked_tables_mode == LTM_LOCK_TABLES ||
9964 thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)
9965 {
9966 if (alter_ctx.is_table_renamed())
9967 thd->mdl_context.release_all_locks_for_name(mdl_ticket);
9968 else
9969 mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
9970 }
9971
9972end_temporary:
9973 my_snprintf(alter_ctx.tmp_buff, sizeof(alter_ctx.tmp_buff),
9974 ER_THD(thd, ER_INSERT_INFO),
9975 (ulong) (copied + deleted), (ulong) deleted,
9976 (ulong) thd->get_stmt_da()->current_statement_warn_count());
9977 my_ok(thd, copied + deleted, 0L, alter_ctx.tmp_buff);
9978 DBUG_RETURN(false);
9979
9980err_new_table_cleanup:
9981 my_free(const_cast<uchar*>(frm.str));
9982 if (new_table)
9983 {
9984 thd->drop_temporary_table(new_table, NULL, true);
9985 }
9986 else
9987 (void) quick_rm_table(thd, new_db_type,
9988 &alter_ctx.new_db, &alter_ctx.tmp_name,
9989 (FN_IS_TMP | (no_ha_table ? NO_HA_TABLE : 0)),
9990 alter_ctx.get_tmp_path());
9991
9992 /*
9993 No default value was provided for a DATE/DATETIME field, the
9994 current sql_mode doesn't allow the '0000-00-00' value and
9995 the table to be altered isn't empty.
9996 Report error here.
9997 */
9998 if (unlikely(alter_ctx.error_if_not_empty &&
9999 thd->get_stmt_da()->current_row_for_warning()))
10000 {
10001 const char *f_val= 0;
10002 enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
10003 switch (alter_ctx.datetime_field->real_field_type())
10004 {
10005 case MYSQL_TYPE_DATE:
10006 case MYSQL_TYPE_NEWDATE:
10007 f_val= "0000-00-00";
10008 t_type= MYSQL_TIMESTAMP_DATE;
10009 break;
10010 case MYSQL_TYPE_DATETIME:
10011 case MYSQL_TYPE_DATETIME2:
10012 f_val= "0000-00-00 00:00:00";
10013 t_type= MYSQL_TIMESTAMP_DATETIME;
10014 break;
10015 default:
10016 /* Shouldn't get here. */
10017 DBUG_ASSERT(0);
10018 }
10019 bool save_abort_on_warning= thd->abort_on_warning;
10020 thd->abort_on_warning= true;
10021 make_truncated_value_warning(thd, Sql_condition::WARN_LEVEL_WARN,
10022 f_val, strlength(f_val), t_type,
10023 alter_ctx.datetime_field->field_name.str);
10024 thd->abort_on_warning= save_abort_on_warning;
10025 }
10026
10027 DBUG_RETURN(true);
10028
10029err_with_mdl_after_alter:
10030 /* the table was altered. binlog the operation */
10031 DBUG_ASSERT(!(mysql_bin_log.is_open() &&
10032 thd->is_current_stmt_binlog_format_row() &&
10033 (create_info->tmp_table())));
10034 write_bin_log(thd, true, thd->query(), thd->query_length());
10035
10036err_with_mdl:
10037 /*
10038 An error happened while we were holding exclusive name metadata lock
10039 on table being altered. To be safe under LOCK TABLES we should
10040 remove all references to the altered table from the list of locked
10041 tables and release the exclusive metadata lock.
10042 */
10043 thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
10044 thd->mdl_context.release_all_locks_for_name(mdl_ticket);
10045 DBUG_RETURN(true);
10046}
10047
10048
10049
10050/**
10051 Prepare the transaction for the alter table's copy phase.
10052*/
10053
10054bool mysql_trans_prepare_alter_copy_data(THD *thd)
10055{
10056 DBUG_ENTER("mysql_trans_prepare_alter_copy_data");
10057 /*
10058 Turn off recovery logging since rollback of an alter table is to
10059 delete the new table so there is no need to log the changes to it.
10060
10061 This needs to be done before external_lock.
10062 */
10063 DBUG_RETURN(ha_enable_transaction(thd, FALSE) != 0);
10064}
10065
10066
10067/**
10068 Commit the copy phase of the alter table.
10069*/
10070
10071bool mysql_trans_commit_alter_copy_data(THD *thd)
10072{
10073 bool error= FALSE;
10074 uint save_unsafe_rollback_flags;
10075 DBUG_ENTER("mysql_trans_commit_alter_copy_data");
10076
10077 /* Save flags as transcommit_implicit_are_deleting_them */
10078 save_unsafe_rollback_flags= thd->transaction.stmt.m_unsafe_rollback_flags;
10079
10080 if (ha_enable_transaction(thd, TRUE))
10081 DBUG_RETURN(TRUE);
10082
10083 /*
10084 Ensure that the new table is saved properly to disk before installing
10085 the new .frm.
10086 And that InnoDB's internal latches are released, to avoid deadlock
10087 when waiting on other instances of the table before rename (Bug#54747).
10088 */
10089 if (trans_commit_stmt(thd))
10090 error= TRUE;
10091 if (trans_commit_implicit(thd))
10092 error= TRUE;
10093
10094 thd->transaction.stmt.m_unsafe_rollback_flags= save_unsafe_rollback_flags;
10095 DBUG_RETURN(error);
10096}
10097
10098
10099static int
10100copy_data_between_tables(THD *thd, TABLE *from, TABLE *to,
10101 List<Create_field> &create, bool ignore,
10102 uint order_num, ORDER *order,
10103 ha_rows *copied, ha_rows *deleted,
10104 Alter_info::enum_enable_or_disable keys_onoff,
10105 Alter_table_ctx *alter_ctx)
10106{
10107 int error= 1;
10108 Copy_field *copy= NULL, *copy_end;
10109 ha_rows found_count= 0, delete_count= 0;
10110 SORT_INFO *file_sort= 0;
10111 READ_RECORD info;
10112 TABLE_LIST tables;
10113 List<Item> fields;
10114 List<Item> all_fields;
10115 bool auto_increment_field_copied= 0;
10116 bool cleanup_done= 0;
10117 bool init_read_record_done= 0;
10118 sql_mode_t save_sql_mode= thd->variables.sql_mode;
10119 ulonglong prev_insert_id, time_to_report_progress;
10120 Field **dfield_ptr= to->default_field;
10121 bool make_versioned= !from->versioned() && to->versioned();
10122 bool make_unversioned= from->versioned() && !to->versioned();
10123 bool keep_versioned= from->versioned() && to->versioned();
10124 bool drop_history= false; // XXX
10125 Field *to_row_start= NULL, *to_row_end= NULL, *from_row_end= NULL;
10126 MYSQL_TIME query_start;
10127 DBUG_ENTER("copy_data_between_tables");
10128
10129 /* Two or 3 stages; Sorting, copying data and update indexes */
10130 thd_progress_init(thd, 2 + MY_TEST(order));
10131
10132 if (!(copy= new (thd->mem_root) Copy_field[to->s->fields]))
10133 DBUG_RETURN(-1);
10134
10135 if (mysql_trans_prepare_alter_copy_data(thd))
10136 {
10137 delete [] copy;
10138 DBUG_RETURN(-1);
10139 }
10140
10141 /* We need external lock before we can disable/enable keys */
10142 if (to->file->ha_external_lock(thd, F_WRLCK))
10143 {
10144 /* Undo call to mysql_trans_prepare_alter_copy_data() */
10145 ha_enable_transaction(thd, TRUE);
10146 delete [] copy;
10147 DBUG_RETURN(-1);
10148 }
10149
10150 alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
10151
10152 /* We can abort alter table for any table type */
10153 thd->abort_on_warning= !ignore && thd->is_strict_mode();
10154
10155 from->file->info(HA_STATUS_VARIABLE);
10156 to->file->extra(HA_EXTRA_PREPARE_FOR_ALTER_TABLE);
10157 to->file->ha_start_bulk_insert(from->file->stats.records,
10158 ignore ? 0 : HA_CREATE_UNIQUE_INDEX_BY_SORT);
10159 List_iterator<Create_field> it(create);
10160 Create_field *def;
10161 copy_end=copy;
10162 to->s->default_fields= 0;
10163 for (Field **ptr=to->field ; *ptr ; ptr++)
10164 {
10165 def=it++;
10166 if (def->field)
10167 {
10168 if (*ptr == to->next_number_field)
10169 {
10170 auto_increment_field_copied= TRUE;
10171 /*
10172 If we are going to copy contents of one auto_increment column to
10173 another auto_increment column it is sensible to preserve zeroes.
10174 This condition also covers case when we are don't actually alter
10175 auto_increment column.
10176 */
10177 if (def->field == from->found_next_number_field)
10178 thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
10179 }
10180 (copy_end++)->set(*ptr,def->field,0);
10181 }
10182 else
10183 {
10184 /*
10185 Update the set of auto-update fields to contain only the new fields
10186 added to the table. Only these fields should be updated automatically.
10187 Old fields keep their current values, and therefore should not be
10188 present in the set of autoupdate fields.
10189 */
10190 if ((*ptr)->default_value)
10191 {
10192 *(dfield_ptr++)= *ptr;
10193 ++to->s->default_fields;
10194 }
10195 }
10196 }
10197 if (dfield_ptr)
10198 *dfield_ptr= NULL;
10199
10200 if (order)
10201 {
10202 if (to->s->primary_key != MAX_KEY &&
10203 to->file->ha_table_flags() & HA_TABLE_SCAN_ON_INDEX)
10204 {
10205 char warn_buff[MYSQL_ERRMSG_SIZE];
10206 my_snprintf(warn_buff, sizeof(warn_buff),
10207 "ORDER BY ignored as there is a user-defined clustered index"
10208 " in the table '%-.192s'", from->s->table_name.str);
10209 push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
10210 warn_buff);
10211 }
10212 else
10213 {
10214 bzero((char *) &tables, sizeof(tables));
10215 tables.table= from;
10216 tables.alias= tables.table_name= from->s->table_name;
10217 tables.db= from->s->db;
10218
10219 THD_STAGE_INFO(thd, stage_sorting);
10220 Filesort_tracker dummy_tracker(false);
10221 Filesort fsort(order, HA_POS_ERROR, true, NULL);
10222
10223 if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
10224 setup_order(thd, thd->lex->select_lex.ref_pointer_array,
10225 &tables, fields, all_fields, order))
10226 goto err;
10227
10228 if (!(file_sort= filesort(thd, from, &fsort, &dummy_tracker)))
10229 goto err;
10230 }
10231 thd_progress_next_stage(thd);
10232 }
10233
10234 if (make_versioned)
10235 {
10236 query_start= thd->query_start_TIME();
10237 to_row_start= to->vers_start_field();
10238 to_row_end= to->vers_end_field();
10239 }
10240 else if (make_unversioned)
10241 {
10242 from_row_end= from->vers_end_field();
10243 }
10244 else if (keep_versioned && drop_history)
10245 {
10246 from_row_end= from->vers_end_field();
10247 }
10248
10249 THD_STAGE_INFO(thd, stage_copy_to_tmp_table);
10250 /* Tell handler that we have values for all columns in the to table */
10251 to->use_all_columns();
10252 /* Add virtual columns to vcol_set to ensure they are updated */
10253 if (to->vfield)
10254 to->mark_virtual_columns_for_write(TRUE);
10255 if (init_read_record(&info, thd, from, (SQL_SELECT *) 0, file_sort, 1, 1,
10256 FALSE))
10257 goto err;
10258 init_read_record_done= 1;
10259
10260 if (ignore && !alter_ctx->fk_error_if_delete_row)
10261 to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
10262 thd->get_stmt_da()->reset_current_row_for_warning();
10263 restore_record(to, s->default_values); // Create empty record
10264 to->reset_default_fields();
10265
10266 thd->progress.max_counter= from->file->records();
10267 time_to_report_progress= MY_HOW_OFTEN_TO_WRITE/10;
10268 if (!ignore) /* for now, InnoDB needs the undo log for ALTER IGNORE */
10269 to->file->extra(HA_EXTRA_BEGIN_ALTER_COPY);
10270
10271 while (likely(!(error= info.read_record())))
10272 {
10273 if (unlikely(thd->killed))
10274 {
10275 thd->send_kill_message();
10276 error= 1;
10277 break;
10278 }
10279 if (unlikely(++thd->progress.counter >= time_to_report_progress))
10280 {
10281 time_to_report_progress+= MY_HOW_OFTEN_TO_WRITE/10;
10282 thd_progress_report(thd, thd->progress.counter,
10283 thd->progress.max_counter);
10284 }
10285
10286 /* Return error if source table isn't empty. */
10287 if (unlikely(alter_ctx->error_if_not_empty))
10288 {
10289 error= 1;
10290 break;
10291 }
10292 if (to->next_number_field)
10293 {
10294 if (auto_increment_field_copied)
10295 to->auto_increment_field_not_null= TRUE;
10296 else
10297 to->next_number_field->reset();
10298 }
10299
10300 for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
10301 {
10302 copy_ptr->do_copy(copy_ptr);
10303 }
10304
10305 if (drop_history && from_row_end && !from_row_end->is_max())
10306 continue;
10307
10308 if (make_versioned)
10309 {
10310 to_row_start->set_notnull();
10311 to_row_start->store_time(&query_start);
10312 to_row_end->set_max();
10313 }
10314 else if (make_unversioned)
10315 {
10316 if (!from_row_end->is_max())
10317 continue; // Drop history rows.
10318 }
10319
10320 prev_insert_id= to->file->next_insert_id;
10321 if (to->default_field)
10322 to->update_default_fields(0, ignore);
10323 if (to->vfield)
10324 to->update_virtual_fields(to->file, VCOL_UPDATE_FOR_WRITE);
10325
10326 /* This will set thd->is_error() if fatal failure */
10327 if (to->verify_constraints(ignore) == VIEW_CHECK_SKIP)
10328 continue;
10329 if (unlikely(thd->is_error()))
10330 {
10331 error= 1;
10332 break;
10333 }
10334 if (keep_versioned && to->versioned(VERS_TRX_ID))
10335 to->vers_write= false;
10336
10337 error= to->file->ha_write_row(to->record[0]);
10338 to->auto_increment_field_not_null= FALSE;
10339 if (unlikely(error))
10340 {
10341 if (to->file->is_fatal_error(error, HA_CHECK_DUP))
10342 {
10343 /* Not a duplicate key error. */
10344 to->file->print_error(error, MYF(0));
10345 error= 1;
10346 break;
10347 }
10348 else
10349 {
10350 /* Duplicate key error. */
10351 if (unlikely(alter_ctx->fk_error_if_delete_row))
10352 {
10353 /*
10354 We are trying to omit a row from the table which serves as parent
10355 in a foreign key. This might have broken referential integrity so
10356 emit an error. Note that we can't ignore this error even if we are
10357 executing ALTER IGNORE TABLE. IGNORE allows to skip rows, but
10358 doesn't allow to break unique or foreign key constraints,
10359 */
10360 my_error(ER_FK_CANNOT_DELETE_PARENT, MYF(0),
10361 alter_ctx->fk_error_id,
10362 alter_ctx->fk_error_table);
10363 break;
10364 }
10365
10366 if (ignore)
10367 {
10368 /* This ALTER IGNORE TABLE. Simply skip row and continue. */
10369 to->file->restore_auto_increment(prev_insert_id);
10370 delete_count++;
10371 }
10372 else
10373 {
10374 /* Ordinary ALTER TABLE. Report duplicate key error. */
10375 uint key_nr= to->file->get_dup_key(error);
10376 if ((int) key_nr >= 0)
10377 {
10378 const char *err_msg= ER_THD(thd, ER_DUP_ENTRY_WITH_KEY_NAME);
10379 if (key_nr == 0 && to->s->keys > 0 &&
10380 (to->key_info[0].key_part[0].field->flags &
10381 AUTO_INCREMENT_FLAG))
10382 err_msg= ER_THD(thd, ER_DUP_ENTRY_AUTOINCREMENT_CASE);
10383 print_keydup_error(to,
10384 key_nr >= to->s->keys ? NULL :
10385 &to->key_info[key_nr],
10386 err_msg, MYF(0));
10387 }
10388 else
10389 to->file->print_error(error, MYF(0));
10390 break;
10391 }
10392 }
10393 }
10394 else
10395 found_count++;
10396 thd->get_stmt_da()->inc_current_row_for_warning();
10397 }
10398
10399 THD_STAGE_INFO(thd, stage_enabling_keys);
10400 thd_progress_next_stage(thd);
10401
10402 if (error > 0 && !from->s->tmp_table)
10403 {
10404 /* We are going to drop the temporary table */
10405 to->file->extra(HA_EXTRA_PREPARE_FOR_DROP);
10406 }
10407 if (unlikely(to->file->ha_end_bulk_insert()) && error <= 0)
10408 {
10409 /* Give error, if not already given */
10410 if (!thd->is_error())
10411 to->file->print_error(my_errno,MYF(0));
10412 error= 1;
10413 }
10414 if (!ignore)
10415 to->file->extra(HA_EXTRA_END_ALTER_COPY);
10416
10417 cleanup_done= 1;
10418 to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
10419
10420 if (unlikely(mysql_trans_commit_alter_copy_data(thd)))
10421 error= 1;
10422
10423 err:
10424 /* Free resources */
10425 if (init_read_record_done)
10426 end_read_record(&info);
10427 delete [] copy;
10428 delete file_sort;
10429
10430 thd->variables.sql_mode= save_sql_mode;
10431 thd->abort_on_warning= 0;
10432 *copied= found_count;
10433 *deleted=delete_count;
10434 to->file->ha_release_auto_increment();
10435
10436 if (!cleanup_done)
10437 {
10438 /* This happens if we get an error during initialzation of data */
10439 DBUG_ASSERT(error);
10440 to->file->ha_end_bulk_insert();
10441 ha_enable_transaction(thd, TRUE);
10442 }
10443
10444 if (to->file->ha_external_lock(thd,F_UNLCK))
10445 error=1;
10446 if (error < 0 && !from->s->tmp_table &&
10447 to->file->extra(HA_EXTRA_PREPARE_FOR_RENAME))
10448 error= 1;
10449 thd_progress_end(thd);
10450 DBUG_RETURN(error > 0 ? -1 : 0);
10451}
10452
10453
10454/*
10455 Recreates one table by calling mysql_alter_table().
10456
10457 SYNOPSIS
10458 mysql_recreate_table()
10459 thd Thread handler
10460 table_list Table to recreate
10461 table_copy Recreate the table by using
10462 ALTER TABLE COPY algorithm
10463
10464 RETURN
10465 Like mysql_alter_table().
10466*/
10467
10468bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy)
10469{
10470 HA_CREATE_INFO create_info;
10471 Alter_info alter_info;
10472 TABLE_LIST *next_table= table_list->next_global;
10473 DBUG_ENTER("mysql_recreate_table");
10474
10475 /* Set lock type which is appropriate for ALTER TABLE. */
10476 table_list->lock_type= TL_READ_NO_INSERT;
10477 /* Same applies to MDL request. */
10478 table_list->mdl_request.set_type(MDL_SHARED_NO_WRITE);
10479 /* hide following tables from open_tables() */
10480 table_list->next_global= NULL;
10481
10482 bzero((char*) &create_info, sizeof(create_info));
10483 create_info.row_type=ROW_TYPE_NOT_USED;
10484 create_info.default_table_charset=default_charset_info;
10485 /* Force alter table to recreate table */
10486 alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
10487
10488 if (table_copy)
10489 alter_info.requested_algorithm= Alter_info::ALTER_TABLE_ALGORITHM_COPY;
10490
10491 thd->prepare_logs_for_admin_command();
10492
10493 bool res= mysql_alter_table(thd, &null_clex_str, &null_clex_str, &create_info,
10494 table_list, &alter_info, 0,
10495 (ORDER *) 0, 0);
10496 table_list->next_global= next_table;
10497 DBUG_RETURN(res);
10498}
10499
10500
10501static void flush_checksum(ha_checksum *row_crc, uchar **checksum_start,
10502 size_t *checksum_length)
10503{
10504 if (*checksum_start)
10505 {
10506 *row_crc= my_checksum(*row_crc, *checksum_start, *checksum_length);
10507 *checksum_start= NULL;
10508 *checksum_length= 0;
10509 }
10510}
10511
10512
10513bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
10514 HA_CHECK_OPT *check_opt)
10515{
10516 TABLE_LIST *table;
10517 List<Item> field_list;
10518 Item *item;
10519 Protocol *protocol= thd->protocol;
10520 DBUG_ENTER("mysql_checksum_table");
10521
10522 /*
10523 CHECKSUM TABLE returns results and rollbacks statement transaction,
10524 so it should not be used in stored function or trigger.
10525 */
10526 DBUG_ASSERT(! thd->in_sub_stmt);
10527
10528 field_list.push_back(item= new (thd->mem_root)
10529 Item_empty_string(thd, "Table", NAME_LEN*2),
10530 thd->mem_root);
10531 item->maybe_null= 1;
10532 field_list.push_back(item= new (thd->mem_root)
10533 Item_int(thd, "Checksum", (longlong) 1,
10534 MY_INT64_NUM_DECIMAL_DIGITS),
10535 thd->mem_root);
10536 item->maybe_null= 1;
10537 if (protocol->send_result_set_metadata(&field_list,
10538 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
10539 DBUG_RETURN(TRUE);
10540
10541 /*
10542 Close all temporary tables which were pre-open to simplify
10543 privilege checking. Clear all references to closed tables.
10544 */
10545 close_thread_tables(thd);
10546 for (table= tables; table; table= table->next_local)
10547 table->table= NULL;
10548
10549 /* Open one table after the other to keep lock time as short as possible. */
10550 for (table= tables; table; table= table->next_local)
10551 {
10552 char table_name[SAFE_NAME_LEN*2+2];
10553 TABLE *t;
10554 TABLE_LIST *save_next_global;
10555
10556 strxmov(table_name, table->db.str ,".", table->table_name.str, NullS);
10557
10558 /* Remember old 'next' pointer and break the list. */
10559 save_next_global= table->next_global;
10560 table->next_global= NULL;
10561 table->lock_type= TL_READ;
10562 /* Allow to open real tables only. */
10563 table->required_type= TABLE_TYPE_NORMAL;
10564
10565 if (thd->open_temporary_tables(table) ||
10566 open_and_lock_tables(thd, table, FALSE, 0))
10567 {
10568 t= NULL;
10569 }
10570 else
10571 t= table->table;
10572
10573 table->next_global= save_next_global;
10574
10575 protocol->prepare_for_resend();
10576 protocol->store(table_name, system_charset_info);
10577
10578 if (!t)
10579 {
10580 /* Table didn't exist */
10581 protocol->store_null();
10582 }
10583 else
10584 {
10585 /* Call ->checksum() if the table checksum matches 'old_mode' settings */
10586 if (!(check_opt->flags & T_EXTEND) &&
10587 (((t->file->ha_table_flags() & HA_HAS_OLD_CHECKSUM) && thd->variables.old_mode) ||
10588 ((t->file->ha_table_flags() & HA_HAS_NEW_CHECKSUM) && !thd->variables.old_mode)))
10589 protocol->store((ulonglong)t->file->checksum());
10590 else if (check_opt->flags & T_QUICK)
10591 protocol->store_null();
10592 else
10593 {
10594 /* calculating table's checksum */
10595 ha_checksum crc= 0;
10596 uchar null_mask=256 - (1 << t->s->last_null_bit_pos);
10597
10598 t->use_all_columns();
10599
10600 if (t->file->ha_rnd_init(1))
10601 protocol->store_null();
10602 else
10603 {
10604 for (;;)
10605 {
10606 if (thd->killed)
10607 {
10608 /*
10609 we've been killed; let handler clean up, and remove the
10610 partial current row from the recordset (embedded lib)
10611 */
10612 t->file->ha_rnd_end();
10613 thd->protocol->remove_last_row();
10614 goto err;
10615 }
10616 ha_checksum row_crc= 0;
10617 int error= t->file->ha_rnd_next(t->record[0]);
10618 if (unlikely(error))
10619 {
10620 break;
10621 }
10622 if (t->s->null_bytes)
10623 {
10624 /* fix undefined null bits */
10625 t->record[0][t->s->null_bytes-1] |= null_mask;
10626 if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
10627 t->record[0][0] |= 1;
10628
10629 row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
10630 }
10631
10632 uchar *checksum_start= NULL;
10633 size_t checksum_length= 0;
10634 for (uint i= 0; i < t->s->fields; i++ )
10635 {
10636 Field *f= t->field[i];
10637
10638 if (! thd->variables.old_mode && f->is_real_null(0))
10639 {
10640 flush_checksum(&row_crc, &checksum_start, &checksum_length);
10641 continue;
10642 }
10643 /*
10644 BLOB and VARCHAR have pointers in their field, we must convert
10645 to string; GEOMETRY is implemented on top of BLOB.
10646 BIT may store its data among NULL bits, convert as well.
10647 */
10648 switch (f->type()) {
10649 case MYSQL_TYPE_BLOB:
10650 case MYSQL_TYPE_VARCHAR:
10651 case MYSQL_TYPE_GEOMETRY:
10652 case MYSQL_TYPE_BIT:
10653 {
10654 flush_checksum(&row_crc, &checksum_start, &checksum_length);
10655 String tmp;
10656 f->val_str(&tmp);
10657 row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(),
10658 tmp.length());
10659 break;
10660 }
10661 default:
10662 if (!checksum_start)
10663 checksum_start= f->ptr;
10664 DBUG_ASSERT(checksum_start + checksum_length == f->ptr);
10665 checksum_length+= f->pack_length();
10666 break;
10667 }
10668 }
10669 flush_checksum(&row_crc, &checksum_start, &checksum_length);
10670
10671 crc+= row_crc;
10672 }
10673 protocol->store((ulonglong)crc);
10674 t->file->ha_rnd_end();
10675 }
10676 }
10677 trans_rollback_stmt(thd);
10678 close_thread_tables(thd);
10679 }
10680
10681 if (thd->transaction_rollback_request)
10682 {
10683 /*
10684 If transaction rollback was requested we honor it. To do this we
10685 abort statement and return error as not only CHECKSUM TABLE is
10686 rolled back but the whole transaction in which it was used.
10687 */
10688 thd->protocol->remove_last_row();
10689 goto err;
10690 }
10691
10692 /* Hide errors from client. Return NULL for problematic tables instead. */
10693 thd->clear_error();
10694
10695 if (protocol->write())
10696 goto err;
10697 }
10698
10699 my_eof(thd);
10700 DBUG_RETURN(FALSE);
10701
10702err:
10703 DBUG_RETURN(TRUE);
10704}
10705
10706/**
10707 @brief Check if the table can be created in the specified storage engine.
10708
10709 Checks if the storage engine is enabled and supports the given table
10710 type (e.g. normal, temporary, system). May do engine substitution
10711 if the requested engine is disabled.
10712
10713 @param thd Thread descriptor.
10714 @param db_name Database name.
10715 @param table_name Name of table to be created.
10716 @param create_info Create info from parser, including engine.
10717
10718 @retval true Engine not available/supported, error has been reported.
10719 @retval false Engine available/supported.
10720*/
10721bool check_engine(THD *thd, const char *db_name,
10722 const char *table_name, HA_CREATE_INFO *create_info)
10723{
10724 DBUG_ENTER("check_engine");
10725 handlerton **new_engine= &create_info->db_type;
10726 handlerton *req_engine= *new_engine;
10727 handlerton *enf_engine= NULL;
10728 bool no_substitution= thd->variables.sql_mode & MODE_NO_ENGINE_SUBSTITUTION;
10729 *new_engine= ha_checktype(thd, req_engine, no_substitution);
10730 DBUG_ASSERT(*new_engine);
10731 if (!*new_engine)
10732 DBUG_RETURN(true);
10733
10734 /* Enforced storage engine should not be used in
10735 ALTER TABLE that does not use explicit ENGINE = x to
10736 avoid unwanted unrelated changes.*/
10737 if (!(thd->lex->sql_command == SQLCOM_ALTER_TABLE &&
10738 !(create_info->used_fields & HA_CREATE_USED_ENGINE)))
10739 enf_engine= thd->variables.enforced_table_plugin ?
10740 plugin_hton(thd->variables.enforced_table_plugin) : NULL;
10741
10742 if (enf_engine && enf_engine != *new_engine)
10743 {
10744 if (no_substitution)
10745 {
10746 const char *engine_name= ha_resolve_storage_engine_name(req_engine);
10747 my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), engine_name);
10748 DBUG_RETURN(TRUE);
10749 }
10750 *new_engine= enf_engine;
10751 }
10752
10753 if (req_engine && req_engine != *new_engine)
10754 {
10755 push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
10756 ER_WARN_USING_OTHER_HANDLER,
10757 ER_THD(thd, ER_WARN_USING_OTHER_HANDLER),
10758 ha_resolve_storage_engine_name(*new_engine),
10759 table_name);
10760 }
10761 if (create_info->tmp_table() &&
10762 ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
10763 {
10764 if (create_info->used_fields & HA_CREATE_USED_ENGINE)
10765 {
10766 my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
10767 hton_name(*new_engine)->str, "TEMPORARY");
10768 *new_engine= 0;
10769 DBUG_RETURN(true);
10770 }
10771 *new_engine= myisam_hton;
10772 }
10773
10774 DBUG_RETURN(false);
10775}
10776