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