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