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