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 #ifdef WITH_WSREP
2674         thd->wsrep_skip_wsrep_GTID = true;
2675 #endif /* WITH_WSREP */
2676         error |= thd->binlog_query(THD::STMT_QUERY_TYPE,
2677                                    built_non_trans_tmp_query.ptr(),
2678                                    built_non_trans_tmp_query.length(),
2679                                    false/*is_trans*/, false/*direct*/,
2680                                    is_drop_tmp_if_exists_with_no_defaultdb/*suppress_use*/,
2681                                    0)/*errcode*/;
2682       }
2683       if (trans_tmp_table_deleted ||
2684           (have_nonexistent_tmp_table && !non_trans_tmp_table_deleted))
2685       {
2686         /*
2687           When multiple tables are dropped, the tables are classified
2688           in the following categories:
2689 
2690           - non-temporary
2691           - temporary transactional
2692           - temporary non-transactional
2693 
2694           The statement is split into one statement for each of the
2695           categories that some table belongs to. So if tables belong
2696           to one category, then just one statement is written; if
2697           tables belong to two or three categories, then two or three
2698           statements are written.
2699 
2700           There must be one Gtid_log_event or Anonymous_log_event for
2701           each DDL statement.  Therefore, a commit is issued after
2702           each statement.  However, when GTID_MODE=OFF, it is possible
2703           for a DROP TEMPORARY to occur in the middle of a
2704           transaction.  In this case, there must *not* be a commit,
2705           since that would commit the transaction. DROP TEMPORARY is
2706           not supposed to have an implicit commit when executed in a
2707           transaction.
2708 
2709           So we use the following logic:
2710 
2711           - If we are not in a transaction, always generate a commit
2712             for a split statement.
2713 
2714           - If we are in a transaction, do not generate a commit for a
2715             split statement.
2716 
2717             The transaction case only happens for DROP TEMPORARY,
2718             since DROP without TEMPORARY has an implicit commit, i.e.,
2719             commits any ongoing transaction before it starts to
2720             execute.  So we only need to check the condition for
2721             ongoing transaction for this call to mysql_bin_log.commit,
2722             and not for the call inside the code block 'if
2723             (non_tmp_table_deleted)'.
2724         */
2725         if (!thd->in_active_multi_stmt_transaction() &&
2726             non_trans_tmp_table_deleted)
2727         {
2728           DBUG_PRINT("info", ("mysql_rm_table_no_locks commit point 1"));
2729           thd->is_commit_in_middle_of_statement= true;
2730           error |= mysql_bin_log.commit(thd, true);
2731           thd->is_commit_in_middle_of_statement= false;
2732         }
2733         if (have_nonexistent_tmp_table)
2734           built_trans_tmp_query.append(nonexistent_tmp_tables);
2735         /* Chop off the last comma */
2736         built_trans_tmp_query.chop();
2737         built_trans_tmp_query.append(" /* generated by server */");
2738 #ifdef WITH_WSREP
2739         thd->wsrep_skip_wsrep_GTID = true;
2740 #endif /* WITH_WSREP */
2741         error |= thd->binlog_query(THD::STMT_QUERY_TYPE,
2742                                    built_trans_tmp_query.ptr(),
2743                                    built_trans_tmp_query.length(),
2744                                    true/*is_trans*/, false/*direct*/,
2745                                    is_drop_tmp_if_exists_with_no_defaultdb/*suppress_use*/,
2746                                    0/*errcode*/);
2747       }
2748       /*
2749         When the DROP TABLE command is used to drop a single table and if that
2750         command fails then the query cannot generate 'partial results'. In
2751         that case the query will not be written to the binary log.
2752       */
2753       if (non_tmp_table_deleted &&
2754           (thd->lex->select_lex->table_list.elements > 1 || !error))
2755       {
2756         /// @see comment for mysql_bin_log.commit above.
2757         if (non_trans_tmp_table_deleted || trans_tmp_table_deleted ||
2758             have_nonexistent_tmp_table)
2759         {
2760           DBUG_PRINT("info", ("mysql_rm_table_no_locks commit point 1"));
2761           thd->is_commit_in_middle_of_statement= true;
2762           error |= mysql_bin_log.commit(thd, true);
2763           thd->is_commit_in_middle_of_statement= false;
2764         }
2765         /* Chop off the last comma */
2766         built_query.chop();
2767         built_query.append(" /* generated by server */");
2768         int error_code = (non_tmp_error ?
2769           (foreign_key_error ? ER_ROW_IS_REFERENCED : ER_BAD_TABLE_ERROR) : 0);
2770 #ifdef WITH_WSREP
2771         thd->wsrep_skip_wsrep_GTID = false;
2772 #endif /* WITH_WSREP */
2773         error |= thd->binlog_query(THD::STMT_QUERY_TYPE,
2774                                    built_query.ptr(),
2775                                    built_query.length(),
2776                                    true/*is_trans*/, false/*direct*/,
2777                                    false/*suppress_use*/,
2778                                    error_code);
2779       }
2780     }
2781     else if (error)
2782     {
2783       /*
2784         We do not care the returned value, since it goes ahead
2785         with error branch in any case.
2786       */
2787       (void) commit_owned_gtid_by_partial_command(thd);
2788     }
2789   }
2790 
2791   if (!drop_temporary)
2792   {
2793     /*
2794       Under LOCK TABLES we should release meta-data locks on the tables
2795       which were dropped.
2796 
2797       Leave LOCK TABLES mode if we managed to drop all tables which were
2798       locked. Additional check for 'non_temp_tables_count' is to avoid
2799       leaving LOCK TABLES mode if we have dropped only temporary tables.
2800     */
2801     if (thd->locked_tables_mode)
2802     {
2803       if (thd->lock && thd->lock->table_count == 0 && non_temp_tables_count > 0)
2804       {
2805         thd->locked_tables_list.unlock_locked_tables(thd);
2806         goto end;
2807       }
2808       for (table= tables; table; table= table->next_local)
2809       {
2810         /* Drop locks for all successfully dropped tables. */
2811         if (table->table == NULL && table->mdl_request.ticket)
2812         {
2813           /*
2814             Under LOCK TABLES we may have several instances of table open
2815             and locked and therefore have to remove several metadata lock
2816             requests associated with them.
2817           */
2818           thd->mdl_context.release_all_locks_for_name(table->mdl_request.ticket);
2819         }
2820       }
2821     }
2822     /*
2823       Rely on the caller to implicitly commit the transaction
2824       and release metadata locks.
2825     */
2826   }
2827 
2828 end:
2829 #ifdef WITH_WSREP
2830         thd->wsrep_skip_wsrep_GTID = false;
2831 #endif /* WITH_WSREP */
2832   DBUG_RETURN(error);
2833 }
2834 
2835 
2836 /**
2837   Quickly remove a table.
2838 
2839   @param thd         Thread context.
2840   @param base        The handlerton handle.
2841   @param db          The database name.
2842   @param table_name  The table name.
2843   @param flags       Flags for build_table_filename() as well as describing
2844                      if handler files / .FRM should be deleted as well.
2845 
2846   @return False in case of success, True otherwise.
2847 */
2848 
quick_rm_table(THD * thd,handlerton * base,const char * db,const char * table_name,uint flags)2849 bool quick_rm_table(THD *thd, handlerton *base, const char *db,
2850                     const char *table_name, uint flags)
2851 {
2852   char path[FN_REFLEN + 1];
2853   bool error= 0;
2854   DBUG_ENTER("quick_rm_table");
2855 
2856   size_t path_length= build_table_filename(path, sizeof(path) - 1,
2857                                            db, table_name, reg_ext, flags);
2858   if (mysql_file_delete(key_file_frm, path, MYF(0)))
2859     error= 1; /* purecov: inspected */
2860   path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
2861   if (flags & NO_HA_TABLE)
2862   {
2863     handler *file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base);
2864     if (!file)
2865       DBUG_RETURN(true);
2866     (void) file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG, NULL);
2867     delete file;
2868   }
2869   if (!(flags & (FRM_ONLY|NO_HA_TABLE)))
2870     error|= ha_delete_table(current_thd, base, path, db, table_name, 0);
2871   DBUG_RETURN(error);
2872 }
2873 
2874 /*
2875    Sort keys according to the following properties, in decreasing order of
2876    importance:
2877    - PRIMARY KEY
2878    - UNIQUE with all columns NOT NULL
2879    - UNIQUE without partial segments
2880    - UNIQUE
2881    - without fulltext columns
2882    - without virtual generated columns
2883 
2884    This allows us to
2885    - check for duplicate key values faster (PK and UNIQUE are first)
2886    - prioritize PKs
2887    - be sure that, if there is no PK, the set of UNIQUE keys candidate for
2888    promotion starts at number 0, and we can choose #0 as PK (it is required
2889    that PK has number 0).
2890 */
2891 
sort_keys(KEY * a,KEY * b)2892 static int sort_keys(KEY *a, KEY *b)
2893 {
2894   ulong a_flags= a->flags, b_flags= b->flags;
2895 
2896   if (a_flags & HA_NOSAME)
2897   {
2898     if (!(b_flags & HA_NOSAME))
2899       return -1;
2900     if ((a_flags ^ b_flags) & HA_NULL_PART_KEY)
2901     {
2902       /* Sort NOT NULL keys before other keys */
2903       return (a_flags & HA_NULL_PART_KEY) ? 1 : -1;
2904     }
2905     if (a->name == primary_key_name)
2906       return -1;
2907     if (b->name == primary_key_name)
2908       return 1;
2909     /* Sort keys don't containing partial segments before others */
2910     if ((a_flags ^ b_flags) & HA_KEY_HAS_PART_KEY_SEG)
2911       return (a_flags & HA_KEY_HAS_PART_KEY_SEG) ? 1 : -1;
2912   }
2913   else if (b_flags & HA_NOSAME)
2914     return 1;					// Prefer b
2915 
2916   if ((a_flags ^ b_flags) & HA_FULLTEXT)
2917   {
2918     return (a_flags & HA_FULLTEXT) ? 1 : -1;
2919   }
2920 
2921   if ((a_flags ^ b_flags) & HA_VIRTUAL_GEN_KEY)
2922   {
2923     return (a_flags & HA_VIRTUAL_GEN_KEY) ? 1 : -1;
2924   }
2925 
2926   /*
2927     Prefer original key order.	usable_key_parts contains here
2928     the original key position.
2929   */
2930   return ((a->usable_key_parts < b->usable_key_parts) ? -1 :
2931 	  (a->usable_key_parts > b->usable_key_parts) ? 1 :
2932 	  0);
2933 }
2934 
2935 /*
2936   Check TYPELIB (set or enum) for duplicates
2937 
2938   SYNOPSIS
2939     check_duplicates_in_interval()
2940     set_or_name   "SET" or "ENUM" string for warning message
2941     name	  name of the checked column
2942     typelib	  list of values for the column
2943     dup_val_count  returns count of duplicate elements
2944 
2945   DESCRIPTION
2946     This function prints an warning for each value in list
2947     which has some duplicates on its right
2948 
2949   RETURN VALUES
2950     0             ok
2951     1             Error
2952 */
2953 
check_duplicates_in_interval(const char * set_or_name,const char * name,TYPELIB * typelib,const CHARSET_INFO * cs,uint * dup_val_count)2954 bool check_duplicates_in_interval(const char *set_or_name,
2955                                   const char *name, TYPELIB *typelib,
2956                                   const CHARSET_INFO *cs, uint *dup_val_count)
2957 {
2958   TYPELIB tmp= *typelib;
2959   const char **cur_value= typelib->type_names;
2960   unsigned int *cur_length= typelib->type_lengths;
2961   *dup_val_count= 0;
2962 
2963   for ( ; tmp.count > 1; cur_value++, cur_length++)
2964   {
2965     tmp.type_names++;
2966     tmp.type_lengths++;
2967     tmp.count--;
2968     if (find_type2(&tmp, *cur_value, *cur_length, cs))
2969     {
2970       THD *thd= current_thd;
2971       ErrConvString err(*cur_value, *cur_length, cs);
2972       if (current_thd->is_strict_mode())
2973       {
2974         my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
2975                  name, err.ptr(), set_or_name);
2976         return 1;
2977       }
2978       push_warning_printf(thd,Sql_condition::SL_NOTE,
2979                           ER_DUPLICATED_VALUE_IN_TYPE,
2980                           ER(ER_DUPLICATED_VALUE_IN_TYPE),
2981                           name, err.ptr(), set_or_name);
2982       (*dup_val_count)++;
2983     }
2984   }
2985   return 0;
2986 }
2987 
2988 
2989 /*
2990   Check TYPELIB (set or enum) max and total lengths
2991 
2992   SYNOPSIS
2993     calculate_interval_lengths()
2994     cs            charset+collation pair of the interval
2995     typelib       list of values for the column
2996     max_length    length of the longest item
2997     tot_length    sum of the item lengths
2998 
2999   DESCRIPTION
3000     After this function call:
3001     - ENUM uses max_length
3002     - SET uses tot_length.
3003 
3004   RETURN VALUES
3005     void
3006 */
calculate_interval_lengths(const CHARSET_INFO * cs,TYPELIB * interval,size_t * max_length,size_t * tot_length)3007 static void calculate_interval_lengths(const CHARSET_INFO *cs,
3008                                        TYPELIB *interval,
3009                                        size_t *max_length,
3010                                        size_t *tot_length)
3011 {
3012   const char **pos;
3013   uint *len;
3014   *max_length= *tot_length= 0;
3015   for (pos= interval->type_names, len= interval->type_lengths;
3016        *pos ; pos++, len++)
3017   {
3018     size_t length= cs->cset->numchars(cs, *pos, *pos + *len);
3019     *tot_length+= length;
3020     set_if_bigger(*max_length, length);
3021   }
3022 }
3023 
3024 
3025 /*
3026   Prepare a create_table instance for packing
3027 
3028   SYNOPSIS
3029     prepare_create_field()
3030     sql_field     field to prepare for packing
3031     blob_columns  count for BLOBs
3032     table_flags   table flags
3033 
3034   DESCRIPTION
3035     This function prepares a Create_field instance.
3036     Fields such as pack_flag are valid after this call.
3037 
3038   RETURN VALUES
3039    0	ok
3040    1	Error
3041 */
3042 
prepare_create_field(Create_field * sql_field,uint * blob_columns,longlong table_flags)3043 int prepare_create_field(Create_field *sql_field,
3044 			 uint *blob_columns,
3045 			 longlong table_flags)
3046 {
3047   unsigned int dup_val_count;
3048   DBUG_ENTER("prepare_field");
3049 
3050   /*
3051     This code came from mysql_prepare_create_table.
3052     Indent preserved to make patching easier
3053   */
3054   assert(sql_field->charset);
3055 
3056   switch (sql_field->sql_type) {
3057   case MYSQL_TYPE_BLOB:
3058   case MYSQL_TYPE_MEDIUM_BLOB:
3059   case MYSQL_TYPE_TINY_BLOB:
3060   case MYSQL_TYPE_LONG_BLOB:
3061     sql_field->pack_flag=FIELDFLAG_BLOB |
3062       pack_length_to_packflag(sql_field->pack_length -
3063                               portable_sizeof_char_ptr);
3064     if (sql_field->charset->state & MY_CS_BINSORT)
3065       sql_field->pack_flag|=FIELDFLAG_BINARY;
3066     sql_field->length=8;			// Unireg field length
3067     sql_field->unireg_check=Field::BLOB_FIELD;
3068     (*blob_columns)++;
3069     break;
3070   case MYSQL_TYPE_GEOMETRY:
3071     if (!(table_flags & HA_CAN_GEOMETRY))
3072     {
3073       my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
3074                       MYF(0), "GEOMETRY");
3075       DBUG_RETURN(1);
3076     }
3077     sql_field->pack_flag=FIELDFLAG_GEOM |
3078       pack_length_to_packflag(sql_field->pack_length -
3079                               portable_sizeof_char_ptr);
3080     if (sql_field->charset->state & MY_CS_BINSORT)
3081       sql_field->pack_flag|=FIELDFLAG_BINARY;
3082     sql_field->length=8;			// Unireg field length
3083     sql_field->unireg_check=Field::BLOB_FIELD;
3084     (*blob_columns)++;
3085     break;
3086   case MYSQL_TYPE_JSON:
3087     // JSON fields are stored as BLOBs.
3088     sql_field->pack_flag=FIELDFLAG_JSON |
3089       pack_length_to_packflag(sql_field->pack_length -
3090                               portable_sizeof_char_ptr);
3091     if (sql_field->charset->state & MY_CS_BINSORT)
3092       sql_field->pack_flag|=FIELDFLAG_BINARY;
3093     sql_field->length=8;                        // Unireg field length
3094     sql_field->unireg_check=Field::BLOB_FIELD;
3095     (*blob_columns)++;
3096     break;
3097   case MYSQL_TYPE_VARCHAR:
3098     if (table_flags & HA_NO_VARCHAR)
3099     {
3100       /* convert VARCHAR to CHAR because handler is not yet up to date */
3101       sql_field->sql_type=    MYSQL_TYPE_VAR_STRING;
3102       sql_field->pack_length= calc_pack_length(sql_field->sql_type,
3103                                                (uint) sql_field->length);
3104       if ((sql_field->length / sql_field->charset->mbmaxlen) >
3105           MAX_FIELD_CHARLENGTH)
3106       {
3107         my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
3108                         MYF(0), sql_field->field_name,
3109                         static_cast<ulong>(MAX_FIELD_CHARLENGTH));
3110         DBUG_RETURN(1);
3111       }
3112     }
3113     /* fall through */
3114   case MYSQL_TYPE_STRING:
3115     sql_field->pack_flag=0;
3116     if (sql_field->charset->state & MY_CS_BINSORT)
3117       sql_field->pack_flag|=FIELDFLAG_BINARY;
3118     break;
3119   case MYSQL_TYPE_ENUM:
3120     sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
3121       FIELDFLAG_INTERVAL;
3122     if (sql_field->charset->state & MY_CS_BINSORT)
3123       sql_field->pack_flag|=FIELDFLAG_BINARY;
3124     sql_field->unireg_check=Field::INTERVAL_FIELD;
3125     if (check_duplicates_in_interval("ENUM",sql_field->field_name,
3126                                      sql_field->interval,
3127                                      sql_field->charset, &dup_val_count))
3128       DBUG_RETURN(1);
3129     break;
3130   case MYSQL_TYPE_SET:
3131     sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
3132       FIELDFLAG_BITFIELD;
3133     if (sql_field->charset->state & MY_CS_BINSORT)
3134       sql_field->pack_flag|=FIELDFLAG_BINARY;
3135     sql_field->unireg_check=Field::BIT_FIELD;
3136     if (check_duplicates_in_interval("SET",sql_field->field_name,
3137                                      sql_field->interval,
3138                                      sql_field->charset, &dup_val_count))
3139       DBUG_RETURN(1);
3140     /* Check that count of unique members is not more then 64 */
3141     if (sql_field->interval->count -  dup_val_count > sizeof(longlong)*8)
3142     {
3143        my_error(ER_TOO_BIG_SET, MYF(0), sql_field->field_name);
3144        DBUG_RETURN(1);
3145     }
3146     break;
3147   case MYSQL_TYPE_DATE:			// Rest of string types
3148   case MYSQL_TYPE_NEWDATE:
3149   case MYSQL_TYPE_TIME:
3150   case MYSQL_TYPE_DATETIME:
3151   case MYSQL_TYPE_TIME2:
3152   case MYSQL_TYPE_DATETIME2:
3153   case MYSQL_TYPE_NULL:
3154     sql_field->pack_flag=f_settype((uint) sql_field->sql_type);
3155     break;
3156   case MYSQL_TYPE_BIT:
3157     /*
3158       We have sql_field->pack_flag already set here, see
3159       mysql_prepare_create_table().
3160     */
3161     break;
3162   case MYSQL_TYPE_NEWDECIMAL:
3163     sql_field->pack_flag=(FIELDFLAG_NUMBER |
3164                           (sql_field->flags & UNSIGNED_FLAG ? 0 :
3165                            FIELDFLAG_DECIMAL) |
3166                           (sql_field->flags & ZEROFILL_FLAG ?
3167                            FIELDFLAG_ZEROFILL : 0) |
3168                           (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
3169     break;
3170   case MYSQL_TYPE_TIMESTAMP:
3171   case MYSQL_TYPE_TIMESTAMP2:
3172     /* fall-through */
3173   default:
3174     sql_field->pack_flag=(FIELDFLAG_NUMBER |
3175                           (sql_field->flags & UNSIGNED_FLAG ? 0 :
3176                            FIELDFLAG_DECIMAL) |
3177                           (sql_field->flags & ZEROFILL_FLAG ?
3178                            FIELDFLAG_ZEROFILL : 0) |
3179                           f_settype((uint) sql_field->sql_type) |
3180                           (sql_field->decimals << FIELDFLAG_DEC_SHIFT));
3181     break;
3182   }
3183   if (!(sql_field->flags & NOT_NULL_FLAG))
3184     sql_field->pack_flag|= FIELDFLAG_MAYBE_NULL;
3185   if (sql_field->flags & NO_DEFAULT_VALUE_FLAG)
3186     sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
3187   DBUG_RETURN(0);
3188 }
3189 
3190 
create_typelib(MEM_ROOT * mem_root,Create_field * field_def,List<String> * src)3191 static TYPELIB *create_typelib(MEM_ROOT *mem_root,
3192                                Create_field *field_def,
3193                                List<String> *src)
3194 {
3195   const CHARSET_INFO *cs= field_def->charset;
3196 
3197   if (!src->elements)
3198     return NULL;
3199 
3200   TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB));
3201   result->count= src->elements;
3202   result->name= "";
3203   if (!(result->type_names=(const char **)
3204         alloc_root(mem_root,(sizeof(char *)+sizeof(int))*(result->count+1))))
3205     return NULL;
3206   result->type_lengths= (uint*)(result->type_names + result->count+1);
3207   List_iterator<String> it(*src);
3208   String conv;
3209   for (uint i=0; i < result->count; i++)
3210   {
3211     size_t dummy;
3212     size_t length;
3213     String *tmp= it++;
3214 
3215     if (String::needs_conversion(tmp->length(), tmp->charset(),
3216                                  cs, &dummy))
3217     {
3218       uint cnv_errs;
3219       conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
3220 
3221       length= conv.length();
3222       result->type_names[i]= strmake_root(mem_root, conv.ptr(),
3223                                           length);
3224     }
3225     else
3226     {
3227       length= tmp->length();
3228       result->type_names[i]= strmake_root(mem_root, tmp->ptr(), length);
3229     }
3230 
3231     // Strip trailing spaces.
3232     length= cs->cset->lengthsp(cs, result->type_names[i], length);
3233     result->type_lengths[i]= length;
3234     ((uchar *)result->type_names[i])[length]= '\0';
3235   }
3236   result->type_names[result->count]= 0;
3237   result->type_lengths[result->count]= 0;
3238 
3239   return result;
3240 }
3241 
3242 
3243 /**
3244   Prepare an instance of Create_field for field creation
3245   (fill all necessary attributes).
3246 
3247   @param[in]  thd          Thread handle
3248   @param[in]  sp           The current SP
3249   @param[in]  field_type   Field type
3250   @param[out] field_def    An instance of create_field to be filled
3251 
3252   @return Error status.
3253 */
3254 
fill_field_definition(THD * thd,sp_head * sp,enum enum_field_types field_type,Create_field * field_def)3255 bool fill_field_definition(THD *thd,
3256                            sp_head *sp,
3257                            enum enum_field_types field_type,
3258                            Create_field *field_def)
3259 {
3260   LEX *lex= thd->lex;
3261   LEX_STRING cmt = { 0, 0 };
3262   uint unused1= 0;
3263 
3264   if (field_def->init(thd, (char*) "", field_type, lex->length, lex->dec,
3265                       lex->type, (Item*) 0, (Item*) 0, &cmt, 0,
3266                       &lex->interval_list,
3267                       lex->charset ? lex->charset :
3268                                      thd->variables.collation_database,
3269                       lex->uint_geom_type, NULL))
3270   {
3271     return true;
3272   }
3273 
3274   if (field_def->interval_list.elements)
3275   {
3276     field_def->interval= create_typelib(sp->get_current_mem_root(),
3277                                         field_def,
3278                                         &field_def->interval_list);
3279   }
3280 
3281   sp_prepare_create_field(thd, field_def);
3282 
3283   return prepare_create_field(field_def, &unused1, HA_CAN_GEOMETRY);
3284 }
3285 
3286 /*
3287   Get character set from field object generated by parser using
3288   default values when not set.
3289 
3290   SYNOPSIS
3291     get_sql_field_charset()
3292     sql_field                 The sql_field object
3293     create_info               Info generated by parser
3294 
3295   RETURN VALUES
3296     cs                        Character set
3297 */
3298 
get_sql_field_charset(Create_field * sql_field,HA_CREATE_INFO * create_info)3299 const CHARSET_INFO* get_sql_field_charset(Create_field *sql_field,
3300                                           HA_CREATE_INFO *create_info)
3301 {
3302   const CHARSET_INFO *cs= sql_field->charset;
3303 
3304   if (!cs)
3305     cs= create_info->default_table_charset;
3306   /*
3307     table_charset is set only in ALTER TABLE t1 CONVERT TO CHARACTER SET csname
3308     if we want change character set for all varchar/char columns.
3309     But the table charset must not affect the BLOB fields, so don't
3310     allow to change my_charset_bin to somethig else.
3311   */
3312   if (create_info->table_charset && cs != &my_charset_bin)
3313     cs= create_info->table_charset;
3314   return cs;
3315 }
3316 
3317 
3318 /**
3319    Modifies the first column definition whose SQL type is TIMESTAMP
3320    by adding the features DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP.
3321 
3322    @param column_definitions The list of column definitions, in the physical
3323                              order in which they appear in the table.
3324  */
promote_first_timestamp_column(List<Create_field> * column_definitions)3325 void promote_first_timestamp_column(List<Create_field> *column_definitions)
3326 {
3327   List_iterator<Create_field> it(*column_definitions);
3328   Create_field *column_definition;
3329 
3330   while ((column_definition= it++) != NULL)
3331   {
3332     if (column_definition->sql_type == MYSQL_TYPE_TIMESTAMP ||      // TIMESTAMP
3333         column_definition->sql_type == MYSQL_TYPE_TIMESTAMP2 || //  ms TIMESTAMP
3334         column_definition->unireg_check == Field::TIMESTAMP_OLD_FIELD) // Legacy
3335     {
3336       if ((column_definition->flags & NOT_NULL_FLAG) != 0 && // NOT NULL,
3337           column_definition->def == NULL &&            // no constant default,
3338           column_definition->gcol_info == NULL &&      // not a generated column
3339           column_definition->unireg_check == Field::NONE) // no function default
3340       {
3341         DBUG_PRINT("info", ("First TIMESTAMP column '%s' was promoted to "
3342                             "DEFAULT CURRENT_TIMESTAMP ON UPDATE "
3343                             "CURRENT_TIMESTAMP",
3344                             column_definition->field_name
3345                             ));
3346         column_definition->unireg_check= Field::TIMESTAMP_DNUN_FIELD;
3347       }
3348       return;
3349     }
3350   }
3351 }
3352 
3353 
3354 /**
3355   Check if there is a duplicate key. Report a warning for every duplicate key.
3356 
3357   @param thd                Thread context.
3358   @param error_schema_name  Schema name of the table used for error reporting.
3359   @param error_table_name   Table name used for error reporting.
3360   @param key                Key to be checked.
3361   @param key_info           Key meta-data info.
3362   @param alter_info         List of columns and indexes to create.
3363 
3364   @retval false           Ok.
3365   @retval true            Error.
3366 */
check_duplicate_key(THD * thd,const char * error_schema_name,const char * error_table_name,Key * key,KEY * key_info,Alter_info * alter_info)3367 static bool check_duplicate_key(THD *thd, const char *error_schema_name,
3368                                 const char *error_table_name,
3369                                 Key *key, KEY *key_info,
3370                                 Alter_info *alter_info)
3371 {
3372   /*
3373     We only check for duplicate indexes if it is requested and the
3374     key is not auto-generated.
3375 
3376     Check is requested if the key was explicitly created or altered
3377     (Index is altered/column associated with it is dropped) by the user
3378     (unless it's a foreign key).
3379   */
3380   if (!key->key_create_info.check_for_duplicate_indexes || key->generated)
3381     return false;
3382 
3383   List_iterator<Key> key_list_iterator(alter_info->key_list);
3384   List_iterator<Key_part_spec> key_column_iterator(key->columns);
3385   Key *k;
3386 
3387   while ((k= key_list_iterator++))
3388   {
3389     // Looking for a similar key...
3390 
3391     if (k == key)
3392     {
3393       /*
3394         Since the duplicate index might exist before or after
3395         the modified key in the list, we continue the
3396         comparison with rest of the keys in case of DROP COLUMN
3397         operation.
3398       */
3399       if (alter_info->flags & Alter_info::ALTER_DROP_COLUMN)
3400         continue;
3401       else
3402         break;
3403     }
3404 
3405     if (k->generated ||
3406         (key->type != k->type) ||
3407         (key->key_create_info.algorithm != k->key_create_info.algorithm) ||
3408         (key->columns.elements != k->columns.elements))
3409     {
3410       // Keys are different.
3411       continue;
3412     }
3413 
3414     /*
3415       Keys 'key' and 'k' might be identical.
3416       Check that the keys have identical columns in the same order.
3417     */
3418 
3419     List_iterator<Key_part_spec> k_column_iterator(k->columns);
3420 
3421     bool all_columns_are_identical= true;
3422 
3423     key_column_iterator.rewind();
3424 
3425     for (uint i= 0; i < key->columns.elements; ++i)
3426     {
3427       Key_part_spec *c1= key_column_iterator++;
3428       Key_part_spec *c2= k_column_iterator++;
3429 
3430       assert(c1 && c2);
3431 
3432       if (my_strcasecmp(system_charset_info,
3433                         c1->field_name.str, c2->field_name.str) ||
3434           (c1->length != c2->length))
3435       {
3436         all_columns_are_identical= false;
3437         break;
3438       }
3439     }
3440 
3441     // Report a warning if we have two identical keys.
3442 
3443     if (all_columns_are_identical)
3444     {
3445       push_warning_printf(thd, Sql_condition::SL_WARNING,
3446                           ER_DUP_INDEX, ER(ER_DUP_INDEX),
3447                           key_info->name,
3448                           error_schema_name,
3449                           error_table_name);
3450       if (thd->is_error())
3451       {
3452         // An error was reported.
3453         return true;
3454       }
3455       break;
3456     }
3457   }
3458   return false;
3459 }
3460 
3461 
3462 /*
3463   Preparation for table creation
3464 
3465   SYNOPSIS
3466     mysql_prepare_create_table()
3467       thd                       Thread object.
3468       error_schema_name         Schema name of the table to create/alter,only
3469                                 used for error reporting.
3470       error_table_name          Name of table to create/alter, only used for
3471                                 error reporting.
3472       create_info               Create information (like MAX_ROWS).
3473       alter_info                List of columns and indexes to create
3474       tmp_table                 If a temporary table is to be created.
3475       db_options          INOUT Table options (like HA_OPTION_PACK_RECORD).
3476       file                      The handler for the new table.
3477       key_info_buffer     OUT   An array of KEY structs for the indexes.
3478       key_count           OUT   The number of elements in the array.
3479       select_field_count        The number of fields coming from a select table.
3480 
3481   DESCRIPTION
3482     Prepares the table and key structures for table creation.
3483 
3484   NOTES
3485     sets create_info->varchar if the table has a varchar
3486 
3487   RETURN VALUES
3488     FALSE    OK
3489     TRUE     error
3490 */
3491 
3492 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)3493 mysql_prepare_create_table(THD *thd, const char *error_schema_name,
3494                            const char *error_table_name,
3495                            HA_CREATE_INFO *create_info,
3496                            Alter_info *alter_info,
3497                            bool tmp_table,
3498                            uint *db_options,
3499                            handler *file, KEY **key_info_buffer,
3500                            uint *key_count, int select_field_count)
3501 {
3502   const char	*key_name;
3503   Create_field	*sql_field,*dup_field;
3504   uint		field,null_fields,blob_columns,max_key_length;
3505   size_t	record_offset= 0;
3506   KEY		*key_info;
3507   KEY_PART_INFO *key_part_info;
3508   int		field_no,dup_no;
3509   int		select_field_pos,auto_increment=0;
3510   List_iterator<Create_field> it(alter_info->create_list);
3511   List_iterator<Create_field> it2(alter_info->create_list);
3512   uint total_uneven_bit_length= 0;
3513   DBUG_ENTER("mysql_prepare_create_table");
3514 
3515   LEX_STRING* connect_string = &create_info->connect_string;
3516   if (connect_string->length != 0 &&
3517       connect_string->length > CONNECT_STRING_MAXLEN &&
3518       (system_charset_info->cset->charpos(system_charset_info,
3519                                           connect_string->str,
3520                                           (connect_string->str +
3521                                            connect_string->length),
3522                                           CONNECT_STRING_MAXLEN)
3523       < connect_string->length))
3524   {
3525     my_error(ER_WRONG_STRING_LENGTH, MYF(0),
3526              connect_string->str, "CONNECTION", CONNECT_STRING_MAXLEN);
3527     DBUG_RETURN(TRUE);
3528   }
3529 
3530   select_field_pos= alter_info->create_list.elements - select_field_count;
3531   null_fields=blob_columns=0;
3532   create_info->varchar= 0;
3533   max_key_length= file->max_key_length();
3534 
3535   for (field_no=0; (sql_field=it++) ; field_no++)
3536   {
3537     const CHARSET_INFO *save_cs;
3538 
3539     /*
3540       Initialize length from its original value (number of characters),
3541       which was set in the parser. This is necessary if we're
3542       executing a prepared statement for the second time.
3543     */
3544     sql_field->length= sql_field->char_length;
3545     /* Set field charset. */
3546     save_cs= sql_field->charset= get_sql_field_charset(sql_field,
3547                                                        create_info);
3548     if (sql_field->flags & BINCMP_FLAG)
3549     {
3550       // e.g. CREATE TABLE t1 (a CHAR(1) BINARY);
3551       if (!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
3552                                                       MY_CS_BINSORT,MYF(0))))
3553       {
3554         char tmp[65];
3555         strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4),
3556                 STRING_WITH_LEN("_bin"));
3557         my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
3558         DBUG_RETURN(TRUE);
3559       }
3560       /*
3561         Now that we have sql_field->charset set properly,
3562         we don't need the BINCMP_FLAG any longer.
3563       */
3564       sql_field->flags&= ~BINCMP_FLAG;
3565     }
3566 
3567     /*
3568       Convert the default value from client character
3569       set into the column character set if necessary.
3570     */
3571     if (sql_field->def &&
3572         save_cs != sql_field->def->collation.collation &&
3573         (sql_field->sql_type == MYSQL_TYPE_VAR_STRING ||
3574          sql_field->sql_type == MYSQL_TYPE_STRING ||
3575          sql_field->sql_type == MYSQL_TYPE_SET ||
3576          sql_field->sql_type == MYSQL_TYPE_ENUM))
3577     {
3578       /*
3579         Starting from 5.1 we work here with a copy of Create_field
3580         created by the caller, not with the instance that was
3581         originally created during parsing. It's OK to create
3582         a temporary item and initialize with it a member of the
3583         copy -- this item will be thrown away along with the copy
3584         at the end of execution, and thus not introduce a dangling
3585         pointer in the parsed tree of a prepared statement or a
3586         stored procedure statement.
3587       */
3588       sql_field->def= sql_field->def->safe_charset_converter(save_cs);
3589 
3590       if (sql_field->def == NULL)
3591       {
3592         /* Could not convert */
3593         my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
3594         DBUG_RETURN(TRUE);
3595       }
3596     }
3597 
3598     if (sql_field->sql_type == MYSQL_TYPE_SET ||
3599         sql_field->sql_type == MYSQL_TYPE_ENUM)
3600     {
3601       size_t dummy;
3602       const CHARSET_INFO *cs= sql_field->charset;
3603       TYPELIB *interval= sql_field->interval;
3604 
3605       /*
3606         Create typelib from interval_list, and if necessary
3607         convert strings from client character set to the
3608         column character set.
3609       */
3610       if (!interval)
3611       {
3612         /*
3613           Create the typelib in runtime memory - we will free the
3614           occupied memory at the same time when we free this
3615           sql_field -- at the end of execution.
3616         */
3617         interval= sql_field->interval= typelib(thd->mem_root,
3618                                                sql_field->interval_list);
3619         List_iterator<String> int_it(sql_field->interval_list);
3620         String conv, *tmp;
3621         char comma_buf[4]; /* 4 bytes for utf32 */
3622         int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
3623                                           (uchar*) comma_buf +
3624                                           sizeof(comma_buf));
3625         assert(comma_length > 0);
3626         for (uint i= 0; (tmp= int_it++); i++)
3627         {
3628           size_t lengthsp;
3629           size_t dummy2;
3630           if (String::needs_conversion(tmp->length(), tmp->charset(),
3631                                        cs, &dummy2))
3632           {
3633             uint cnv_errs;
3634             conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
3635             interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
3636                                                   conv.length());
3637             interval->type_lengths[i]= conv.length();
3638           }
3639 
3640           // Strip trailing spaces.
3641           lengthsp= cs->cset->lengthsp(cs, interval->type_names[i],
3642                                        interval->type_lengths[i]);
3643           interval->type_lengths[i]= lengthsp;
3644           ((uchar *)interval->type_names[i])[lengthsp]= '\0';
3645           if (sql_field->sql_type == MYSQL_TYPE_SET)
3646           {
3647             if (cs->coll->instr(cs, interval->type_names[i],
3648                                 interval->type_lengths[i],
3649                                 comma_buf, comma_length, NULL, 0))
3650             {
3651               ErrConvString err(tmp->ptr(), tmp->length(), cs);
3652               my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "set", err.ptr());
3653               DBUG_RETURN(TRUE);
3654             }
3655           }
3656         }
3657         sql_field->interval_list.empty(); // Don't need interval_list anymore
3658       }
3659 
3660       if (sql_field->sql_type == MYSQL_TYPE_SET)
3661       {
3662         size_t field_length;
3663         if (sql_field->def != NULL)
3664         {
3665           char *not_used;
3666           uint not_used2;
3667           bool not_found= 0;
3668           String str, *def= sql_field->def->val_str(&str);
3669           if (def == NULL) /* SQL "NULL" maps to NULL */
3670           {
3671             if ((sql_field->flags & NOT_NULL_FLAG) != 0)
3672             {
3673               my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
3674               DBUG_RETURN(TRUE);
3675             }
3676 
3677             /* else, NULL is an allowed value */
3678             (void) find_set(interval, NULL, 0,
3679                             cs, &not_used, &not_used2, &not_found);
3680           }
3681           else /* not NULL */
3682           {
3683             (void) find_set(interval, def->ptr(), def->length(),
3684                             cs, &not_used, &not_used2, &not_found);
3685           }
3686 
3687           if (not_found)
3688           {
3689             my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
3690             DBUG_RETURN(TRUE);
3691           }
3692         }
3693         calculate_interval_lengths(cs, interval, &dummy, &field_length);
3694         sql_field->length= field_length + (interval->count - 1);
3695       }
3696       else  /* MYSQL_TYPE_ENUM */
3697       {
3698         size_t field_length;
3699         assert(sql_field->sql_type == MYSQL_TYPE_ENUM);
3700         if (sql_field->def != NULL)
3701         {
3702           String str, *def= sql_field->def->val_str(&str);
3703           if (def == NULL) /* SQL "NULL" maps to NULL */
3704           {
3705             if ((sql_field->flags & NOT_NULL_FLAG) != 0)
3706             {
3707               my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
3708               DBUG_RETURN(TRUE);
3709             }
3710 
3711             /* else, the defaults yield the correct length for NULLs. */
3712           }
3713           else /* not NULL */
3714           {
3715             def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
3716             if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
3717             {
3718               my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
3719               DBUG_RETURN(TRUE);
3720             }
3721           }
3722         }
3723         calculate_interval_lengths(cs, interval, &field_length, &dummy);
3724         sql_field->length= field_length;
3725       }
3726       set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
3727     }
3728 
3729     if (sql_field->sql_type == MYSQL_TYPE_BIT)
3730     {
3731       sql_field->pack_flag= FIELDFLAG_NUMBER;
3732       if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
3733         total_uneven_bit_length+= sql_field->length & 7;
3734       else
3735         sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
3736     }
3737 
3738     sql_field->create_length_to_internal_length();
3739     if (prepare_blob_field(thd, sql_field))
3740       DBUG_RETURN(TRUE);
3741 
3742     if (!(sql_field->flags & NOT_NULL_FLAG))
3743       null_fields++;
3744 
3745     if (check_column_name(sql_field->field_name))
3746     {
3747       my_error(ER_WRONG_COLUMN_NAME, MYF(0), sql_field->field_name);
3748       DBUG_RETURN(TRUE);
3749     }
3750 
3751     /* Check if we have used the same field name before */
3752     for (dup_no=0; (dup_field=it2++) != sql_field; dup_no++)
3753     {
3754       if (my_strcasecmp(system_charset_info,
3755 			sql_field->field_name,
3756 			dup_field->field_name) == 0)
3757       {
3758 	/*
3759 	  If this was a CREATE ... SELECT statement, accept a field
3760 	  redefinition if we are changing a field in the SELECT part
3761 	*/
3762 	if (field_no < select_field_pos || dup_no >= select_field_pos)
3763 	{
3764 	  my_error(ER_DUP_FIELDNAME, MYF(0), sql_field->field_name);
3765 	  DBUG_RETURN(TRUE);
3766 	}
3767 	else
3768 	{
3769 	  /* Field redefined */
3770 
3771           /*
3772             If we are replacing a BIT field, revert the increment
3773             of total_uneven_bit_length that was done above.
3774           */
3775           if (sql_field->sql_type == MYSQL_TYPE_BIT &&
3776               file->ha_table_flags() & HA_CAN_BIT_FIELD)
3777             total_uneven_bit_length-= sql_field->length & 7;
3778 
3779 	  sql_field->def=		dup_field->def;
3780 	  sql_field->sql_type=		dup_field->sql_type;
3781 
3782           /*
3783             If we are replacing a field with a BIT field, we need
3784             to initialize pack_flag. Note that we do not need to
3785             increment total_uneven_bit_length here as this dup_field
3786             has already been processed.
3787           */
3788           if (sql_field->sql_type == MYSQL_TYPE_BIT)
3789           {
3790             sql_field->pack_flag= FIELDFLAG_NUMBER;
3791             if (!(file->ha_table_flags() & HA_CAN_BIT_FIELD))
3792               sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
3793           }
3794 
3795 	  sql_field->charset=		(dup_field->charset ?
3796 					 dup_field->charset :
3797 					 create_info->default_table_charset);
3798 	  sql_field->length=		dup_field->char_length;
3799           sql_field->pack_length=	dup_field->pack_length;
3800           sql_field->key_length=	dup_field->key_length;
3801 	  sql_field->decimals=		dup_field->decimals;
3802 	  sql_field->unireg_check=	dup_field->unireg_check;
3803           /*
3804             We're making one field from two, the result field will have
3805             dup_field->flags as flags. If we've incremented null_fields
3806             because of sql_field->flags, decrement it back.
3807           */
3808           if (!(sql_field->flags & NOT_NULL_FLAG))
3809             null_fields--;
3810 	  sql_field->flags=		dup_field->flags;
3811 	  sql_field->create_length_to_internal_length();
3812           sql_field->interval=          dup_field->interval;
3813           sql_field->gcol_info=         dup_field->gcol_info;
3814           sql_field->stored_in_db=      dup_field->stored_in_db;
3815 	  it2.remove();			// Remove first (create) definition
3816 	  select_field_pos--;
3817 	  break;
3818 	}
3819       }
3820     }
3821     /* Don't pack rows in old tables if the user has requested this */
3822     if ((sql_field->flags & BLOB_FLAG) ||
3823 	(sql_field->sql_type == MYSQL_TYPE_VARCHAR &&
3824 	create_info->row_type != ROW_TYPE_FIXED))
3825       (*db_options)|= HA_OPTION_PACK_RECORD;
3826     it2.rewind();
3827   }
3828 
3829   /* record_offset will be increased with 'length-of-null-bits' later */
3830   record_offset= 0;
3831   null_fields+= total_uneven_bit_length;
3832 
3833   bool has_vgc= false;
3834   it.rewind();
3835   while ((sql_field=it++))
3836   {
3837     assert(sql_field->charset != 0);
3838 
3839     if (prepare_create_field(sql_field, &blob_columns,
3840 			     file->ha_table_flags()))
3841       DBUG_RETURN(TRUE);
3842     if (sql_field->sql_type == MYSQL_TYPE_VARCHAR)
3843       create_info->varchar= TRUE;
3844     sql_field->offset= record_offset;
3845     if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
3846       auto_increment++;
3847     /*
3848       For now skip fields that are not physically stored in the database
3849       (generated fields) and update their offset later
3850       (see the next loop).
3851     */
3852     if (sql_field->stored_in_db)
3853       record_offset+= sql_field->pack_length;
3854     else
3855       has_vgc= true;
3856   }
3857   /* Update generated fields' offset*/
3858   if (has_vgc)
3859   {
3860     it.rewind();
3861     while ((sql_field=it++))
3862     {
3863       if (!sql_field->stored_in_db)
3864       {
3865         sql_field->offset= record_offset;
3866         record_offset+= sql_field->pack_length;
3867       }
3868     }
3869   }
3870   if (auto_increment > 1)
3871   {
3872     my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
3873     DBUG_RETURN(TRUE);
3874   }
3875   if (auto_increment &&
3876       (file->ha_table_flags() & HA_NO_AUTO_INCREMENT))
3877   {
3878     my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
3879                ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
3880     DBUG_RETURN(TRUE);
3881   }
3882 
3883   if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
3884   {
3885     my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
3886                MYF(0));
3887     DBUG_RETURN(TRUE);
3888   }
3889 
3890   /*
3891    CREATE TABLE[with auto_increment column] SELECT is unsafe as the rows
3892    inserted in the created table depends on the order of the rows fetched
3893    from the select tables. This order may differ on master and slave. We
3894    therefore mark it as unsafe.
3895   */
3896   if (select_field_count > 0 && auto_increment)
3897   thd->lex->set_stmt_unsafe(LEX::BINLOG_STMT_UNSAFE_CREATE_SELECT_AUTOINC);
3898 
3899   /* Create keys */
3900 
3901   List_iterator<Key> key_iterator(alter_info->key_list);
3902   List_iterator<Key> key_iterator2(alter_info->key_list);
3903   uint key_parts=0, fk_key_count=0;
3904   bool primary_key=0,unique_key=0;
3905   Key *key, *key2;
3906   uint tmp, key_number;
3907   /* special marker for keys to be ignored */
3908   static char ignore_key[1];
3909 
3910   /* Calculate number of key segements */
3911   *key_count= 0;
3912 
3913   while ((key=key_iterator++))
3914   {
3915     DBUG_PRINT("info", ("key name: '%s'  type: %d", key->name.str ? key->name.str :
3916                         "(none)" , key->type));
3917     if (key->type == KEYTYPE_FOREIGN)
3918     {
3919       fk_key_count++;
3920       if (((Foreign_key *)key)->validate(alter_info->create_list))
3921         DBUG_RETURN(TRUE);
3922       Foreign_key *fk_key= (Foreign_key*) key;
3923       if (fk_key->ref_columns.elements &&
3924 	  fk_key->ref_columns.elements != fk_key->columns.elements)
3925       {
3926         my_error(ER_WRONG_FK_DEF, MYF(0),
3927                  (fk_key->name.str ? fk_key->name.str :
3928                                      "foreign key without name"),
3929                  ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
3930 	DBUG_RETURN(TRUE);
3931       }
3932       continue;
3933     }
3934     (*key_count)++;
3935     tmp=file->max_key_parts();
3936     if (key->columns.elements > tmp && key->type != KEYTYPE_SPATIAL)
3937     {
3938       my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
3939       DBUG_RETURN(TRUE);
3940     }
3941 
3942     LEX_CSTRING key_name_cstr= {key->name.str, key->name.length};
3943     if (check_string_char_length(key_name_cstr, "", NAME_CHAR_LEN,
3944                                  system_charset_info, 1))
3945     {
3946       my_error(ER_TOO_LONG_IDENT, MYF(0), key->name.str);
3947       DBUG_RETURN(TRUE);
3948     }
3949     key_iterator2.rewind ();
3950     if (key->type != KEYTYPE_FOREIGN)
3951     {
3952       while ((key2 = key_iterator2++) != key)
3953       {
3954 	/*
3955           foreign_key_prefix(key, key2) returns 0 if key or key2, or both, is
3956           'generated', and a generated key is a prefix of the other key.
3957           Then we do not need the generated shorter key.
3958 
3959           KEYTYPE_SPATIAL and KEYTYPE_FULLTEXT cannot be used as
3960           supporting keys for foreign key constraints even if the
3961           generated key is prefix of such a key.
3962         */
3963         if ((key2->type != KEYTYPE_FOREIGN &&
3964              key2->type != KEYTYPE_SPATIAL &&
3965              key2->type != KEYTYPE_FULLTEXT &&
3966              key2->name.str != ignore_key &&
3967              !foreign_key_prefix(key, key2)))
3968         {
3969           /* TODO: issue warning message */
3970           /* mark that the generated key should be ignored */
3971           if (!key2->generated ||
3972               (key->generated && key->columns.elements <
3973                key2->columns.elements))
3974             key->name.str= ignore_key;
3975           else
3976           {
3977             key2->name.str= ignore_key;
3978             key_parts-= key2->columns.elements;
3979             (*key_count)--;
3980           }
3981           break;
3982         }
3983       }
3984     }
3985     if (key->name.str != ignore_key)
3986       key_parts+=key->columns.elements;
3987     else
3988       (*key_count)--;
3989     if (key->name.str && !tmp_table && (key->type != KEYTYPE_PRIMARY) &&
3990 	!my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
3991     {
3992       my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
3993       DBUG_RETURN(TRUE);
3994     }
3995   }
3996   tmp=file->max_keys();
3997   if (*key_count > tmp)
3998   {
3999     my_error(ER_TOO_MANY_KEYS,MYF(0),tmp);
4000     DBUG_RETURN(TRUE);
4001   }
4002 
4003   (*key_info_buffer)= key_info= (KEY*) sql_calloc(sizeof(KEY) * (*key_count));
4004   key_part_info=(KEY_PART_INFO*) sql_calloc(sizeof(KEY_PART_INFO)*key_parts);
4005   if (!*key_info_buffer || ! key_part_info)
4006     DBUG_RETURN(TRUE);				// Out of memory
4007 
4008   key_iterator.rewind();
4009   key_number=0;
4010   for (; (key=key_iterator++) ; key_number++)
4011   {
4012     size_t key_length=0;
4013     Key_part_spec *column;
4014 
4015     if (key->name.str == ignore_key)
4016     {
4017       /* ignore redundant keys */
4018       do
4019 	key=key_iterator++;
4020       while (key && key->name.str == ignore_key);
4021       if (!key)
4022 	break;
4023     }
4024 
4025     switch (key->type) {
4026     case KEYTYPE_MULTIPLE:
4027 	key_info->flags= 0;
4028 	break;
4029     case KEYTYPE_FULLTEXT:
4030 	key_info->flags= HA_FULLTEXT;
4031 	if ((key_info->parser_name= &key->key_create_info.parser_name)->str)
4032           key_info->flags|= HA_USES_PARSER;
4033         else
4034           key_info->parser_name= 0;
4035 	break;
4036     case KEYTYPE_SPATIAL:
4037 	key_info->flags= HA_SPATIAL;
4038 	break;
4039     case KEYTYPE_FOREIGN:
4040       key_number--;				// Skip this key
4041       continue;
4042     default:
4043       key_info->flags = HA_NOSAME;
4044       break;
4045     }
4046     if (key->generated)
4047       key_info->flags|= HA_GENERATED_KEY;
4048 
4049     key_info->algorithm= key->key_create_info.algorithm;
4050     key_info->user_defined_key_parts=(uint8) key->columns.elements;
4051     key_info->actual_key_parts= key_info->user_defined_key_parts;
4052     key_info->key_part=key_part_info;
4053     key_info->usable_key_parts= key_number;
4054 
4055     if (key->type == KEYTYPE_FULLTEXT)
4056     {
4057       key_info->algorithm= HA_KEY_ALG_FULLTEXT;
4058       if (!(file->ha_table_flags() & HA_CAN_FULLTEXT))
4059       {
4060         if (is_ha_partition_handlerton(file->ht))
4061         {
4062           my_message(ER_FULLTEXT_NOT_SUPPORTED_WITH_PARTITIONING,
4063                      ER(ER_FULLTEXT_NOT_SUPPORTED_WITH_PARTITIONING),
4064                      MYF(0));
4065           DBUG_RETURN(TRUE);
4066         }
4067 	my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
4068                    MYF(0));
4069 	DBUG_RETURN(TRUE);
4070       }
4071     }
4072     /*
4073        Make SPATIAL to be RTREE by default
4074        SPATIAL only on BLOB or at least BINARY, this
4075        actually should be replaced by special GEOM type
4076        in near future when new frm file is ready
4077        checking for proper key parts number:
4078     */
4079 
4080     /* TODO: Add proper checks if handler supports key_type and algorithm */
4081     if (key_info->flags & HA_SPATIAL)
4082     {
4083       if (!(file->ha_table_flags() & HA_CAN_RTREEKEYS))
4084       {
4085         my_message(ER_TABLE_CANT_HANDLE_SPKEYS, ER(ER_TABLE_CANT_HANDLE_SPKEYS),
4086                    MYF(0));
4087         DBUG_RETURN(TRUE);
4088       }
4089       if (key_info->user_defined_key_parts != 1)
4090       {
4091         my_error(ER_TOO_MANY_KEY_PARTS, MYF(0), 1);
4092         DBUG_RETURN(TRUE);
4093       }
4094     }
4095     else if (key_info->algorithm == HA_KEY_ALG_RTREE)
4096     {
4097       if ((key_info->user_defined_key_parts & 1) == 1)
4098       {
4099         my_error(ER_TOO_MANY_KEY_PARTS, MYF(0), 1);
4100         DBUG_RETURN(TRUE);
4101       }
4102       /* TODO: To be deleted */
4103       my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
4104       DBUG_RETURN(TRUE);
4105     }
4106 
4107     /* Take block size from key part or table part */
4108     /*
4109       TODO: Add warning if block size changes. We can't do it here, as
4110       this may depend on the size of the key
4111     */
4112     key_info->block_size= (key->key_create_info.block_size ?
4113                            key->key_create_info.block_size :
4114                            create_info->key_block_size);
4115 
4116     if (key_info->block_size)
4117       key_info->flags|= HA_USES_BLOCK_SIZE;
4118 
4119     List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
4120     const CHARSET_INFO *ft_key_charset=0;  // for FULLTEXT
4121     for (uint column_nr=0 ; (column=cols++) ; column_nr++)
4122     {
4123       Key_part_spec *dup_column;
4124 
4125       it.rewind();
4126       field=0;
4127       while ((sql_field=it++) &&
4128 	     my_strcasecmp(system_charset_info,
4129 			   column->field_name.str,
4130 			   sql_field->field_name))
4131 	field++;
4132       if (!sql_field)
4133       {
4134 	my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name.str);
4135 	DBUG_RETURN(TRUE);
4136       }
4137       if (sql_field->is_virtual_gcol())
4138       {
4139         const char *errmsg= NULL;
4140         if (key->type == KEYTYPE_FULLTEXT)
4141           errmsg= "Fulltext index on virtual generated column";
4142         else if (key->type == KEYTYPE_SPATIAL)
4143           errmsg= "Spatial index on virtual generated column";
4144         if (errmsg)
4145         {
4146           my_error(ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN, MYF(0), errmsg);
4147           DBUG_RETURN(TRUE);
4148         }
4149         key_info->flags|= HA_VIRTUAL_GEN_KEY;
4150         /* Check if the storage engine supports indexes on virtual columns. */
4151         if (!(file->ha_table_flags() & HA_CAN_INDEX_VIRTUAL_GENERATED_COLUMN))
4152         {
4153           my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
4154                    ha_resolve_storage_engine_name(file->ht),
4155                    "Index on virtual generated column");
4156           DBUG_RETURN(TRUE);
4157         }
4158       }
4159       while ((dup_column= cols2++) != column)
4160       {
4161         if (!my_strcasecmp(system_charset_info,
4162 	     	           column->field_name.str, dup_column->field_name.str))
4163 	{
4164 	  my_printf_error(ER_DUP_FIELDNAME,
4165 			  ER(ER_DUP_FIELDNAME),MYF(0),
4166 			  column->field_name.str);
4167 	  DBUG_RETURN(TRUE);
4168 	}
4169       }
4170       cols2.rewind();
4171       if (key->type == KEYTYPE_FULLTEXT)
4172       {
4173 	if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
4174 	     sql_field->sql_type != MYSQL_TYPE_VARCHAR &&
4175 	     !f_is_blob(sql_field->pack_flag)) ||
4176 	    sql_field->charset == &my_charset_bin ||
4177 	    sql_field->charset->mbminlen > 1 || // ucs2 doesn't work yet
4178 	    (ft_key_charset && sql_field->charset != ft_key_charset))
4179 	{
4180 	    my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name.str);
4181 	    DBUG_RETURN(-1);
4182 	}
4183 	ft_key_charset=sql_field->charset;
4184 	/*
4185 	  for fulltext keys keyseg length is 1 for blobs (it's ignored in ft
4186 	  code anyway, and 0 (set to column width later) for char's. it has
4187 	  to be correct col width for char's, as char data are not prefixed
4188 	  with length (unlike blobs, where ft code takes data length from a
4189 	  data prefix, ignoring column->length).
4190 	*/
4191 	column->length= MY_TEST(f_is_blob(sql_field->pack_flag));
4192       }
4193       else
4194       {
4195 	column->length*= sql_field->charset->mbmaxlen;
4196 
4197         if (key->type == KEYTYPE_SPATIAL)
4198         {
4199           if (column->length)
4200           {
4201             my_error(ER_WRONG_SUB_KEY, MYF(0));
4202             DBUG_RETURN(TRUE);
4203           }
4204           if (!f_is_geom(sql_field->pack_flag))
4205           {
4206             my_error(ER_SPATIAL_MUST_HAVE_GEOM_COL, MYF(0));
4207             DBUG_RETURN(TRUE);
4208           }
4209         }
4210 
4211         // JSON columns cannot be used as keys.
4212         if (f_is_json(sql_field->pack_flag))
4213         {
4214           my_error(ER_JSON_USED_AS_KEY, MYF(0), column->field_name.str);
4215           DBUG_RETURN(TRUE);
4216         }
4217 
4218 	if (f_is_blob(sql_field->pack_flag) ||
4219             (f_is_geom(sql_field->pack_flag) && key->type != KEYTYPE_SPATIAL))
4220 	{
4221 	  if (!(file->ha_table_flags() & HA_CAN_INDEX_BLOBS))
4222 	  {
4223 	    my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name.str);
4224 	    DBUG_RETURN(TRUE);
4225 	  }
4226           if (f_is_geom(sql_field->pack_flag) && sql_field->geom_type ==
4227               Field::GEOM_POINT)
4228             column->length= MAX_LEN_GEOM_POINT_FIELD;
4229 	  if (!column->length)
4230 	  {
4231 	    my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name.str);
4232 	    DBUG_RETURN(TRUE);
4233 	  }
4234 	}
4235 	if (key->type == KEYTYPE_SPATIAL)
4236 	{
4237 	  if (!column->length)
4238 	  {
4239 	    /*
4240               4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
4241               Lately we'll extend this code to support more dimensions
4242 	    */
4243 	    column->length= 4*sizeof(double);
4244 	  }
4245 	}
4246         /*
4247           Set NO_DEFAULT_VALUE_FLAG for the PRIMARY KEY column if default
4248           values is not explicitly provided for the column in CREATE TABLE
4249           statement and it is not an AUTO_INCREMENT field.
4250 
4251           Default values for TIMESTAMP/DATETIME needs special handling as:
4252 
4253          a) If default is explicitly specified (lets say this as case 1) :
4254               DEFAULT CURRENT_TIMESTAMP
4255               DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
4256             MySQL does not set sql_field->def flag , but sets
4257             Field::TIMESTAMP_DN_FIELD/TIMESTAMP_DNUN_FIELD to the unireg_check.
4258             These flags are also set during timestamp column promotion (case2)
4259 
4260             When explicit_defaults_for_timestamp is not set, the behavior
4261             expected in both case1 and case2 is to retain the defaults even
4262             when the column participates in PRIMARY KEY. When
4263             explicit_defaults_for_timestamp is set, the promotion logic
4264             is disabled and the above mentioned flags are not used implicitly.
4265 
4266          b) If explicit_defaults_for_timestamp variable is not set:
4267              Default value assigned due to first timestamp column promotion is
4268              retained.
4269              Default constant value assigned due to implicit promotion of second
4270              timestamp column is removed.
4271         */
4272         if (key->type == KEYTYPE_PRIMARY && !sql_field->def &&
4273             !(sql_field->flags & AUTO_INCREMENT_FLAG) &&
4274             !(real_type_with_now_as_default(sql_field->sql_type) &&
4275               (sql_field->unireg_check == Field::TIMESTAMP_DN_FIELD ||
4276                sql_field->unireg_check == Field::TIMESTAMP_DNUN_FIELD)))
4277         {
4278           sql_field->flags|= NO_DEFAULT_VALUE_FLAG;
4279           sql_field->pack_flag|= FIELDFLAG_NO_DEFAULT;
4280         }
4281         /*
4282           Emitting error when field is a part of primary key and is
4283           explicitly requested to be NULL by the user.
4284         */
4285         if ((sql_field->flags & EXPLICIT_NULL_FLAG) &&
4286             (key->type == KEYTYPE_PRIMARY))
4287         {
4288           my_error(ER_PRIMARY_CANT_HAVE_NULL, MYF(0));
4289           DBUG_RETURN(true);
4290         }
4291         // Primary key on virtual generated column is not supported.
4292         if (key->type == KEYTYPE_PRIMARY &&
4293             !sql_field->stored_in_db)
4294         {
4295           /* Primary key fields must always be physically stored. */
4296           my_error(ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN, MYF(0),
4297                    "Defining a virtual generated column as primary key");
4298           DBUG_RETURN(TRUE);
4299         }
4300 
4301 	if (!(sql_field->flags & NOT_NULL_FLAG))
4302 	{
4303 	  if (key->type == KEYTYPE_PRIMARY)
4304 	  {
4305 	    /* Implicitly set primary key fields to NOT NULL for ISO conf. */
4306 	    sql_field->flags|= NOT_NULL_FLAG;
4307 	    sql_field->pack_flag&= ~FIELDFLAG_MAYBE_NULL;
4308             null_fields--;
4309 	  }
4310 	  else
4311           {
4312             key_info->flags|= HA_NULL_PART_KEY;
4313             if (!(file->ha_table_flags() & HA_NULL_IN_KEY))
4314             {
4315               my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name.str);
4316               DBUG_RETURN(TRUE);
4317             }
4318             if (key->type == KEYTYPE_SPATIAL)
4319             {
4320               my_message(ER_SPATIAL_CANT_HAVE_NULL,
4321                          ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
4322               DBUG_RETURN(TRUE);
4323             }
4324           }
4325 	}
4326 	if (MTYP_TYPENR(sql_field->unireg_check) == Field::NEXT_NUMBER)
4327 	{
4328 	  if (column_nr == 0 || (file->ha_table_flags() & HA_AUTO_PART_KEY))
4329 	    auto_increment--;			// Field is used
4330 	}
4331       }
4332 
4333       key_part_info->fieldnr= field;
4334       key_part_info->offset=  (uint16) sql_field->offset;
4335       key_part_info->key_type=sql_field->pack_flag;
4336       size_t key_part_length= sql_field->key_length;
4337 
4338       if (column->length)
4339       {
4340 	if (f_is_blob(sql_field->pack_flag))
4341 	{
4342           key_part_length= column->length;
4343           /*
4344             There is a possibility that the given prefix length is less
4345             than the engine max key part length, but still greater
4346             than the BLOB field max size. We handle this case
4347             using the max_field_size variable below.
4348           */
4349           size_t max_field_size= blob_length_by_type(sql_field->sql_type);
4350 	  if (key_part_length > max_field_size ||
4351               key_part_length > max_key_length ||
4352 	      key_part_length > file->max_key_part_length(create_info))
4353 	  {
4354             // Given prefix length is too large, adjust it.
4355 	    key_part_length= min(max_key_length,
4356                                  file->max_key_part_length(create_info));
4357 	    if (max_field_size)
4358               key_part_length= min(key_part_length, max_field_size);
4359 	    if (key->type == KEYTYPE_MULTIPLE)
4360 	    {
4361 	      /* not a critical problem */
4362 	      push_warning_printf(thd, Sql_condition::SL_WARNING,
4363 		                  ER_TOO_LONG_KEY, ER(ER_TOO_LONG_KEY),
4364                                   key_part_length);
4365               /* Align key length to multibyte char boundary */
4366               key_part_length-= key_part_length % sql_field->charset->mbmaxlen;
4367               /*
4368                If SQL_MODE is STRICT, then report error, else report warning
4369                and continue execution.
4370               */
4371               if (thd->is_error())
4372                 DBUG_RETURN(true);
4373 	    }
4374 	    else
4375 	    {
4376 	      my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
4377 	      DBUG_RETURN(TRUE);
4378 	    }
4379 	  }
4380 	}
4381         // Catch invalid use of partial keys
4382 	else if (!f_is_geom(sql_field->pack_flag) &&
4383                  // is the key partial?
4384                  column->length != key_part_length &&
4385                  // is prefix length bigger than field length?
4386                  (column->length > key_part_length ||
4387                   // can the field have a partial key?
4388                   !Field::type_can_have_key_part (sql_field->sql_type) ||
4389                   // a packed field can't be used in a partial key
4390                   f_is_packed(sql_field->pack_flag) ||
4391                   // does the storage engine allow prefixed search?
4392                   ((file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS) &&
4393                    // and is this a 'unique' key?
4394                    (key_info->flags & HA_NOSAME))))
4395         {
4396 	  my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
4397 	  DBUG_RETURN(TRUE);
4398 	}
4399 	else if (!(file->ha_table_flags() & HA_NO_PREFIX_CHAR_KEYS))
4400 	  key_part_length= column->length;
4401       }
4402       else if (key_part_length == 0)
4403       {
4404 	my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name.str);
4405 	  DBUG_RETURN(TRUE);
4406       }
4407       if (key_part_length > file->max_key_part_length(create_info) &&
4408           key->type != KEYTYPE_FULLTEXT)
4409       {
4410         key_part_length= file->max_key_part_length(create_info);
4411 	if (key->type == KEYTYPE_MULTIPLE)
4412 	{
4413 	  /* not a critical problem */
4414 	  push_warning_printf(thd, Sql_condition::SL_WARNING,
4415                               ER_TOO_LONG_KEY, ER(ER_TOO_LONG_KEY),
4416                               key_part_length);
4417           /* Align key length to multibyte char boundary */
4418           key_part_length-= key_part_length % sql_field->charset->mbmaxlen;
4419           /*
4420             If SQL_MODE is STRICT, then report error, else report warning
4421             and continue execution.
4422           */
4423           if (thd->is_error())
4424             DBUG_RETURN(true);
4425 	}
4426 	else
4427 	{
4428 	  my_error(ER_TOO_LONG_KEY, MYF(0), key_part_length);
4429 	  DBUG_RETURN(TRUE);
4430 	}
4431       }
4432       key_part_info->length= (uint16) key_part_length;
4433       /* Use packed keys for long strings on the first column */
4434       if ((create_info->db_type->flags & HTON_SUPPORTS_PACKED_KEYS) &&
4435           !((*db_options) & HA_OPTION_NO_PACK_KEYS) &&
4436           !((create_info->table_options & HA_OPTION_NO_PACK_KEYS)) &&
4437 	  (key_part_length >= KEY_DEFAULT_PACK_LENGTH &&
4438 	   (sql_field->sql_type == MYSQL_TYPE_STRING ||
4439 	    sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
4440 	    sql_field->pack_flag & FIELDFLAG_BLOB)))
4441       {
4442 	if ((column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB)) ||
4443             sql_field->sql_type == MYSQL_TYPE_VARCHAR)
4444 	  key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
4445 	else
4446 	  key_info->flags|= HA_PACK_KEY;
4447       }
4448 
4449       /*
4450          Check if the key segment is partial, set the key flag
4451          accordingly. The key segment for a POINT column is NOT considered
4452          partial if key_length==MAX_LEN_GEOM_POINT_FIELD.
4453          Note that fulltext indexes ignores prefixes.
4454       */
4455       if (key->type != KEYTYPE_FULLTEXT &&
4456           key_part_length != sql_field->key_length &&
4457           !(sql_field->sql_type == MYSQL_TYPE_GEOMETRY &&
4458             sql_field->geom_type == Field::GEOM_POINT &&
4459             key_part_length == MAX_LEN_GEOM_POINT_FIELD))
4460         {
4461           key_info->flags|= HA_KEY_HAS_PART_KEY_SEG;
4462         }
4463 
4464       key_length+= key_part_length;
4465       key_part_info++;
4466 
4467       /* Create the key name based on the first column (if not given) */
4468       if (column_nr == 0)
4469       {
4470 	if (key->type == KEYTYPE_PRIMARY)
4471 	{
4472 	  if (primary_key)
4473 	  {
4474 	    my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
4475                        MYF(0));
4476 	    DBUG_RETURN(TRUE);
4477 	  }
4478 	  key_name=primary_key_name;
4479 	  primary_key=1;
4480 	}
4481 	else if (!(key_name= key->name.str))
4482 	  key_name=make_unique_key_name(sql_field->field_name,
4483 					*key_info_buffer, key_info);
4484 	if (check_if_keyname_exists(key_name, *key_info_buffer, key_info))
4485 	{
4486 	  my_error(ER_DUP_KEYNAME, MYF(0), key_name);
4487 	  DBUG_RETURN(TRUE);
4488 	}
4489 	key_info->name=(char*) key_name;
4490       }
4491     }
4492     key_info->actual_flags= key_info->flags;
4493     if (!key_info->name || check_column_name(key_info->name))
4494     {
4495       my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key_info->name);
4496       DBUG_RETURN(TRUE);
4497     }
4498     if (!(key_info->flags & HA_NULL_PART_KEY))
4499       unique_key=1;
4500     key_info->key_length=(uint16) key_length;
4501     if (key_length > max_key_length && key->type != KEYTYPE_FULLTEXT)
4502     {
4503       my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
4504       if (thd->is_error())  // May be silenced - see Bug#20629014
4505         DBUG_RETURN(true);
4506     }
4507     if (validate_comment_length(thd, key->key_create_info.comment.str,
4508                                 &key->key_create_info.comment.length,
4509                                 INDEX_COMMENT_MAXLEN,
4510                                 ER_TOO_LONG_INDEX_COMMENT,
4511                                 key_info->name))
4512        DBUG_RETURN(true);
4513     key_info->comment.length= key->key_create_info.comment.length;
4514     if (key_info->comment.length > 0)
4515     {
4516       key_info->flags|= HA_USES_COMMENT;
4517       key_info->comment.str= key->key_create_info.comment.str;
4518     }
4519 
4520     // Check if a duplicate index is defined.
4521   if (check_duplicate_key(thd, error_schema_name, error_table_name,
4522                           key, key_info, alter_info))
4523       DBUG_RETURN(true);
4524 
4525     key_info++;
4526   }
4527 
4528   if (!unique_key && !primary_key &&
4529       (file->ha_table_flags() & HA_REQUIRE_PRIMARY_KEY))
4530   {
4531     my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
4532     DBUG_RETURN(TRUE);
4533   }
4534   if (auto_increment > 0)
4535   {
4536     my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
4537     DBUG_RETURN(TRUE);
4538   }
4539   /* Sort keys in optimized order */
4540   my_qsort((uchar*) *key_info_buffer, *key_count, sizeof(KEY),
4541 	   (qsort_cmp) sort_keys);
4542   create_info->null_bits= null_fields;
4543 
4544   /* Check fields. */
4545   it.rewind();
4546 
4547   /*
4548     Check if  STRICT SQL mode is active and server is not started with
4549     --explicit-defaults-for-timestamp. Below check was added to prevent implicit
4550     default 0 value of timestamp. When explicit-defaults-for-timestamp server
4551     option is removed, whole set of check can be removed.
4552   */
4553   if (thd->variables.sql_mode & MODE_NO_ZERO_DATE &&
4554       !thd->variables.explicit_defaults_for_timestamp)
4555   {
4556     while ((sql_field=it++))
4557     {
4558       Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
4559 
4560       if (!sql_field->def &&
4561           !sql_field->gcol_info &&
4562           is_timestamp_type(sql_field->sql_type) &&
4563           (sql_field->flags & NOT_NULL_FLAG) &&
4564           (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
4565       {
4566         /*
4567           An error should be reported if:
4568             - there is no explicit DEFAULT clause (default column value);
4569             - this is a TIMESTAMP column;
4570             - the column is not NULL;
4571             - this is not the DEFAULT CURRENT_TIMESTAMP column.
4572           And from checks before while loop,
4573             - STRICT SQL mode is active;
4574             - server is not started with --explicit-defaults-for-timestamp
4575 
4576           In other words, an error should be reported if
4577             - STRICT SQL mode is active;
4578             - the column definition is equivalent to
4579               'column_name TIMESTAMP DEFAULT 0'.
4580         */
4581 
4582         my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
4583         DBUG_RETURN(TRUE);
4584       }
4585     }
4586   }
4587 
4588   {
4589     LEX_STRING*	compress = &create_info->compress;
4590 
4591     if (compress->length != 0 &&
4592 	compress->length > TABLE_COMMENT_MAXLEN &&
4593 	system_charset_info->cset->charpos(system_charset_info,
4594 					   compress->str,
4595 					   compress->str + compress->length,
4596 					   TABLE_COMMENT_MAXLEN)
4597 	< compress->length)
4598     {
4599       my_error(ER_WRONG_STRING_LENGTH, MYF(0),
4600 	       compress->str, "COMPRESSION", TABLE_COMMENT_MAXLEN);
4601       DBUG_RETURN(TRUE);
4602     }
4603   }
4604 
4605   {
4606     LEX_STRING*	encrypt_type = &create_info->encrypt_type;
4607 
4608     if (encrypt_type->length != 0 &&
4609 	encrypt_type->length > TABLE_COMMENT_MAXLEN &&
4610 	system_charset_info->cset->charpos(system_charset_info,
4611 					   encrypt_type->str,
4612 					   encrypt_type->str
4613 					   + encrypt_type->length,
4614 					   TABLE_COMMENT_MAXLEN)
4615 	< encrypt_type->length)
4616     {
4617       my_error(ER_WRONG_STRING_LENGTH, MYF(0),
4618 	       encrypt_type->str, "ENCRYPTION", TABLE_COMMENT_MAXLEN);
4619       DBUG_RETURN(TRUE);
4620     }
4621   }
4622 
4623   DBUG_RETURN(FALSE);
4624 }
4625 
4626 /**
4627   @brief check comment length of table, column, index and partition
4628 
4629   @details If comment length is more than the standard length
4630     truncate it and store the comment length upto the standard
4631     comment length size
4632 
4633   @param          thd             Thread handle
4634   @param          comment_str     Comment string
4635   @param[in,out]  comment_len     Comment length
4636   @param          max_len         Maximum allowed comment length
4637   @param          err_code        Error message
4638   @param          comment_name    Type of comment
4639 
4640   @return Operation status
4641     @retval       true            Error found
4642     @retval       false           On success
4643 */
4644 
validate_comment_length(THD * thd,const char * comment_str,size_t * comment_len,uint max_len,uint err_code,const char * comment_name)4645 bool validate_comment_length(THD *thd, const char *comment_str,
4646                              size_t *comment_len, uint max_len,
4647                              uint err_code, const char *comment_name)
4648 {
4649   size_t length= 0;
4650   DBUG_ENTER("validate_comment_length");
4651   size_t tmp_len= system_charset_info->cset->charpos(system_charset_info,
4652                                                      comment_str,
4653                                                      comment_str +
4654                                                      *comment_len,
4655                                                      max_len);
4656   if (tmp_len < *comment_len)
4657   {
4658     if (thd->is_strict_mode())
4659     {
4660       my_error(err_code, MYF(0),
4661                comment_name, static_cast<ulong>(max_len));
4662       DBUG_RETURN(true);
4663     }
4664     char warn_buff[MYSQL_ERRMSG_SIZE];
4665     length= my_snprintf(warn_buff, sizeof(warn_buff), ER(err_code),
4666                         comment_name, static_cast<ulong>(max_len));
4667     /* do not push duplicate warnings */
4668     if (!thd->get_stmt_da()->has_sql_condition(warn_buff, length))
4669       push_warning(thd, Sql_condition::SL_WARNING,
4670                    err_code, warn_buff);
4671     *comment_len= tmp_len;
4672   }
4673   DBUG_RETURN(false);
4674 }
4675 
4676 
4677 /*
4678   Set table default charset, if not set
4679 
4680   SYNOPSIS
4681     set_table_default_charset()
4682     create_info        Table create information
4683 
4684   DESCRIPTION
4685     If the table character set was not given explicitely,
4686     let's fetch the database default character set and
4687     apply it to the table.
4688 */
4689 
set_table_default_charset(THD * thd,HA_CREATE_INFO * create_info,char * db)4690 static void set_table_default_charset(THD *thd,
4691 				      HA_CREATE_INFO *create_info, char *db)
4692 {
4693   /*
4694     If the table character set was not given explicitly,
4695     let's fetch the database default character set and
4696     apply it to the table.
4697   */
4698   if (!create_info->default_table_charset)
4699   {
4700     HA_CREATE_INFO db_info;
4701 
4702     load_db_opt_by_name(thd, db, &db_info);
4703 
4704     create_info->default_table_charset= db_info.default_table_charset;
4705   }
4706 }
4707 
4708 
4709 /*
4710   Extend long VARCHAR fields to blob & prepare field if it's a blob
4711 
4712   SYNOPSIS
4713     prepare_blob_field()
4714     sql_field		Field to check
4715 
4716   RETURN
4717     0	ok
4718     1	Error (sql_field can't be converted to blob)
4719         In this case the error is given
4720 */
4721 
prepare_blob_field(THD * thd,Create_field * sql_field)4722 static bool prepare_blob_field(THD *thd, Create_field *sql_field)
4723 {
4724   DBUG_ENTER("prepare_blob_field");
4725 
4726   if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
4727       !(sql_field->flags & BLOB_FLAG))
4728   {
4729     /* Convert long VARCHAR columns to TEXT or BLOB */
4730     char warn_buff[MYSQL_ERRMSG_SIZE];
4731 
4732     if (sql_field->def || thd->is_strict_mode())
4733     {
4734       my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
4735                static_cast<ulong>(MAX_FIELD_VARCHARLENGTH /
4736                                   sql_field->charset->mbmaxlen));
4737       DBUG_RETURN(1);
4738     }
4739     sql_field->sql_type= MYSQL_TYPE_BLOB;
4740     sql_field->flags|= BLOB_FLAG;
4741     my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_AUTO_CONVERT), sql_field->field_name,
4742             (sql_field->charset == &my_charset_bin) ? "VARBINARY" : "VARCHAR",
4743             (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
4744     push_warning(thd, Sql_condition::SL_NOTE, ER_AUTO_CONVERT,
4745                  warn_buff);
4746   }
4747 
4748   if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
4749   {
4750     if (sql_field->sql_type == FIELD_TYPE_BLOB ||
4751         sql_field->sql_type == FIELD_TYPE_TINY_BLOB ||
4752         sql_field->sql_type == FIELD_TYPE_MEDIUM_BLOB)
4753     {
4754       /* The user has given a length to the blob column */
4755       sql_field->sql_type= get_blob_type_from_length(sql_field->length);
4756       sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
4757     }
4758     sql_field->length= 0;
4759   }
4760   DBUG_RETURN(0);
4761 }
4762 
4763 
4764 /*
4765   Preparation of Create_field for SP function return values.
4766   Based on code used in the inner loop of mysql_prepare_create_table()
4767   above.
4768 
4769   SYNOPSIS
4770     sp_prepare_create_field()
4771     thd			Thread object
4772     sql_field		Field to prepare
4773 
4774   DESCRIPTION
4775     Prepares the field structures for field creation.
4776 
4777 */
4778 
sp_prepare_create_field(THD * thd,Create_field * sql_field)4779 static void sp_prepare_create_field(THD *thd, Create_field *sql_field)
4780 {
4781   if (sql_field->sql_type == MYSQL_TYPE_SET ||
4782       sql_field->sql_type == MYSQL_TYPE_ENUM)
4783   {
4784     size_t field_length, dummy;
4785     if (sql_field->sql_type == MYSQL_TYPE_SET)
4786     {
4787       calculate_interval_lengths(sql_field->charset,
4788                                  sql_field->interval, &dummy,
4789                                  &field_length);
4790       sql_field->length= field_length +
4791                          (sql_field->interval->count - 1);
4792     }
4793     else /* MYSQL_TYPE_ENUM */
4794     {
4795       calculate_interval_lengths(sql_field->charset,
4796                                  sql_field->interval,
4797                                  &field_length, &dummy);
4798       sql_field->length= field_length;
4799     }
4800     set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
4801   }
4802 
4803   if (sql_field->sql_type == MYSQL_TYPE_BIT)
4804   {
4805     sql_field->pack_flag= FIELDFLAG_NUMBER |
4806                           FIELDFLAG_TREAT_BIT_AS_CHAR;
4807   }
4808   sql_field->create_length_to_internal_length();
4809   assert(sql_field->def == 0);
4810   /* Can't go wrong as sql_field->def is not defined */
4811   (void) prepare_blob_field(thd, sql_field);
4812 }
4813 
4814 
4815 /**
4816   Create a table
4817 
4818   @param thd                 Thread object
4819   @param db                  Database
4820   @param table_name          Table name
4821   @param error_table_name    The real table name in case table_name is a temporary
4822                              table (ALTER). Only used for error messages.
4823   @param path                Path to table (i.e. to its .FRM file without
4824                              the extension).
4825   @param create_info         Create information (like MAX_ROWS)
4826   @param alter_info          Description of fields and keys for new table
4827   @param internal_tmp_table  Set to true if this is an internal temporary table
4828                              (From ALTER TABLE)
4829   @param select_field_count  Number of fields coming from SELECT part of
4830                              CREATE TABLE ... SELECT statement. Must be zero
4831                              for standard create of table.
4832   @param no_ha_table         Indicates that only .FRM file (and PAR file if table
4833                              is partitioned) needs to be created and not a table
4834                              in the storage engine.
4835   @param[out] is_trans       Identifies the type of engine where the table
4836                              was created: either trans or non-trans.
4837   @param[out] key_info       Array of KEY objects describing keys in table
4838                              which was created.
4839   @param[out] key_count      Number of keys in table which was created.
4840 
4841   If one creates a temporary table, this is automatically opened
4842 
4843   Note that this function assumes that caller already have taken
4844   exclusive metadata lock on table being created or used some other
4845   way to ensure that concurrent operations won't intervene.
4846   mysql_create_table() is a wrapper that can be used for this.
4847 
4848   @retval false OK
4849   @retval true  error
4850 */
4851 
4852 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)4853 bool create_table_impl(THD *thd,
4854                        const char *db, const char *table_name,
4855                        const char *error_table_name,
4856                        const char *path,
4857                        HA_CREATE_INFO *create_info,
4858                        Alter_info *alter_info,
4859                        bool internal_tmp_table,
4860                        uint select_field_count,
4861                        bool no_ha_table,
4862                        bool *is_trans,
4863                        KEY **key_info,
4864                        uint *key_count)
4865 {
4866   const char	*alias;
4867   uint		db_options;
4868   handler	*file;
4869   bool		error= TRUE;
4870   bool		is_whitelisted_table;
4871   bool		prepare_error;
4872   Key_length_error_handler error_handler;
4873 
4874   DBUG_ENTER("create_table_impl");
4875   DBUG_PRINT("enter", ("db: '%s'  table: '%s'  tmp: %d",
4876                        db, table_name, internal_tmp_table));
4877 
4878 
4879   /* Check for duplicate fields and check type of table to create */
4880   if (!alter_info->create_list.elements)
4881   {
4882     my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
4883                MYF(0));
4884     DBUG_RETURN(TRUE);
4885   }
4886 
4887   if (check_engine(thd, db, table_name, create_info))
4888     DBUG_RETURN(TRUE);
4889 
4890   // Check if new table creation is disallowed by the storage engine.
4891   if (!internal_tmp_table &&
4892       ha_is_storage_engine_disabled(create_info->db_type))
4893   {
4894     /*
4895       If table creation is disabled for the engine then substitute the engine
4896       for the table with the default engine only if sql mode
4897       NO_ENGINE_SUBSTITUTION is disabled.
4898     */
4899     handlerton *new_engine= NULL;
4900     if (is_engine_substitution_allowed(thd))
4901       new_engine= ha_default_handlerton(thd);
4902 
4903     /*
4904       Proceed with the engine substitution only if,
4905       1. The disabled engine and the default engine are not the same.
4906       2. The default engine is not in the disabled engines list.
4907       else report an error.
4908     */
4909     if (new_engine && create_info->db_type &&
4910         new_engine != create_info->db_type &&
4911         !ha_is_storage_engine_disabled(new_engine))
4912     {
4913       push_warning_printf(thd, Sql_condition::SL_WARNING,
4914                           ER_DISABLED_STORAGE_ENGINE,
4915                           ER(ER_DISABLED_STORAGE_ENGINE),
4916                           ha_resolve_storage_engine_name(create_info->db_type));
4917 
4918       create_info->db_type= new_engine;
4919 
4920       push_warning_printf(thd, Sql_condition::SL_WARNING,
4921                           ER_WARN_USING_OTHER_HANDLER,
4922                           ER(ER_WARN_USING_OTHER_HANDLER),
4923                           ha_resolve_storage_engine_name(create_info->db_type),
4924                           table_name);
4925     }
4926     else
4927     {
4928       my_error(ER_DISABLED_STORAGE_ENGINE, MYF(0),
4929                ha_resolve_storage_engine_name(create_info->db_type));
4930       DBUG_RETURN(true);
4931     }
4932   }
4933 
4934   set_table_default_charset(thd, create_info, (char*) db);
4935 
4936   db_options= create_info->table_options;
4937   if (create_info->row_type == ROW_TYPE_DYNAMIC)
4938     db_options|=HA_OPTION_PACK_RECORD;
4939   alias= table_case_name(create_info, table_name);
4940   if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
4941                               create_info->db_type)))
4942   {
4943     mem_alloc_error(sizeof(handler));
4944     DBUG_RETURN(TRUE);
4945   }
4946   partition_info *part_info= thd->work_part_info;
4947 
4948   if (!part_info && create_info->db_type->partition_flags &&
4949       (create_info->db_type->partition_flags() & HA_USE_AUTO_PARTITION))
4950   {
4951     Partition_handler *part_handler= file->get_partition_handler();
4952     assert(part_handler != NULL);
4953 
4954     /*
4955       Table is not defined as a partitioned table but the engine handles
4956       all tables as partitioned. The handler will set up the partition info
4957       object with the default settings.
4958     */
4959     thd->work_part_info= part_info= new partition_info();
4960     if (!part_info)
4961     {
4962       mem_alloc_error(sizeof(partition_info));
4963       DBUG_RETURN(TRUE);
4964     }
4965     part_handler->set_auto_partitions(part_info);
4966     part_info->default_engine_type= create_info->db_type;
4967     part_info->is_auto_partitioned= TRUE;
4968   }
4969   if (part_info)
4970   {
4971     /*
4972       The table has been specified as a partitioned table.
4973       If this is part of an ALTER TABLE the handler will be the partition
4974       handler but we need to specify the default handler to use for
4975       partitions also in the call to check_partition_info. We transport
4976       this information in the default_db_type variable, it is either
4977       DB_TYPE_DEFAULT or the engine set in the ALTER TABLE command.
4978     */
4979     Key *key;
4980     handlerton *part_engine_type= create_info->db_type;
4981     char *part_syntax_buf;
4982     uint syntax_len;
4983     handlerton *engine_type;
4984     List_iterator<partition_element> part_it(part_info->partitions);
4985     partition_element *part_elem;
4986 
4987     while ((part_elem= part_it++))
4988     {
4989       if (part_elem->part_comment)
4990       {
4991         size_t comment_len= strlen(part_elem->part_comment);
4992         if (validate_comment_length(thd, part_elem->part_comment,
4993                                      &comment_len,
4994                                      TABLE_PARTITION_COMMENT_MAXLEN,
4995                                      ER_TOO_LONG_TABLE_PARTITION_COMMENT,
4996                                      part_elem->partition_name))
4997           DBUG_RETURN(true);
4998         part_elem->part_comment[comment_len]= '\0';
4999       }
5000       if (part_elem->subpartitions.elements)
5001       {
5002         List_iterator<partition_element> sub_it(part_elem->subpartitions);
5003         partition_element *subpart_elem;
5004         while ((subpart_elem= sub_it++))
5005         {
5006           if (subpart_elem->part_comment)
5007           {
5008             size_t comment_len= strlen(subpart_elem->part_comment);
5009             if (validate_comment_length(thd, subpart_elem->part_comment,
5010                                          &comment_len,
5011                                          TABLE_PARTITION_COMMENT_MAXLEN,
5012                                          ER_TOO_LONG_TABLE_PARTITION_COMMENT,
5013                                          subpart_elem->partition_name))
5014               DBUG_RETURN(true);
5015             subpart_elem->part_comment[comment_len]= '\0';
5016           }
5017         }
5018       }
5019     }
5020     if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
5021     {
5022       my_error(ER_PARTITION_NO_TEMPORARY, MYF(0));
5023       goto err;
5024     }
5025     if (is_ha_partition_handlerton(part_engine_type) &&
5026         part_info->default_engine_type)
5027     {
5028       /*
5029         This only happens at ALTER TABLE.
5030         default_engine_type was assigned from the engine set in the ALTER
5031         TABLE command.
5032       */
5033       ;
5034     }
5035     else
5036     {
5037       if (create_info->used_fields & HA_CREATE_USED_ENGINE)
5038       {
5039         part_info->default_engine_type= create_info->db_type;
5040       }
5041       else
5042       {
5043         if (part_info->default_engine_type == NULL)
5044         {
5045           part_info->default_engine_type= ha_checktype(thd,
5046                                           DB_TYPE_DEFAULT, 0, 0);
5047         }
5048       }
5049     }
5050     DBUG_PRINT("info", ("db_type = %s create_info->db_type = %s",
5051              ha_resolve_storage_engine_name(part_info->default_engine_type),
5052              ha_resolve_storage_engine_name(create_info->db_type)));
5053     if (part_info->check_partition_info(thd, &engine_type, file,
5054                                         create_info, FALSE))
5055       goto err;
5056     part_info->default_engine_type= engine_type;
5057 
5058     {
5059       /*
5060         We reverse the partitioning parser and generate a standard format
5061         for syntax stored in frm file.
5062       */
5063       sql_mode_t sql_mode_backup= thd->variables.sql_mode;
5064       thd->variables.sql_mode&= ~(MODE_ANSI_QUOTES);
5065       part_syntax_buf= generate_partition_syntax(part_info,
5066                                                  &syntax_len,
5067                                                  TRUE, TRUE,
5068                                                  create_info,
5069                                                  alter_info,
5070                                                  NULL);
5071       thd->variables.sql_mode= sql_mode_backup;
5072       if (part_syntax_buf == NULL)
5073       {
5074         goto err;
5075       }
5076     }
5077     part_info->part_info_string= part_syntax_buf;
5078     part_info->part_info_len= syntax_len;
5079     if (!engine_type->partition_flags ||
5080         is_ha_partition_handlerton(create_info->db_type))
5081     {
5082       /*
5083         The handler assigned to the table cannot handle partitioning.
5084         Assign the partition handler as the handler of the table.
5085       */
5086       DBUG_PRINT("info", ("db_type: %s",
5087                         ha_resolve_storage_engine_name(create_info->db_type)));
5088       LEX_CSTRING engine_name= {C_STRING_WITH_LEN("partition")};
5089       plugin_ref plugin= ha_resolve_by_name_raw(thd, engine_name);
5090       if (!plugin)
5091       {
5092         goto no_partitioning;
5093       }
5094       create_info->db_type= plugin_data<handlerton*>(plugin);
5095       assert(create_info->db_type->flags & HTON_NOT_USER_SELECTABLE);
5096       delete file;
5097       if (!(file= get_new_handler(NULL, thd->mem_root, create_info->db_type)))
5098       {
5099         mem_alloc_error(sizeof(handler));
5100         DBUG_RETURN(true);
5101       }
5102       if (file->ht != create_info->db_type)
5103       {
5104 	assert(0);
5105         goto no_partitioning;
5106       }
5107       Partition_handler *part_handler= file->get_partition_handler();
5108       if (!part_handler)
5109       {
5110         assert(0);
5111         goto no_partitioning;
5112       }
5113       part_handler->set_part_info(part_info, false);
5114 
5115       /*
5116         Re-run the initialize_partition after setting the part_info,
5117         to create the partition's handlers.
5118       */
5119       if (part_handler->initialize_partition(thd->mem_root))
5120         goto no_partitioning;
5121       /* Re-read the table flags */
5122       file->init();
5123 
5124       /*
5125         If we have default number of partitions or subpartitions we
5126         might require to set-up the part_info object such that it
5127         creates a proper .par file. The current part_info object is
5128         only used to create the frm-file and .par-file.
5129       */
5130       if (part_info->use_default_num_partitions &&
5131           part_info->num_parts &&
5132           (int)part_info->num_parts !=
5133           part_handler->get_default_num_partitions(create_info))
5134       {
5135         uint i;
5136         List_iterator<partition_element> part_it(part_info->partitions);
5137         part_it++;
5138         assert(thd->lex->sql_command != SQLCOM_CREATE_TABLE);
5139         for (i= 1; i < part_info->partitions.elements; i++)
5140           (part_it++)->part_state= PART_TO_BE_DROPPED;
5141       }
5142       else if (part_info->is_sub_partitioned() &&
5143                part_info->use_default_num_subpartitions &&
5144                part_info->num_subparts &&
5145                (int)part_info->num_subparts !=
5146                  part_handler->get_default_num_partitions(create_info))
5147       {
5148         assert(thd->lex->sql_command != SQLCOM_CREATE_TABLE);
5149         part_info->num_subparts=
5150           part_handler->get_default_num_partitions(create_info);
5151       }
5152     }
5153     else if (create_info->db_type != engine_type)
5154     {
5155       /*
5156         We come here when we don't use a partitioned handler.
5157         Since we use a partitioned table it must be "native partitioned".
5158         We have switched engine from defaults, most likely only specified
5159         engines in partition clauses.
5160       */
5161       delete file;
5162       if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
5163                                   engine_type)))
5164       {
5165         mem_alloc_error(sizeof(handler));
5166         DBUG_RETURN(TRUE);
5167       }
5168       create_info->db_type= engine_type;
5169     }
5170     /*
5171       Unless table's storage engine supports partitioning natively
5172       don't allow foreign keys on partitioned tables (they won't
5173       work work even with InnoDB beneath of partitioning engine).
5174       If storage engine handles partitioning natively (like NDB)
5175       foreign keys support is possible, so we let the engine decide.
5176     */
5177     if (is_ha_partition_handlerton(create_info->db_type))
5178     {
5179       List_iterator_fast<Key> key_iterator(alter_info->key_list);
5180       while ((key= key_iterator++))
5181       {
5182         if (key->type == KEYTYPE_FOREIGN)
5183         {
5184           my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
5185           goto err;
5186         }
5187       }
5188     }
5189   }
5190 
5191   /*
5192     System tables residing in mysql database and created
5193     by innodb engine could be created with any supported
5194     innodb page size ( 4k,8k,16K).  We have a index size
5195     limit depending upon the page size, but for system
5196     tables which are whitelisted we can skip this check,
5197     since the innodb engine ensures that the index size
5198     will be supported.
5199   */
5200   is_whitelisted_table = (file->ht->db_type == DB_TYPE_INNODB) ?
5201     ha_is_supported_system_table(file->ht, db, error_table_name) : false;
5202   if (is_whitelisted_table) thd->push_internal_handler(&error_handler);
5203 
5204   prepare_error= mysql_prepare_create_table(thd, db, error_table_name,
5205 					    create_info, alter_info,
5206 					    internal_tmp_table,
5207 					    &db_options, file,
5208 					    key_info, key_count,
5209 					    select_field_count);
5210 
5211   if (is_whitelisted_table) thd->pop_internal_handler();
5212   if (prepare_error) goto err;
5213 
5214   if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
5215     create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
5216 
5217   /* Check if table already exists */
5218   if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
5219       find_temporary_table(thd, db, table_name))
5220   {
5221     if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
5222     {
5223       push_warning_printf(thd, Sql_condition::SL_NOTE,
5224                           ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
5225                           alias);
5226       error= 0;
5227       goto err;
5228     }
5229     my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
5230     goto err;
5231   }
5232 
5233   if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
5234   {
5235     char frm_name[FN_REFLEN+1];
5236     strxnmov(frm_name, sizeof(frm_name) - 1, path, reg_ext, NullS);
5237 
5238     if (!access(frm_name, F_OK))
5239     {
5240       if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
5241         goto warn;
5242       my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
5243       goto err;
5244     }
5245     /*
5246       We don't assert here, but check the result, because the table could be
5247       in the table definition cache and in the same time the .frm could be
5248       missing from the disk, in case of manual intervention which deletes
5249       the .frm file. The user has to use FLUSH TABLES; to clear the cache.
5250       Then she could create the table. This case is pretty obscure and
5251       therefore we don't introduce a new error message only for it.
5252     */
5253     mysql_mutex_lock(&LOCK_open);
5254     if (get_cached_table_share(thd, db, table_name))
5255     {
5256       mysql_mutex_unlock(&LOCK_open);
5257       my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
5258       goto err;
5259     }
5260     mysql_mutex_unlock(&LOCK_open);
5261   }
5262 
5263   /*
5264     Check that table with given name does not already
5265     exist in any storage engine. In such a case it should
5266     be discovered and the error ER_TABLE_EXISTS_ERROR be returned
5267     unless user specified CREATE TABLE IF EXISTS
5268     An exclusive metadata lock ensures that no
5269     one else is attempting to discover the table. Since
5270     it's not on disk as a frm file, no one could be using it!
5271   */
5272   if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
5273   {
5274     bool create_if_not_exists =
5275       create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
5276     int retcode = ha_table_exists_in_engine(thd, db, table_name);
5277     DBUG_PRINT("info", ("exists_in_engine: %u",retcode));
5278     switch (retcode)
5279     {
5280       case HA_ERR_NO_SUCH_TABLE:
5281         /* Normal case, no table exists. we can go and create it */
5282         break;
5283       case HA_ERR_TABLE_EXIST:
5284         DBUG_PRINT("info", ("Table existed in handler"));
5285 
5286         if (create_if_not_exists)
5287           goto warn;
5288         my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
5289         goto err;
5290         break;
5291       default:
5292         DBUG_PRINT("info", ("error: %u from storage engine", retcode));
5293         my_error(retcode, MYF(0),table_name);
5294         goto err;
5295     }
5296   }
5297 
5298   THD_STAGE_INFO(thd, stage_creating_table);
5299 
5300   {
5301     size_t dirlen;
5302     char   dirpath[FN_REFLEN];
5303 
5304     /*
5305       data_file_name and index_file_name include the table name without
5306       extension. Mostly this does not refer to an existing file. When
5307       comparing data_file_name or index_file_name against the data
5308       directory, we try to resolve all symbolic links. On some systems,
5309       we use realpath(3) for the resolution. This returns ENOENT if the
5310       resolved path does not refer to an existing file. my_realpath()
5311       does then copy the requested path verbatim, without symlink
5312       resolution. Thereafter the comparison can fail even if the
5313       requested path is within the data directory. E.g. if symlinks to
5314       another file system are used. To make realpath(3) return the
5315       resolved path, we strip the table name and compare the directory
5316       path only. If the directory doesn't exist either, table creation
5317       will fail anyway.
5318     */
5319     if (create_info->data_file_name)
5320     {
5321       dirname_part(dirpath, create_info->data_file_name, &dirlen);
5322       if (test_if_data_home_dir(dirpath))
5323       {
5324         my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
5325         goto err;
5326       }
5327     }
5328     if (create_info->index_file_name)
5329     {
5330       dirname_part(dirpath, create_info->index_file_name, &dirlen);
5331       if (test_if_data_home_dir(dirpath))
5332       {
5333         my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
5334         goto err;
5335       }
5336     }
5337   }
5338 
5339   if (check_partition_dirs(thd->lex->part_info))
5340   {
5341     goto err;
5342   }
5343 
5344   if (thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE)
5345   {
5346     if (create_info->data_file_name)
5347       push_warning_printf(thd, Sql_condition::SL_WARNING,
5348                           WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
5349                           "DATA DIRECTORY");
5350     if (create_info->index_file_name)
5351       push_warning_printf(thd, Sql_condition::SL_WARNING,
5352                           WARN_OPTION_IGNORED, ER(WARN_OPTION_IGNORED),
5353                           "INDEX DIRECTORY");
5354     create_info->data_file_name= create_info->index_file_name= 0;
5355   }
5356   create_info->table_options=db_options;
5357 
5358   /*
5359     Create .FRM (and .PAR file for partitioned table).
5360     If "no_ha_table" is false also create table in storage engine.
5361   */
5362   if (rea_create_table(thd, path, db, table_name,
5363                        create_info, alter_info->create_list,
5364                        *key_count, *key_info, file, no_ha_table))
5365     goto err;
5366 
5367   if (!no_ha_table && create_info->options & HA_LEX_CREATE_TMP_TABLE)
5368   {
5369     /*
5370       Open a table (skipping table cache) and add it into
5371       THD::temporary_tables list.
5372     */
5373 
5374     TABLE *table= open_table_uncached(thd, path, db, table_name, true, true);
5375 
5376     if (!table)
5377     {
5378       (void) rm_temporary_table(create_info->db_type, path);
5379       goto err;
5380     }
5381 
5382     if (is_trans != NULL)
5383       *is_trans= table->file->has_transactions();
5384 
5385     thd->thread_specific_used= TRUE;
5386   }
5387   else if (part_info && no_ha_table)
5388   {
5389     /*
5390       For partitioned tables we can't find some problems with table
5391       until table is opened. Therefore in order to disallow creation
5392       of corrupted tables we have to try to open table as the part
5393       of its creation process.
5394       In cases when both .FRM and SE part of table are created table
5395       is implicitly open in ha_create_table() call.
5396       In cases when we create .FRM without SE part we have to open
5397       table explicitly.
5398     */
5399     TABLE table;
5400     TABLE_SHARE share;
5401 
5402     init_tmp_table_share(thd, &share, db, 0, table_name, path);
5403 
5404     bool result= (open_table_def(thd, &share, 0) ||
5405                   open_table_from_share(thd, &share, "", 0, (uint) READ_ALL,
5406                                         0, &table, true));
5407     /*
5408       Assert that the change list is empty as no partition function currently
5409       needs to modify item tree. May need call THD::rollback_item_tree_changes
5410       later before calling closefrm if the change list is not empty.
5411     */
5412     assert(thd->change_list.is_empty());
5413     if (!result)
5414       (void) closefrm(&table, 0);
5415 
5416     free_table_share(&share);
5417 
5418     if (result)
5419     {
5420       char frm_name[FN_REFLEN + 1];
5421       strxnmov(frm_name, sizeof(frm_name) - 1, path, reg_ext, NullS);
5422       (void) mysql_file_delete(key_file_frm, frm_name, MYF(0));
5423       (void) file->ha_create_handler_files(path, NULL, CHF_DELETE_FLAG,
5424                                            create_info);
5425       goto err;
5426     }
5427   }
5428 
5429   error= FALSE;
5430 err:
5431   THD_STAGE_INFO(thd, stage_after_create);
5432   delete file;
5433   if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
5434       thd->in_multi_stmt_transaction_mode() && !error)
5435   {
5436     /*
5437       When autocommit is disabled, creating temporary table sets this
5438       flag to start transaction in any case (regardless of binlog=on/off,
5439       binlog format and transactional/non-transactional engine) to make
5440       behavior consistent.
5441     */
5442     thd->server_status|= SERVER_STATUS_IN_TRANS;
5443   }
5444   DBUG_RETURN(error);
5445 
5446 warn:
5447   error= FALSE;
5448   push_warning_printf(thd, Sql_condition::SL_NOTE,
5449                       ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
5450                       alias);
5451   goto err;
5452 no_partitioning:
5453   my_error(ER_FEATURE_NOT_AVAILABLE, MYF(0), "partitioning",
5454            "--skip-partition", "-DWITH_PARTITION_STORAGE_ENGINE=1");
5455   goto err;
5456 }
5457 
5458 
5459 /**
5460   Simple wrapper around create_table_impl() to be used
5461   in various version of CREATE TABLE statement.
5462 */
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)5463 bool mysql_create_table_no_lock(THD *thd,
5464                                 const char *db, const char *table_name,
5465                                 HA_CREATE_INFO *create_info,
5466                                 Alter_info *alter_info,
5467                                 uint select_field_count,
5468                                 bool *is_trans)
5469 {
5470   KEY *not_used_1;
5471   uint not_used_2;
5472   char path[FN_REFLEN + 1];
5473 
5474   if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
5475     build_tmptable_filename(thd, path, sizeof(path));
5476   else
5477   {
5478     bool was_truncated;
5479     const char *alias= table_case_name(create_info, table_name);
5480     build_table_filename(path, sizeof(path) - 1 - reg_ext_length,
5481                          db, alias, "", 0, &was_truncated);
5482     // Check truncation, will lead to overflow when adding extension
5483     if (was_truncated)
5484     {
5485       my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), sizeof(path) - 1, path);
5486       return true;
5487     }
5488   }
5489 
5490   return create_table_impl(thd, db, table_name, table_name, path, create_info,
5491                            alter_info, false, select_field_count, false,
5492                            is_trans, &not_used_1, &not_used_2);
5493 }
5494 
5495 
5496 /**
5497   Implementation of SQLCOM_CREATE_TABLE.
5498 
5499   Take the metadata locks (including a shared lock on the affected
5500   schema) and create the table. Is written to be called from
5501   mysql_execute_command(), to which it delegates the common parts
5502   with other commands (i.e. implicit commit before and after,
5503   close of thread tables.
5504 */
5505 
mysql_create_table(THD * thd,TABLE_LIST * create_table,HA_CREATE_INFO * create_info,Alter_info * alter_info)5506 bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
5507                         HA_CREATE_INFO *create_info,
5508                         Alter_info *alter_info)
5509 {
5510   bool result;
5511   bool is_trans= FALSE;
5512   uint not_used;
5513   DBUG_ENTER("mysql_create_table");
5514 
5515   /*
5516     Open or obtain "X" MDL lock on the table being created.
5517     To check the existence of table, lock of type "S" is obtained on the table
5518     and then it is upgraded to "X" if table does not exists.
5519   */
5520   if (open_tables(thd, &thd->lex->query_tables, &not_used, 0))
5521   {
5522     result= TRUE;
5523     goto end;
5524   }
5525 
5526   /* Got lock. */
5527   DEBUG_SYNC(thd, "locked_table_name");
5528 
5529   /*
5530     Promote first timestamp column, when explicit_defaults_for_timestamp
5531     is not set
5532   */
5533   if (!thd->variables.explicit_defaults_for_timestamp)
5534     promote_first_timestamp_column(&alter_info->create_list);
5535 
5536   result= mysql_create_table_no_lock(thd, create_table->db,
5537                                      create_table->table_name, create_info,
5538                                      alter_info, 0, &is_trans);
5539   /*
5540     Don't write statement if:
5541     - Table creation has failed
5542     - Row-based logging is used and we are creating a temporary table
5543     Otherwise, the statement shall be binlogged.
5544   */
5545   if (!result)
5546   {
5547     /*
5548       CREATE TEMPORARY TABLE doesn't terminate a transaction. Calling
5549       stmt.mark_created_temp_table() guarantees the transaction can be binlogged
5550       correctly.
5551     */
5552     if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
5553       thd->get_transaction()->mark_created_temp_table(Transaction_ctx::STMT);
5554 
5555     if (!thd->is_current_stmt_binlog_format_row() ||
5556         (thd->is_current_stmt_binlog_format_row() &&
5557          !(create_info->options & HA_LEX_CREATE_TMP_TABLE)))
5558     {
5559       thd->add_to_binlog_accessed_dbs(create_table->db);
5560       result= write_bin_log(thd, true,
5561                             thd->query().str, thd->query().length, is_trans);
5562     }
5563   }
5564 
5565 end:
5566   DBUG_RETURN(result);
5567 }
5568 
5569 
5570 /*
5571 ** Give the key name after the first field with an optional '_#' after
5572 **/
5573 
5574 static bool
check_if_keyname_exists(const char * name,KEY * start,KEY * end)5575 check_if_keyname_exists(const char *name, KEY *start, KEY *end)
5576 {
5577   for (KEY *key=start ; key != end ; key++)
5578     if (!my_strcasecmp(system_charset_info,name,key->name))
5579       return 1;
5580   return 0;
5581 }
5582 
5583 
5584 static char *
make_unique_key_name(const char * field_name,KEY * start,KEY * end)5585 make_unique_key_name(const char *field_name,KEY *start,KEY *end)
5586 {
5587   char buff[MAX_FIELD_NAME],*buff_end;
5588 
5589   if (!check_if_keyname_exists(field_name,start,end) &&
5590       my_strcasecmp(system_charset_info,field_name,primary_key_name))
5591     return (char*) field_name;			// Use fieldname
5592   buff_end=strmake(buff,field_name, sizeof(buff)-4);
5593 
5594   /*
5595     Only 3 chars + '\0' left, so need to limit to 2 digit
5596     This is ok as we can't have more than 100 keys anyway
5597   */
5598   for (uint i=2 ; i< 100; i++)
5599   {
5600     *buff_end= '_';
5601     int10_to_str(i, buff_end+1, 10);
5602     if (!check_if_keyname_exists(buff,start,end))
5603       return sql_strdup(buff);
5604   }
5605   return (char*) "not_specified";		// Should never happen
5606 }
5607 
5608 
5609 /****************************************************************************
5610 ** Alter a table definition
5611 ****************************************************************************/
5612 
5613 /**
5614   Rename a table.
5615 
5616   @param base      The handlerton handle.
5617   @param old_db    The old database name.
5618   @param old_name  The old table name.
5619   @param new_db    The new database name.
5620   @param new_name  The new table name.
5621   @param flags     flags
5622                    FN_FROM_IS_TMP old_name is temporary.
5623                    FN_TO_IS_TMP   new_name is temporary.
5624                    NO_FRM_RENAME  Don't rename the FRM file
5625                                   but only the table in the storage engine.
5626                    NO_HA_TABLE    Don't rename table in engine.
5627                    NO_FK_CHECKS   Don't check FK constraints during rename.
5628 
5629   @return false    OK
5630   @return true     Error
5631 */
5632 
5633 bool
mysql_rename_table(handlerton * base,const char * old_db,const char * old_name,const char * new_db,const char * new_name,uint flags)5634 mysql_rename_table(handlerton *base, const char *old_db,
5635                    const char *old_name, const char *new_db,
5636                    const char *new_name, uint flags)
5637 {
5638   THD *thd= current_thd;
5639   char from[FN_REFLEN + 1], to[FN_REFLEN + 1],
5640     lc_from[FN_REFLEN + 1], lc_to[FN_REFLEN + 1];
5641   char *from_base= from, *to_base= to;
5642   char tmp_name[NAME_LEN+1];
5643   handler *file;
5644   int error=0;
5645   ulonglong save_bits= thd->variables.option_bits;
5646   size_t length;
5647   bool was_truncated;
5648   DBUG_ENTER("mysql_rename_table");
5649   DBUG_PRINT("enter", ("old: '%s'.'%s'  new: '%s'.'%s'",
5650                        old_db, old_name, new_db, new_name));
5651 
5652   // Temporarily disable foreign key checks
5653   if (flags & NO_FK_CHECKS)
5654     thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS;
5655 
5656   file= (base == NULL ? 0 :
5657          get_new_handler((TABLE_SHARE*) 0, thd->mem_root, base));
5658 
5659   build_table_filename(from, sizeof(from) - 1, old_db, old_name, "",
5660                        flags & FN_FROM_IS_TMP);
5661   length= build_table_filename(to, sizeof(to) - 1, new_db, new_name, "",
5662                                flags & FN_TO_IS_TMP, &was_truncated);
5663   // Check if we hit FN_REFLEN bytes along with file extension.
5664   if (was_truncated || length+reg_ext_length > FN_REFLEN)
5665   {
5666     my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), sizeof(to)-1, to);
5667     DBUG_RETURN(TRUE);
5668   }
5669 
5670   /*
5671     If lower_case_table_names == 2 (case-preserving but case-insensitive
5672     file system) and the storage is not HA_FILE_BASED, we need to provide
5673     a lowercase file name, but we leave the .frm in mixed case.
5674    */
5675   if (lower_case_table_names == 2 && file &&
5676       !(file->ha_table_flags() & HA_FILE_BASED))
5677   {
5678     my_stpcpy(tmp_name, old_name);
5679     my_casedn_str(files_charset_info, tmp_name);
5680     build_table_filename(lc_from, sizeof(lc_from) - 1, old_db, tmp_name, "",
5681                          flags & FN_FROM_IS_TMP);
5682     from_base= lc_from;
5683 
5684     my_stpcpy(tmp_name, new_name);
5685     my_casedn_str(files_charset_info, tmp_name);
5686     build_table_filename(lc_to, sizeof(lc_to) - 1, new_db, tmp_name, "",
5687                          flags & FN_TO_IS_TMP);
5688     to_base= lc_to;
5689   }
5690 
5691   if (flags & NO_HA_TABLE)
5692   {
5693     if (rename_file_ext(from,to,reg_ext))
5694       error= my_errno();
5695     (void) file->ha_create_handler_files(to, from, CHF_RENAME_FLAG, NULL);
5696   }
5697   else if (!file || !(error=file->ha_rename_table(from_base, to_base)))
5698   {
5699     if (!(flags & NO_FRM_RENAME) && rename_file_ext(from,to,reg_ext))
5700     {
5701       error=my_errno();
5702       /* Restore old file name */
5703       if (file)
5704         file->ha_rename_table(to_base, from_base);
5705     }
5706   }
5707   delete file;
5708   if (error == HA_ERR_WRONG_COMMAND)
5709     my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER TABLE");
5710   else if (error)
5711   {
5712     char errbuf[MYSYS_STRERROR_SIZE];
5713     my_error(ER_ERROR_ON_RENAME, MYF(0), from, to,
5714              error, my_strerror(errbuf, sizeof(errbuf), error));
5715   }
5716 
5717 #ifdef HAVE_PSI_TABLE_INTERFACE
5718   /*
5719     Remove the old table share from the pfs table share array. The new table
5720     share will be created when the renamed table is first accessed.
5721    */
5722   if (likely(error == 0))
5723   {
5724     my_bool temp_table= (my_bool)is_prefix(old_name, tmp_file_prefix);
5725     PSI_TABLE_CALL(drop_table_share)
5726       (temp_table, old_db, static_cast<int>(strlen(old_db)),
5727        old_name, static_cast<int>(strlen(old_name)));
5728   }
5729 #endif
5730 
5731   // Restore options bits to the original value
5732   thd->variables.option_bits= save_bits;
5733 
5734   DBUG_RETURN(error != 0);
5735 }
5736 
5737 
5738 /*
5739   Create a table identical to the specified table
5740 
5741   SYNOPSIS
5742     mysql_create_like_table()
5743     thd		Thread object
5744     table       Table list element for target table
5745     src_table   Table list element for source table
5746     create_info Create info
5747 
5748   RETURN VALUES
5749     FALSE OK
5750     TRUE  error
5751 */
5752 
mysql_create_like_table(THD * thd,TABLE_LIST * table,TABLE_LIST * src_table,HA_CREATE_INFO * create_info)5753 bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
5754                              HA_CREATE_INFO *create_info)
5755 {
5756   HA_CREATE_INFO local_create_info;
5757   Alter_info local_alter_info;
5758   Alter_table_ctx local_alter_ctx; // Not used
5759   bool res= TRUE;
5760   bool is_trans= FALSE;
5761   uint not_used;
5762   Tablespace_hash_set tablespace_set(PSI_INSTRUMENT_ME);
5763 
5764   DBUG_ENTER("mysql_create_like_table");
5765 #ifdef WITH_WSREP
5766   if (WSREP(thd) && !thd->wsrep_applier)
5767   {
5768     TABLE *tmp_table;
5769     bool is_tmp_table= FALSE;
5770 
5771     for (tmp_table= thd->temporary_tables; tmp_table; tmp_table=tmp_table->next)
5772     {
5773       if (!strcmp(src_table->db, tmp_table->s->db.str)     &&
5774           !strcmp(src_table->table_name, tmp_table->s->table_name.str))
5775       {
5776         is_tmp_table= TRUE;
5777         break;
5778       }
5779     }
5780     if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
5781     {
5782       /* CREATE TEMPORARY TABLE LIKE must be skipped from replication */
5783       WSREP_DEBUG("CREATE TEMPORARY TABLE LIKE... skipped replication\n %s",
5784                   thd->query().str);
5785     }
5786     else if (!is_tmp_table)
5787     {
5788       /* this is straight CREATE TABLE LIKE... eith no tmp tables */
5789       WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL);
5790     }
5791     else
5792     {
5793       /* here we have CREATE TABLE LIKE <temporary table>
5794          the temporary table definition will be needed in slaves to
5795          enable the create to succeed
5796        */
5797       TABLE_LIST tbl;
5798       tbl.db= src_table->db;
5799       tbl.table_name= tbl.alias= src_table->table_name;
5800       tbl.table= tmp_table;
5801       char buf[2048];
5802       String query(buf, sizeof(buf), system_charset_info);
5803       query.length(0);  // Have to zero it since constructor doesn't
5804 
5805       (void)  store_create_info(thd, &tbl, &query, NULL, TRUE);
5806       WSREP_DEBUG("TMP TABLE: %s", query.ptr());
5807 
5808       thd->wsrep_TOI_pre_query=     query.ptr();
5809       thd->wsrep_TOI_pre_query_len= query.length();
5810 
5811       WSREP_TO_ISOLATION_BEGIN(table->db, table->table_name, NULL);
5812 
5813       thd->wsrep_TOI_pre_query=      NULL;
5814       thd->wsrep_TOI_pre_query_len= 0;
5815     }
5816   }
5817 #endif
5818 
5819   /*
5820     We the open source table to get its description in HA_CREATE_INFO
5821     and Alter_info objects. This also acquires a shared metadata lock
5822     on this table which ensures that no concurrent DDL operation will
5823     mess with it.
5824     Also in case when we create non-temporary table open_tables()
5825     call obtains an exclusive metadata lock on target table ensuring
5826     that we can safely perform table creation.
5827     Thus by holding both these locks we ensure that our statement is
5828     properly isolated from all concurrent operations which matter.
5829   */
5830   if (open_tables(thd, &thd->lex->query_tables, &not_used, 0))
5831     goto err;
5832   src_table->table->use_all_columns();
5833 
5834   DEBUG_SYNC(thd, "create_table_like_after_open");
5835 
5836   /*
5837     During open_tables(), the target tablespace name(s) for a table being
5838     created or altered should be locked. However, for 'CREATE TABLE ... LIKE',
5839     the source table is not being created, yet its tablespace name should be
5840     locked since it is used as the target tablespace name for the table being
5841     created. The  target tablespace name cannot be set before open_tables()
5842     (which is how we handle this for e.g. CREATE TABLE ... TABLESPACE ...'),
5843     since before open_tables(), the source table itself is not locked, which
5844     means that a DDL operation may sneak in and change the tablespace of the
5845     source table *after* we retrieved it from the .FRM file of the source
5846     table, and *before* the source table itself is locked. Thus, we lock the
5847     target tablespace here in a separate mdl lock acquisition phase after
5848     open_tables(). Since the table is already opened (and locked), we retrieve
5849     the tablespace name from the table share instead of reading it from the
5850     .FRM file.
5851   */
5852 
5853   // Add the tablespace name, if used.
5854   if (src_table->table->s->tablespace &&
5855       strlen(src_table->table->s->tablespace) > 0)
5856   {
5857     assert(thd->mdl_context.owns_equal_or_stronger_lock(MDL_key::TABLE,
5858                                                         src_table->db, src_table->table_name, MDL_SHARED));
5859 
5860     if (tablespace_set.insert(
5861           const_cast<char*>(src_table->table->s->tablespace)))
5862       DBUG_RETURN(true);
5863   }
5864 
5865   // Add tablespace names used under partition/subpartition definitions.
5866   if (fill_partition_tablespace_names(
5867         src_table->table->part_info, &tablespace_set))
5868     DBUG_RETURN(true);
5869 
5870   /*
5871     After we have identified the tablespace names, we iterate
5872     over the names and acquire MDL lock for each of them.
5873   */
5874   if (lock_tablespace_names(thd,
5875                             &tablespace_set,
5876                             thd->variables.lock_wait_timeout))
5877   {
5878     DBUG_RETURN(true);
5879   }
5880 
5881   /* Fill HA_CREATE_INFO and Alter_info with description of source table. */
5882   local_create_info.db_type= src_table->table->s->db_type();
5883   local_create_info.row_type= src_table->table->s->row_type;
5884   if (mysql_prepare_alter_table(thd, src_table->table, &local_create_info,
5885                                 &local_alter_info, &local_alter_ctx))
5886     goto err;
5887   /* Partition info is not handled by mysql_prepare_alter_table() call. */
5888   if (src_table->table->part_info)
5889     thd->work_part_info= src_table->table->part_info->get_clone();
5890 
5891   /*
5892     Adjust description of source table before using it for creation of
5893     target table.
5894 
5895     Similarly to SHOW CREATE TABLE we ignore MAX_ROWS attribute of
5896     temporary table which represents I_S table.
5897   */
5898   if (src_table->schema_table)
5899     local_create_info.max_rows= 0;
5900   /* Set IF NOT EXISTS option as in the CREATE TABLE LIKE statement. */
5901   local_create_info.options|= create_info->options&HA_LEX_CREATE_IF_NOT_EXISTS;
5902   /* Replace type of source table with one specified in the statement. */
5903   local_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
5904   local_create_info.options|= create_info->options & HA_LEX_CREATE_TMP_TABLE;
5905   /* Reset auto-increment counter for the new table. */
5906   local_create_info.auto_increment_value= 0;
5907   /*
5908     Do not inherit values of DATA and INDEX DIRECTORY options from
5909     the original table. This is documented behavior.
5910   */
5911   local_create_info.data_file_name= local_create_info.index_file_name= NULL;
5912   local_create_info.alias= create_info->alias;
5913 
5914   if ((res= mysql_create_table_no_lock(thd, table->db, table->table_name,
5915                                        &local_create_info, &local_alter_info,
5916                                        0, &is_trans)))
5917     goto err;
5918 
5919   /*
5920     Ensure that table or view does not exist and we have an exclusive lock on
5921     target table if we are creating non-temporary table. In LOCK TABLES mode
5922     the only way the table is locked, is if it already exists (since you cannot
5923     LOCK TABLE a non-existing table). And the only way we then can end up here
5924     is if IF EXISTS was used.
5925   */
5926   assert(table->table || table->is_view() ||
5927          (create_info->options & HA_LEX_CREATE_TMP_TABLE) ||
5928          (thd->locked_tables_mode != LTM_LOCK_TABLES &&
5929           thd->mdl_context.owns_equal_or_stronger_lock(MDL_key::TABLE,
5930                                                        table->db, table->table_name,
5931                                                        MDL_EXCLUSIVE)) ||
5932          (thd->locked_tables_mode == LTM_LOCK_TABLES &&
5933           (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS) &&
5934           thd->mdl_context.owns_equal_or_stronger_lock(MDL_key::TABLE,
5935                                                        table->db, table->table_name,
5936                                                        MDL_SHARED_NO_WRITE)));
5937 
5938   DEBUG_SYNC(thd, "create_table_like_before_binlog");
5939 
5940   /*
5941     CREATE TEMPORARY TABLE doesn't terminate a transaction. Calling
5942     stmt.mark_created_temp_table() guarantees the transaction can be binlogged
5943     correctly.
5944   */
5945   if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
5946     thd->get_transaction()->mark_created_temp_table(Transaction_ctx::STMT);
5947 
5948   /*
5949     We have to write the query before we unlock the tables.
5950   */
5951   if (!thd->is_current_stmt_binlog_disabled() &&
5952       thd->is_current_stmt_binlog_format_row())
5953   {
5954     /*
5955        Since temporary tables are not replicated under row-based
5956        replication, CREATE TABLE ... LIKE ... needs special
5957        treatement.  We have four cases to consider, according to the
5958        following decision table:
5959 
5960            ==== ========= ========= ==============================
5961            Case    Target    Source Write to binary log
5962            ==== ========= ========= ==============================
5963            1       normal    normal Original statement
5964            2       normal temporary Generated statement
5965            3    temporary    normal Nothing
5966            4    temporary temporary Nothing
5967            ==== ========= ========= ==============================
5968     */
5969     if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
5970     {
5971       if (src_table->table->s->tmp_table)               // Case 2
5972       {
5973         char buf[2048];
5974         String query(buf, sizeof(buf), system_charset_info);
5975         query.length(0);  // Have to zero it since constructor doesn't
5976         Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN);
5977         bool new_table= FALSE; // Whether newly created table is open.
5978 
5979         /*
5980           The condition avoids a crash as described in BUG#48506. Other
5981           binlogging problems related to CREATE TABLE IF NOT EXISTS LIKE
5982           when the existing object is a view will be solved by BUG 47442.
5983         */
5984         if (!table->is_view())
5985         {
5986           if (!table->table)
5987           {
5988             /*
5989               In order for store_create_info() to work we need to open
5990               destination table if it is not already open (i.e. if it
5991               has not existed before). We don't need acquire metadata
5992               lock in order to do this as we already hold exclusive
5993               lock on this table. The table will be closed by
5994               close_thread_table() at the end of this branch.
5995             */
5996             if (open_table(thd, table, &ot_ctx))
5997               goto err;
5998             new_table= TRUE;
5999           }
6000 
6001           /*
6002             After opening a MERGE table add the children to the query list of
6003             tables, so that children tables info can be used on "CREATE TABLE"
6004             statement generation by the binary log.
6005             Note that placeholders don't have the handler open.
6006           */
6007           if (table->table->file->extra(HA_EXTRA_ADD_CHILDREN_LIST))
6008             goto err;
6009 
6010           /*
6011             As the reference table is temporary and may not exist on slave, we must
6012             force the ENGINE to be present into CREATE TABLE.
6013           */
6014           create_info->used_fields|= HA_CREATE_USED_ENGINE;
6015 
6016           int result MY_ATTRIBUTE((unused))=
6017             store_create_info(thd, table, &query,
6018                               create_info, TRUE /* show_database */);
6019 
6020           assert(result == 0); // store_create_info() always return 0
6021           if (write_bin_log(thd, TRUE, query.ptr(), query.length()))
6022             goto err;
6023 
6024           if (new_table)
6025           {
6026             assert(thd->open_tables == table->table);
6027             /*
6028               When opening the table, we ignored the locked tables
6029               (MYSQL_OPEN_GET_NEW_TABLE). Now we can close the table
6030               without risking to close some locked table.
6031             */
6032             close_thread_table(thd, &thd->open_tables);
6033           }
6034         }
6035       }
6036       else                                      // Case 1
6037         if (write_bin_log(thd, true, thd->query().str, thd->query().length))
6038           goto err;
6039     }
6040     /*
6041       Case 3 and 4 does nothing under RBR
6042     */
6043   }
6044   else if (write_bin_log(thd, true,
6045                          thd->query().str, thd->query().length, is_trans))
6046     goto err;
6047 
6048 err:
6049   DBUG_RETURN(res);
6050 #ifdef WITH_WSREP
6051  error:
6052   thd->wsrep_TOI_pre_query= NULL;
6053   DBUG_RETURN(TRUE);
6054 #endif /* WITH_WSREP */
6055 }
6056 
6057 
6058 /**
6059   Class utilizing RAII for correct set/reset of the
6060   THD::tablespace_op flag. The destructor will reset
6061   the flag when a stack allocated instance goes out
6062   of scope.
6063  */
6064 
6065 class Tablespace_op_flag_handler
6066 {
6067 private:
6068   THD *m_thd;
6069 public:
Tablespace_op_flag_handler(THD * thd)6070   Tablespace_op_flag_handler(THD *thd): m_thd(thd)
6071   {
6072     m_thd->tablespace_op= true;
6073   }
~Tablespace_op_flag_handler()6074   ~Tablespace_op_flag_handler()
6075   {
6076     m_thd->tablespace_op= false;
6077   }
6078 };
6079 
6080 /* table_list should contain just one table */
mysql_discard_or_import_tablespace(THD * thd,TABLE_LIST * table_list,bool discard)6081 int mysql_discard_or_import_tablespace(THD *thd,
6082                                        TABLE_LIST *table_list,
6083                                        bool discard)
6084 {
6085   Alter_table_prelocking_strategy alter_prelocking_strategy;
6086   int error;
6087   DBUG_ENTER("mysql_discard_or_import_tablespace");
6088 
6089   /*
6090     Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
6091     ALTER TABLE
6092   */
6093 
6094    /*
6095      DISCARD/IMPORT TABLESPACE do not respect ALGORITHM and LOCK clauses.
6096    */
6097   if (thd->lex->alter_info.requested_lock !=
6098       Alter_info::ALTER_TABLE_LOCK_DEFAULT)
6099   {
6100     my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
6101              "LOCK=NONE/SHARED/EXCLUSIVE",
6102              "LOCK=DEFAULT");
6103     DBUG_RETURN(true);
6104   }
6105   else if (thd->lex->alter_info.requested_algorithm !=
6106            Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT)
6107   {
6108     my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
6109              "ALGORITHM=COPY/INPLACE",
6110              "ALGORITHM=DEFAULT");
6111     DBUG_RETURN(true);
6112   }
6113 
6114   THD_STAGE_INFO(thd, stage_discard_or_import_tablespace);
6115 
6116   /*
6117     Set thd->tablespace_op, and reset it when the variable leaves scope.
6118     We set this flag so that ha_innobase::open and ::external_lock() do
6119     not complain when we lock the table
6120   */
6121   Tablespace_op_flag_handler set_tablespace_op(thd);
6122 
6123   /*
6124     Adjust values of table-level and metadata which was set in parser
6125     for the case general ALTER TABLE.
6126   */
6127   table_list->mdl_request.set_type(MDL_EXCLUSIVE);
6128   table_list->lock_type= TL_WRITE;
6129   /* Do not open views. */
6130   table_list->required_type= FRMTYPE_TABLE;
6131 
6132   if (open_and_lock_tables(thd, table_list, 0, &alter_prelocking_strategy))
6133   {
6134     /* purecov: begin inspected */
6135     DBUG_RETURN(-1);
6136     /* purecov: end */
6137   }
6138 
6139   if (table_list->table->part_info)
6140   {
6141     /*
6142       If not ALL is mentioned and there is at least one specified
6143       [sub]partition name, use the specified [sub]partitions only.
6144     */
6145     if (thd->lex->alter_info.partition_names.elements > 0 &&
6146         !(thd->lex->alter_info.flags & Alter_info::ALTER_ALL_PARTITION))
6147     {
6148       table_list->partition_names= &thd->lex->alter_info.partition_names;
6149       /* Set all [named] partitions as used. */
6150       if (table_list->table->part_info->set_partition_bitmaps(table_list))
6151         DBUG_RETURN(-1);
6152     }
6153   }
6154   else
6155   {
6156     if (thd->lex->alter_info.partition_names.elements > 0 ||
6157         thd->lex->alter_info.flags & Alter_info::ALTER_ALL_PARTITION)
6158     {
6159       /* Don't allow DISCARD/IMPORT PARTITION on a nonpartitioned table */
6160       my_error(ER_PARTITION_MGMT_ON_NONPARTITIONED, MYF(0));
6161       DBUG_RETURN(true);
6162     }
6163   }
6164 
6165   /*
6166     Under LOCK TABLES we need to upgrade SNRW metadata lock to X lock
6167     before doing discard or import of tablespace.
6168 
6169     Skip this step for temporary tables as metadata locks are not
6170     applicable for them.
6171   */
6172   if (table_list->table->s->tmp_table == NO_TMP_TABLE &&
6173       (thd->locked_tables_mode == LTM_LOCK_TABLES ||
6174        thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) &&
6175       thd->mdl_context.upgrade_shared_lock(table_list->table->mdl_ticket,
6176                                            MDL_EXCLUSIVE,
6177                                            thd->variables.lock_wait_timeout))
6178   {
6179     DBUG_RETURN(-1);
6180   }
6181 
6182   error= table_list->table->file->ha_discard_or_import_tablespace(discard);
6183 
6184   THD_STAGE_INFO(thd, stage_end);
6185 
6186   if (error)
6187     goto err;
6188 
6189   /*
6190     The 0 in the call below means 'not in a transaction', which means
6191     immediate invalidation; that is probably what we wish here
6192   */
6193   query_cache.invalidate(thd, table_list, FALSE);
6194 
6195   /* The ALTER TABLE is always in its own transaction */
6196   error= trans_commit_stmt(thd);
6197   if (trans_commit_implicit(thd))
6198     error=1;
6199   if (error)
6200     goto err;
6201   error= write_bin_log(thd, false, thd->query().str, thd->query().length);
6202 
6203 err:
6204   if (table_list->table->s->tmp_table == NO_TMP_TABLE &&
6205       (thd->locked_tables_mode == LTM_LOCK_TABLES ||
6206        thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES))
6207   {
6208     table_list->table->mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
6209   }
6210 
6211   if (error == 0)
6212   {
6213     my_ok(thd);
6214     DBUG_RETURN(0);
6215   }
6216 
6217   table_list->table->file->print_error(error, MYF(0));
6218 
6219   DBUG_RETURN(-1);
6220 }
6221 
6222 
6223 /**
6224   Check if key is a candidate key, i.e. a unique index with no index
6225   fields partial, nullable or virtual generated.
6226 */
6227 
is_candidate_key(KEY * key)6228 static bool is_candidate_key(KEY *key)
6229 {
6230   KEY_PART_INFO *key_part;
6231   KEY_PART_INFO *key_part_end= key->key_part + key->user_defined_key_parts;
6232 
6233   if (!(key->flags & HA_NOSAME) || (key->flags & HA_NULL_PART_KEY))
6234     return false;
6235 
6236   if (key->flags & HA_VIRTUAL_GEN_KEY)
6237     return false;
6238 
6239   for (key_part= key->key_part; key_part < key_part_end; key_part++)
6240   {
6241     if (key_part->key_part_flag & HA_PART_KEY_SEG)
6242       return false;
6243   }
6244 
6245   return true;
6246 }
6247 
6248 
6249 /**
6250   Get Create_field object for newly created table by field index.
6251 
6252   @param alter_info  Alter_info describing newly created table.
6253   @param idx         Field index.
6254 */
6255 
get_field_by_index(Alter_info * alter_info,uint idx)6256 static Create_field *get_field_by_index(Alter_info *alter_info, uint idx)
6257 {
6258   List_iterator_fast<Create_field> field_it(alter_info->create_list);
6259   uint field_idx= 0;
6260   Create_field *field;
6261 
6262   while ((field= field_it++) && field_idx < idx)
6263   { field_idx++; }
6264 
6265   return field;
6266 }
6267 
6268 
6269 /**
6270   Look-up KEY object by index name using case-insensitive comparison.
6271 
6272   @param key_name   Index name.
6273   @param key_start  Start of array of KEYs for table.
6274   @param key_end    End of array of KEYs for table.
6275 
6276   @note Skips indexes which are marked as renamed.
6277   @note Case-insensitive comparison is necessary to correctly
6278         handle renaming of keys.
6279 
6280   @retval non-NULL - pointer to KEY object for index found.
6281   @retval NULL     - no index with such name found (or it is marked
6282                      as renamed).
6283 */
6284 
find_key_ci(const char * key_name,KEY * key_start,KEY * key_end)6285 static KEY* find_key_ci(const char *key_name, KEY *key_start, KEY *key_end)
6286 {
6287   for (KEY *key= key_start; key < key_end; key++)
6288   {
6289     /* Skip already renamed keys. */
6290     if (! (key->flags & HA_KEY_RENAMED) &&
6291         ! my_strcasecmp(system_charset_info, key_name, key->name))
6292       return key;
6293   }
6294   return NULL;
6295 }
6296 
6297 
6298 /**
6299   Look-up KEY object by index name using case-sensitive comparison.
6300 
6301   @param key_name   Index name.
6302   @param key_start  Start of array of KEYs for table.
6303   @param key_end    End of array of KEYs for table.
6304 
6305   @note Skips indexes which are marked as renamed.
6306   @note Case-sensitive comparison is necessary to correctly
6307         handle: ALTER TABLE t1 DROP KEY x, ADD KEY X(c).
6308         where new and old index are identical except case
6309         of their names (in this case index still needs
6310         to be re-created to keep case of the name in .FRM
6311         and storage-engine in sync).
6312 
6313   @retval non-NULL - pointer to KEY object for index found.
6314   @retval NULL     - no index with such name found (or it is marked
6315                      as renamed).
6316 */
6317 
find_key_cs(const char * key_name,KEY * key_start,KEY * key_end)6318 static KEY* find_key_cs(const char *key_name, KEY *key_start, KEY *key_end)
6319 {
6320   for (KEY *key= key_start; key < key_end; key++)
6321   {
6322     /* Skip renamed keys. */
6323     if (! (key->flags & HA_KEY_RENAMED) && ! strcmp(key_name, key->name))
6324       return key;
6325   }
6326   return NULL;
6327 }
6328 
6329 
6330 /**
6331   Check if index has changed in a new version of table (ignore
6332   possible rename of index). Also changes to the comment field
6333   of the key is marked with a flag in the ha_alter_info.
6334 
6335   @param[in/out]  ha_alter_info  Structure describing changes to be done
6336                                  by ALTER TABLE and holding data used
6337                                  during in-place alter.
6338   @param          table_key      Description of key in old version of table.
6339   @param          new_key        Description of key in new version of table.
6340 
6341   @returns True - if index has changed, false -otherwise.
6342 */
6343 
has_index_def_changed(Alter_inplace_info * ha_alter_info,const KEY * table_key,const KEY * new_key)6344 static bool has_index_def_changed(Alter_inplace_info *ha_alter_info,
6345                                   const KEY *table_key,
6346                                   const KEY *new_key)
6347 {
6348   const KEY_PART_INFO *key_part, *new_part, *end;
6349   const Create_field *new_field;
6350   Alter_info *alter_info= ha_alter_info->alter_info;
6351 
6352   DBUG_EXECUTE_IF("assert_index_def_has_no_pack_flag",
6353                   assert(!(table_key->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY))););
6354 
6355   /* Check that the key types are compatible between old and new tables. */
6356   if ((table_key->algorithm != new_key->algorithm) ||
6357       ((table_key->flags & HA_KEYFLAG_MASK) !=
6358        (new_key->flags & HA_KEYFLAG_MASK)) ||
6359       (table_key->user_defined_key_parts != new_key->user_defined_key_parts))
6360     return true;
6361 
6362   /*
6363     If an index comment is added/dropped/changed, then mark it for a
6364     fast/INPLACE alteration.
6365   */
6366   if ((table_key->comment.length != new_key->comment.length) ||
6367       (table_key->comment.length && strcmp(table_key->comment.str,
6368                                            new_key->comment.str)))
6369     ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_INDEX_COMMENT;
6370 
6371   /*
6372     Check that the key parts remain compatible between the old and
6373     new tables.
6374   */
6375   end= table_key->key_part + table_key->user_defined_key_parts;
6376   for (key_part= table_key->key_part, new_part= new_key->key_part;
6377        key_part < end;
6378        key_part++, new_part++)
6379   {
6380 
6381     new_field= get_field_by_index(alter_info, new_part->fieldnr);
6382 
6383     /*
6384       If there is a change in index length due to column expansion
6385       like varchar(X) changed to varchar(X + N) and has a compatible
6386       packed data representation, we mark it for fast/INPLACE change
6387       in index definition. Some engines like InnoDB supports INPLACE
6388       alter for such cases.
6389 
6390       In other cases, key definition has changed if we are using a
6391       different field or if the used key part length is different, or
6392       key part direction has changed.
6393     */
6394     if (key_part->length != new_part->length &&
6395         ha_alter_info->alter_info->flags == Alter_info::ALTER_CHANGE_COLUMN &&
6396         (key_part->field->is_equal((Create_field *)new_field) == IS_EQUAL_PACK_LENGTH))
6397     {
6398       ha_alter_info->handler_flags|=
6399           Alter_inplace_info::ALTER_COLUMN_INDEX_LENGTH;
6400     }
6401     else if (key_part->length != new_part->length)
6402       return true;
6403 
6404     /*
6405       For prefix keys KEY_PART_INFO::field points to cloned Field
6406       object with adjusted length. So below we have to check field
6407       indexes instead of simply comparing pointers to Field objects.
6408     */
6409     if (! new_field->field ||
6410         new_field->field->field_index != key_part->fieldnr - 1)
6411       return true;
6412 
6413     /*
6414       Key definition has changed, if the key is converted from a
6415       non-prefixed key to a prefixed key or vice-versa. This
6416       is because InnoDB treats prefix keys differently from
6417       full-column keys. Ignoring BLOBs since the key_length()
6418       is not set correctly and also the prefix is ignored
6419       for FULLTEXT keys.
6420       Ex: When the column length is increased but the key part
6421       length remains the same.
6422     */
6423     if (!(new_field->flags & BLOB_FLAG) &&
6424         (table_key->algorithm != HA_KEY_ALG_FULLTEXT))
6425     {
6426       bool old_part_key_seg= (key_part->key_part_flag & HA_PART_KEY_SEG);
6427       bool new_part_key_seg= (new_field->key_length != new_part->length);
6428 
6429       if (old_part_key_seg ^ new_part_key_seg)
6430         return true;
6431     }
6432   }
6433 
6434   return false;
6435 }
6436 
6437 
compare_uint(const uint * s,const uint * t)6438 static int compare_uint(const uint *s, const uint *t)
6439 {
6440   return (*s < *t) ? -1 : ((*s > *t) ? 1 : 0);
6441 }
6442 
6443 
6444 /**
6445    Lock the list of tables which are direct or indirect parents in
6446    foreign key with cascading actions for the table being altered.
6447    This prevents DML operations from being performed on the list of
6448    tables which otherwise may break the 'CASCADE' FK constraint of
6449    the table being altered.
6450 
6451    @param thd        Thread handler.
6452    @param table      The table which is altered.
6453 
6454    @retval false     Ok.
6455    @retval true      Error.
6456 */
6457 
lock_fk_dependent_tables(THD * thd,TABLE * table)6458 static bool lock_fk_dependent_tables(THD *thd, TABLE *table)
6459 {
6460   MDL_request_list mdl_requests;
6461   List <st_handler_tablename> fk_table_list;
6462   List_iterator<st_handler_tablename> fk_table_list_it(fk_table_list);
6463   st_handler_tablename *tbl_name;
6464 
6465   table->file->get_cascade_foreign_key_table_list(thd, &fk_table_list);
6466 
6467   while ((tbl_name= fk_table_list_it++))
6468   {
6469     MDL_request *table_mdl_request= new (thd->mem_root) MDL_request;
6470 
6471     if (table_mdl_request == NULL)
6472       return true;
6473 
6474     MDL_REQUEST_INIT(table_mdl_request,
6475                      MDL_key::TABLE, tbl_name->db,tbl_name->tablename,
6476                      MDL_SHARED_READ_ONLY, MDL_STATEMENT);
6477     mdl_requests.push_front(table_mdl_request);
6478   }
6479 
6480   if (thd->mdl_context.acquire_locks(&mdl_requests,
6481                                      thd->variables.lock_wait_timeout))
6482     return true;
6483 
6484   return false;
6485 }
6486 
6487 
6488 /**
6489    Compare original and new versions of a table and fill Alter_inplace_info
6490    describing differences between those versions.
6491 
6492    @param          thd                Thread
6493    @param          table              The original table.
6494    @param          varchar            Indicates that new definition has new
6495                                       VARCHAR column.
6496    @param[in/out]  ha_alter_info      Data structure which already contains
6497                                       basic information about create options,
6498                                       field and keys for the new version of
6499                                       table and which should be completed with
6500                                       more detailed information needed for
6501                                       in-place ALTER.
6502 
6503    First argument 'table' contains information of the original
6504    table, which includes all corresponding parts that the new
6505    table has in arguments create_list, key_list and create_info.
6506 
6507    Compare the changes between the original and new table definitions.
6508    The result of this comparison is then passed to SE which determines
6509    whether it can carry out these changes in-place.
6510 
6511    Mark any changes detected in the ha_alter_flags.
6512    We generally try to specify handler flags only if there are real
6513    changes. But in cases when it is cumbersome to determine if some
6514    attribute has really changed we might choose to set flag
6515    pessimistically, for example, relying on parser output only.
6516 
6517    If there are no data changes, but index changes, 'index_drop_buffer'
6518    and/or 'index_add_buffer' are populated with offsets into
6519    table->key_info or key_info_buffer respectively for the indexes
6520    that need to be dropped and/or (re-)created.
6521 
6522    Note that this function assumes that it is OK to change Alter_info
6523    and HA_CREATE_INFO which it gets. It is caller who is responsible
6524    for creating copies for this structures if he needs them unchanged.
6525 
6526    @retval true  error
6527    @retval false success
6528 */
6529 
fill_alter_inplace_info(THD * thd,TABLE * table,bool varchar,Alter_inplace_info * ha_alter_info)6530 static bool fill_alter_inplace_info(THD *thd,
6531                                     TABLE *table,
6532                                     bool varchar,
6533                                     Alter_inplace_info *ha_alter_info)
6534 {
6535   Field **f_ptr, *field;
6536   List_iterator_fast<Create_field> new_field_it;
6537   Create_field *new_field;
6538   uint candidate_key_count= 0;
6539   Alter_info *alter_info= ha_alter_info->alter_info;
6540   DBUG_ENTER("fill_alter_inplace_info");
6541 
6542   /* Allocate result buffers. */
6543   if (! (ha_alter_info->index_drop_buffer=
6544           (KEY**) thd->alloc(sizeof(KEY*) * table->s->keys)) ||
6545       ! (ha_alter_info->index_add_buffer=
6546           (uint*) thd->alloc(sizeof(uint) *
6547                             alter_info->key_list.elements)) ||
6548       ! (ha_alter_info->index_rename_buffer=
6549           (KEY_PAIR*) thd->alloc(sizeof(KEY_PAIR) *
6550                                  alter_info->alter_rename_key_list.elements)))
6551     DBUG_RETURN(true);
6552 
6553   /* First we setup ha_alter_flags based on what was detected by parser. */
6554 
6555   /*
6556     Comparing new and old default values of column is cumbersome.
6557     So instead of using such a comparison for detecting if default
6558     has really changed we rely on flags set by parser to get an
6559     approximate value for storage engine flag.
6560   */
6561   if (alter_info->flags & (Alter_info::ALTER_CHANGE_COLUMN |
6562                            Alter_info::ALTER_CHANGE_COLUMN_DEFAULT))
6563     ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_DEFAULT;
6564   if (alter_info->flags & Alter_info::ADD_FOREIGN_KEY)
6565     ha_alter_info->handler_flags|= Alter_inplace_info::ADD_FOREIGN_KEY;
6566   if (alter_info->flags & Alter_info::DROP_FOREIGN_KEY)
6567     ha_alter_info->handler_flags|= Alter_inplace_info::DROP_FOREIGN_KEY;
6568   if (alter_info->flags & Alter_info::ALTER_OPTIONS)
6569     ha_alter_info->handler_flags|= Alter_inplace_info::CHANGE_CREATE_OPTION;
6570   if (alter_info->flags & Alter_info::ALTER_RENAME)
6571     ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_RENAME;
6572   /* Check partition changes */
6573   if (alter_info->flags & Alter_info::ALTER_ADD_PARTITION)
6574     ha_alter_info->handler_flags|= Alter_inplace_info::ADD_PARTITION;
6575   if (alter_info->flags & Alter_info::ALTER_DROP_PARTITION)
6576     ha_alter_info->handler_flags|= Alter_inplace_info::DROP_PARTITION;
6577   if (alter_info->flags & Alter_info::ALTER_PARTITION)
6578     ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_PARTITION;
6579   if (alter_info->flags & Alter_info::ALTER_COALESCE_PARTITION)
6580     ha_alter_info->handler_flags|= Alter_inplace_info::COALESCE_PARTITION;
6581   if (alter_info->flags & Alter_info::ALTER_REORGANIZE_PARTITION)
6582     ha_alter_info->handler_flags|= Alter_inplace_info::REORGANIZE_PARTITION;
6583   if (alter_info->flags & Alter_info::ALTER_TABLE_REORG)
6584     ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_TABLE_REORG;
6585   if (alter_info->flags & Alter_info::ALTER_REMOVE_PARTITIONING)
6586     ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_REMOVE_PARTITIONING;
6587   if (alter_info->flags & Alter_info::ALTER_ALL_PARTITION)
6588     ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_ALL_PARTITION;
6589   /* Check for: ALTER TABLE FORCE, ALTER TABLE ENGINE and OPTIMIZE TABLE. */
6590   if (alter_info->flags & Alter_info::ALTER_RECREATE)
6591     ha_alter_info->handler_flags|= Alter_inplace_info::RECREATE_TABLE;
6592   if (alter_info->flags & Alter_info::ALTER_UPGRADE_PARTITIONING)
6593     ha_alter_info->handler_flags|=
6594       Alter_inplace_info::ALTER_UPGRADE_PARTITIONING;
6595   if (alter_info->with_validation == Alter_info::ALTER_WITH_VALIDATION)
6596     ha_alter_info->handler_flags|= Alter_inplace_info::VALIDATE_VIRTUAL_COLUMN;
6597 
6598   /*
6599     If we altering table with old VARCHAR fields we will be automatically
6600     upgrading VARCHAR column types.
6601   */
6602   if (table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar)
6603     ha_alter_info->handler_flags|=  Alter_inplace_info::ALTER_STORED_COLUMN_TYPE;
6604 
6605   /*
6606     Go through fields in old version of table and detect changes to them.
6607     We don't want to rely solely on Alter_info flags for this since:
6608     a) new definition of column can be fully identical to the old one
6609        despite the fact that this column is mentioned in MODIFY clause.
6610     b) even if new column type differs from its old column from metadata
6611        point of view, it might be identical from storage engine point
6612        of view (e.g. when ENUM('a','b') is changed to ENUM('a','b',c')).
6613     c) flags passed to storage engine contain more detailed information
6614        about nature of changes than those provided from parser.
6615   */
6616   uint old_field_index_without_vgc= 0;
6617   for (f_ptr= table->field; (field= *f_ptr); f_ptr++)
6618   {
6619     /* Clear marker for renamed or dropped field
6620     which we are going to set later. */
6621     field->flags&= ~(FIELD_IS_RENAMED | FIELD_IS_DROPPED);
6622 
6623     /* Use transformed info to evaluate flags for storage engine. */
6624     uint new_field_index= 0;
6625     uint new_field_index_without_vgc= 0;
6626     new_field_it.init(alter_info->create_list);
6627     while ((new_field= new_field_it++))
6628     {
6629       if (new_field->field == field)
6630         break;
6631       if (new_field->stored_in_db)
6632         new_field_index_without_vgc++;
6633       new_field_index++;
6634     }
6635 
6636     if (new_field)
6637     {
6638       /* Field is not dropped. Evaluate changes bitmap for it. */
6639 
6640       /*
6641         Check if type of column has changed to some incompatible type.
6642       */
6643       switch (field->is_equal(new_field))
6644       {
6645       case IS_EQUAL_NO:
6646         /* New column type is incompatible with old one. */
6647         if (field->is_virtual_gcol())
6648           ha_alter_info->handler_flags|=
6649             Alter_inplace_info::ALTER_VIRTUAL_COLUMN_TYPE;
6650         else
6651           ha_alter_info->handler_flags|=
6652             Alter_inplace_info::ALTER_STORED_COLUMN_TYPE;
6653         break;
6654       case IS_EQUAL_YES:
6655         /*
6656           New column is the same as the old one or the fully compatible with
6657           it (for example, ENUM('a','b') was changed to ENUM('a','b','c')).
6658           Such a change if any can ALWAYS be carried out by simply updating
6659           data-dictionary without even informing storage engine.
6660           No flag is set in this case.
6661         */
6662         break;
6663       case IS_EQUAL_PACK_LENGTH:
6664         /*
6665           New column type differs from the old one, but has compatible packed
6666           data representation. Depending on storage engine, such a change can
6667           be carried out by simply updating data dictionary without changing
6668           actual data (for example, VARCHAR(300) is changed to VARCHAR(400)).
6669         */
6670         ha_alter_info->handler_flags|= Alter_inplace_info::
6671                                          ALTER_COLUMN_EQUAL_PACK_LENGTH;
6672         break;
6673       default:
6674         assert(0);
6675       }
6676 
6677       // Conversion to and from generated column is supported if stored:
6678       if (field->is_gcol() != new_field->is_gcol())
6679       {
6680         assert((field->is_gcol() && !field->is_virtual_gcol()) ||
6681                (new_field->is_gcol() && !new_field->is_virtual_gcol()));
6682         ha_alter_info->handler_flags|=
6683           Alter_inplace_info::ALTER_STORED_COLUMN_TYPE;
6684       }
6685 
6686       // Modification of generation expression is supported:
6687       if (field->is_gcol() && new_field->is_gcol())
6688       {
6689         // Modification of storage attribute is not supported
6690         assert(field->is_virtual_gcol() == new_field->is_virtual_gcol());
6691         if (!field->gcol_expr_is_equal(new_field))
6692         {
6693           if (field->is_virtual_gcol())
6694             ha_alter_info->handler_flags|=
6695               Alter_inplace_info::ALTER_VIRTUAL_COLUMN_TYPE;
6696           else
6697             ha_alter_info->handler_flags|=
6698               Alter_inplace_info::ALTER_STORED_COLUMN_TYPE;
6699         }
6700       }
6701 
6702       bool field_renamed;
6703       /*
6704         InnoDB data dictionary is case sensitive so we should use
6705         string case sensitive comparison between fields.
6706         Note: strcmp branch is to be removed in future when we fix it
6707         in InnoDB.
6708       */
6709       if (ha_alter_info->create_info->db_type->db_type == DB_TYPE_INNODB)
6710         field_renamed= strcmp(field->field_name, new_field->field_name);
6711       else
6712 	field_renamed= my_strcasecmp(system_charset_info, field->field_name,
6713                                      new_field->field_name);
6714 
6715       /* Check if field was renamed */
6716       if (field_renamed)
6717       {
6718         field->flags|= FIELD_IS_RENAMED;
6719         ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_COLUMN_NAME;
6720       }
6721 
6722       /* Check that NULL behavior is same for old and new fields */
6723       if ((new_field->flags & NOT_NULL_FLAG) !=
6724           (uint) (field->flags & NOT_NULL_FLAG))
6725       {
6726         if (new_field->flags & NOT_NULL_FLAG)
6727           ha_alter_info->handler_flags|=
6728             Alter_inplace_info::ALTER_COLUMN_NOT_NULLABLE;
6729         else
6730           ha_alter_info->handler_flags|=
6731             Alter_inplace_info::ALTER_COLUMN_NULLABLE;
6732       }
6733 
6734       /*
6735         We do not detect changes to default values in this loop.
6736         See comment above for more details.
6737       */
6738 
6739       /*
6740         Detect changes in column order.
6741 
6742         Note that a stored column can't become virtual and vice versa
6743         thanks to check in mysql_prepare_alter_table().
6744       */
6745       if (field->stored_in_db)
6746       {
6747         if (old_field_index_without_vgc != new_field_index_without_vgc)
6748           ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_STORED_COLUMN_ORDER;
6749       }
6750       else
6751       {
6752         if (field->field_index != new_field_index)
6753           ha_alter_info->handler_flags|= Alter_inplace_info::ALTER_VIRTUAL_COLUMN_ORDER;
6754       }
6755 
6756       /* Detect changes in storage type of column */
6757       if (new_field->field_storage_type() != field->field_storage_type())
6758         ha_alter_info->handler_flags|=
6759           Alter_inplace_info::ALTER_COLUMN_STORAGE_TYPE;
6760 
6761       /* Detect changes in column format of column */
6762       if (new_field->column_format() != field->column_format())
6763         ha_alter_info->handler_flags|=
6764           Alter_inplace_info::ALTER_COLUMN_COLUMN_FORMAT;
6765 
6766       /*
6767         We don't have easy way to detect change in generation expression.
6768         So we always assume that it has changed if generated column was
6769         mentioned in CHANGE/MODIFY COLUMN clause of ALTER TABLE.
6770       */
6771       if (new_field->change)
6772       {
6773         if (new_field->is_virtual_gcol())
6774             ha_alter_info->handler_flags|=
6775               Alter_inplace_info::ALTER_VIRTUAL_GCOL_EXPR;
6776         else if (new_field->gcol_info)
6777             ha_alter_info->handler_flags|=
6778               Alter_inplace_info::ALTER_STORED_GCOL_EXPR;
6779       }
6780     }
6781     else
6782     {
6783       /*
6784         Field is not present in new version of table and therefore was dropped.
6785       */
6786       assert(alter_info->flags & Alter_info::ALTER_DROP_COLUMN);
6787       if (field->is_virtual_gcol())
6788         ha_alter_info->handler_flags|=
6789           Alter_inplace_info::DROP_VIRTUAL_COLUMN;
6790       else
6791         ha_alter_info->handler_flags|=
6792           Alter_inplace_info::DROP_STORED_COLUMN;
6793       field->flags|= FIELD_IS_DROPPED;
6794     }
6795     if (field->stored_in_db)
6796       old_field_index_without_vgc++;
6797   }
6798 
6799   if (alter_info->flags & Alter_info::ALTER_ADD_COLUMN)
6800   {
6801     new_field_it.init(alter_info->create_list);
6802     while ((new_field= new_field_it++))
6803     {
6804       if (!new_field->field)
6805       {
6806         /*
6807           Field is not present in old version of table and therefore was added.
6808         */
6809         if (new_field->is_virtual_gcol())
6810           ha_alter_info->handler_flags|=
6811             Alter_inplace_info::ADD_VIRTUAL_COLUMN;
6812         else if (new_field->gcol_info)
6813           ha_alter_info->handler_flags|=
6814             Alter_inplace_info::ADD_STORED_GENERATED_COLUMN;
6815         else
6816           ha_alter_info->handler_flags|=
6817             Alter_inplace_info::ADD_STORED_BASE_COLUMN;
6818       }
6819     }
6820     /* One of these should be set since Alter_info::ALTER_ADD_COLUMN was set. */
6821     assert(ha_alter_info->handler_flags &
6822            (Alter_inplace_info::ADD_VIRTUAL_COLUMN |
6823             Alter_inplace_info::ADD_STORED_BASE_COLUMN |
6824             Alter_inplace_info::ADD_STORED_GENERATED_COLUMN));
6825   }
6826 
6827   /*
6828     Go through keys and check if the original ones are compatible
6829     with new table.
6830   */
6831   KEY *table_key;
6832   KEY *table_key_end= table->key_info + table->s->keys;
6833   KEY *new_key;
6834   KEY *new_key_end=
6835     ha_alter_info->key_info_buffer + ha_alter_info->key_count;
6836 
6837   DBUG_PRINT("info", ("index count old: %d  new: %d",
6838                       table->s->keys, ha_alter_info->key_count));
6839 
6840   /*
6841     First, we need to handle keys being renamed, otherwise code handling
6842     dropping/addition of keys might be confused in some situations.
6843   */
6844   for (table_key= table->key_info; table_key < table_key_end; table_key++)
6845     table_key->flags&= ~HA_KEY_RENAMED;
6846   for (new_key= ha_alter_info->key_info_buffer;
6847        new_key < new_key_end; new_key++)
6848     new_key->flags&= ~HA_KEY_RENAMED;
6849 
6850   List_iterator_fast<Alter_rename_key> rename_key_it(alter_info->
6851                                                      alter_rename_key_list);
6852   Alter_rename_key *rename_key;
6853 
6854   while ((rename_key= rename_key_it++))
6855   {
6856     table_key= find_key_ci(rename_key->old_name, table->key_info, table_key_end);
6857     new_key= find_key_ci(rename_key->new_name, ha_alter_info->key_info_buffer,
6858                          new_key_end);
6859 
6860     table_key->flags|= HA_KEY_RENAMED;
6861     new_key->flags|= HA_KEY_RENAMED;
6862 
6863     if (! has_index_def_changed(ha_alter_info, table_key, new_key))
6864     {
6865       /* Key was not modified but still was renamed. */
6866       ha_alter_info->handler_flags|= Alter_inplace_info::RENAME_INDEX;
6867       ha_alter_info->add_renamed_key(table_key, new_key);
6868     }
6869     else
6870     {
6871       /* Key was modified. */
6872       ha_alter_info->add_modified_key(table_key, new_key);
6873     }
6874   }
6875 
6876   /*
6877     Step through all keys of the old table and search matching new keys.
6878   */
6879   for (table_key= table->key_info; table_key < table_key_end; table_key++)
6880   {
6881     /* Skip renamed keys. */
6882     if (table_key->flags & HA_KEY_RENAMED)
6883       continue;
6884 
6885     new_key= find_key_cs(table_key->name, ha_alter_info->key_info_buffer,
6886                          new_key_end);
6887 
6888     if (new_key == NULL)
6889     {
6890       /* Matching new key not found. This means the key should be dropped. */
6891       ha_alter_info->add_dropped_key(table_key);
6892     }
6893     else if (has_index_def_changed(ha_alter_info, table_key, new_key))
6894     {
6895       /* Key was modified. */
6896       ha_alter_info->add_modified_key(table_key, new_key);
6897     }
6898   }
6899 
6900   /*
6901     Step through all keys of the new table and find matching old keys.
6902   */
6903   for (new_key= ha_alter_info->key_info_buffer;
6904        new_key < new_key_end;
6905        new_key++)
6906   {
6907     /* Skip renamed keys. */
6908     if (new_key->flags & HA_KEY_RENAMED)
6909       continue;
6910 
6911     if (! find_key_cs(new_key->name, table->key_info, table_key_end))
6912     {
6913       /* Matching old key not found. This means the key should be added. */
6914       ha_alter_info->add_added_key(new_key);
6915     }
6916   }
6917 
6918   /*
6919     Sort index_add_buffer according to how key_info_buffer is sorted.
6920     I.e. with primary keys first - see sort_keys().
6921   */
6922   my_qsort(ha_alter_info->index_add_buffer,
6923            ha_alter_info->index_add_count,
6924            sizeof(uint), (qsort_cmp) compare_uint);
6925 
6926   /* Now let us calculate flags for storage engine API. */
6927 
6928   /* Count all existing candidate keys. */
6929   for (table_key= table->key_info; table_key < table_key_end; table_key++)
6930   {
6931     /*
6932       Check if key is a candidate key, This key is either already primary key
6933       or could be promoted to primary key if the original primary key is
6934       dropped.
6935       In MySQL one is allowed to create primary key with partial fields (i.e.
6936       primary key which is not considered candidate). For simplicity we count
6937       such key as a candidate key here.
6938     */
6939     if (((uint) (table_key - table->key_info) == table->s->primary_key) ||
6940         is_candidate_key(table_key))
6941       candidate_key_count++;
6942   }
6943 
6944   /* Figure out what kind of indexes we are dropping. */
6945   KEY **dropped_key;
6946   KEY **dropped_key_end= ha_alter_info->index_drop_buffer +
6947                          ha_alter_info->index_drop_count;
6948 
6949   for (dropped_key= ha_alter_info->index_drop_buffer;
6950        dropped_key < dropped_key_end; dropped_key++)
6951   {
6952     table_key= *dropped_key;
6953 
6954     if (table_key->flags & HA_NOSAME)
6955     {
6956       /*
6957         Unique key. Check for PRIMARY KEY. Also see comment about primary
6958         and candidate keys above.
6959       */
6960       if ((uint) (table_key - table->key_info) == table->s->primary_key)
6961       {
6962         ha_alter_info->handler_flags|= Alter_inplace_info::DROP_PK_INDEX;
6963         candidate_key_count--;
6964       }
6965       else
6966       {
6967         ha_alter_info->handler_flags|= Alter_inplace_info::DROP_UNIQUE_INDEX;
6968         if (is_candidate_key(table_key))
6969           candidate_key_count--;
6970       }
6971     }
6972     else
6973       ha_alter_info->handler_flags|= Alter_inplace_info::DROP_INDEX;
6974   }
6975 
6976   /* Now figure out what kind of indexes we are adding. */
6977   for (uint add_key_idx= 0; add_key_idx < ha_alter_info->index_add_count; add_key_idx++)
6978   {
6979     new_key= ha_alter_info->key_info_buffer + ha_alter_info->index_add_buffer[add_key_idx];
6980 
6981     if (new_key->flags & HA_NOSAME)
6982     {
6983       bool is_pk= !my_strcasecmp(system_charset_info, new_key->name, primary_key_name);
6984 
6985       if ((!(new_key->flags & HA_KEY_HAS_PART_KEY_SEG) &&
6986            !(new_key->flags & HA_NULL_PART_KEY)) ||
6987           is_pk)
6988       {
6989         /* Candidate key or primary key! */
6990         if (candidate_key_count == 0 || is_pk)
6991           ha_alter_info->handler_flags|= Alter_inplace_info::ADD_PK_INDEX;
6992         else
6993           ha_alter_info->handler_flags|= Alter_inplace_info::ADD_UNIQUE_INDEX;
6994         candidate_key_count++;
6995       }
6996       else
6997       {
6998         ha_alter_info->handler_flags|= Alter_inplace_info::ADD_UNIQUE_INDEX;
6999       }
7000     }
7001     else
7002     {
7003       if (new_key->flags & HA_SPATIAL)
7004       {
7005         ha_alter_info->handler_flags|= Alter_inplace_info::ADD_SPATIAL_INDEX;
7006       }
7007       else
7008       {
7009         ha_alter_info->handler_flags|= Alter_inplace_info::ADD_INDEX;
7010       }
7011     }
7012   }
7013 
7014   DBUG_RETURN(false);
7015 }
7016 
7017 
7018 /**
7019   Mark fields participating in newly added indexes in TABLE object which
7020   corresponds to new version of altered table.
7021 
7022   @param ha_alter_info  Alter_inplace_info describing in-place ALTER.
7023   @param altered_table  TABLE object for new version of TABLE in which
7024                         fields should be marked.
7025 */
7026 
update_altered_table(const Alter_inplace_info & ha_alter_info,TABLE * altered_table)7027 static void update_altered_table(const Alter_inplace_info &ha_alter_info,
7028                                  TABLE *altered_table)
7029 {
7030   uint field_idx, add_key_idx;
7031   KEY *key;
7032   KEY_PART_INFO *end, *key_part;
7033 
7034   /*
7035     Clear marker for all fields, as we are going to set it only
7036     for fields which participate in new indexes.
7037   */
7038   for (field_idx= 0; field_idx < altered_table->s->fields; ++field_idx)
7039     altered_table->field[field_idx]->flags&= ~FIELD_IN_ADD_INDEX;
7040 
7041   /*
7042     Go through array of newly added indexes and mark fields
7043     participating in them.
7044   */
7045   for (add_key_idx= 0; add_key_idx < ha_alter_info.index_add_count;
7046        add_key_idx++)
7047   {
7048     key= ha_alter_info.key_info_buffer +
7049          ha_alter_info.index_add_buffer[add_key_idx];
7050 
7051     end= key->key_part + key->user_defined_key_parts;
7052     for (key_part= key->key_part; key_part < end; key_part++)
7053       altered_table->field[key_part->fieldnr]->flags|= FIELD_IN_ADD_INDEX;
7054   }
7055 }
7056 
7057 
7058 /**
7059   Initialize TABLE::field for the new table with appropriate
7060   column defaults. Can be default values from TABLE_SHARE or
7061   function defaults from Create_field.
7062 
7063   @param altered_table  TABLE object for the new version of the table.
7064   @param create         Create_field containing function defaults.
7065 */
7066 
set_column_defaults(TABLE * altered_table,List<Create_field> & create)7067 static void set_column_defaults(TABLE *altered_table,
7068                                 List<Create_field> &create)
7069 {
7070   // Initialize TABLE::field default values
7071   restore_record(altered_table, s->default_values);
7072 
7073   List_iterator<Create_field> iter(create);
7074   for (uint i= 0; i < altered_table->s->fields; ++i)
7075   {
7076     const Create_field *definition= iter++;
7077     if (definition->field == NULL) // this column didn't exist in old table.
7078       altered_table->field[i]->evaluate_insert_default_function();
7079   }
7080 }
7081 
7082 
7083 /**
7084   Compare two tables to see if their metadata are compatible.
7085   One table specified by a TABLE instance, the other using Alter_info
7086   and HA_CREATE_INFO.
7087 
7088   @param[in]  table          The first table.
7089   @param[in]  alter_info     Alter options, fields and keys for the
7090                              second table.
7091   @param[in]  create_info    Create options for the second table.
7092   @param[out] metadata_equal Result of comparison.
7093 
7094   @retval true   error
7095   @retval false  success
7096 */
7097 
mysql_compare_tables(TABLE * table,Alter_info * alter_info,HA_CREATE_INFO * create_info,bool * metadata_equal)7098 bool mysql_compare_tables(TABLE *table,
7099                           Alter_info *alter_info,
7100                           HA_CREATE_INFO *create_info,
7101                           bool *metadata_equal)
7102 {
7103   DBUG_ENTER("mysql_compare_tables");
7104 
7105   uint changes= IS_EQUAL_NO;
7106   uint key_count;
7107   List_iterator_fast<Create_field> tmp_new_field_it;
7108   THD *thd= table->in_use;
7109   *metadata_equal= false;
7110 
7111   /*
7112     Create a copy of alter_info.
7113     To compare definitions, we need to "prepare" the definition - transform it
7114     from parser output to a format that describes the table layout (all column
7115     defaults are initialized, duplicate columns are removed). This is done by
7116     mysql_prepare_create_table.  Unfortunately, mysql_prepare_create_table
7117     performs its transformations "in-place", that is, modifies the argument.
7118     Since we would like to keep mysql_compare_tables() idempotent (not altering
7119     any of the arguments) we create a copy of alter_info here and pass it to
7120     mysql_prepare_create_table, then use the result to compare the tables, and
7121     then destroy the copy.
7122   */
7123   Alter_info tmp_alter_info(*alter_info, thd->mem_root);
7124   uint db_options= 0; /* not used */
7125   KEY *key_info_buffer= NULL;
7126 
7127   /* Create the prepared information. */
7128   if (mysql_prepare_create_table(thd, "", "",
7129                                  create_info, &tmp_alter_info,
7130                                  (table->s->tmp_table != NO_TMP_TABLE),
7131                                  &db_options,
7132                                  table->file, &key_info_buffer,
7133                                  &key_count, 0))
7134     DBUG_RETURN(true);
7135 
7136   /* Some very basic checks. */
7137   if (table->s->fields != alter_info->create_list.elements ||
7138       table->s->db_type() != create_info->db_type ||
7139       table->s->tmp_table ||
7140       (table->s->row_type != create_info->row_type))
7141     DBUG_RETURN(false);
7142 
7143   /* Go through fields and check if they are compatible. */
7144   tmp_new_field_it.init(tmp_alter_info.create_list);
7145   for (Field **f_ptr= table->field; *f_ptr; f_ptr++)
7146   {
7147     Field *field= *f_ptr;
7148     Create_field *tmp_new_field= tmp_new_field_it++;
7149 
7150     /* Check that NULL behavior is the same. */
7151     if ((tmp_new_field->flags & NOT_NULL_FLAG) !=
7152 	(uint) (field->flags & NOT_NULL_FLAG))
7153       DBUG_RETURN(false);
7154 
7155     /*
7156       mysql_prepare_alter_table() clears HA_OPTION_PACK_RECORD bit when
7157       preparing description of existing table. In ALTER TABLE it is later
7158       updated to correct value by create_table_impl() call.
7159       So to get correct value of this bit in this function we have to
7160       mimic behavior of create_table_impl().
7161     */
7162     if (create_info->row_type == ROW_TYPE_DYNAMIC ||
7163 	(tmp_new_field->flags & BLOB_FLAG) ||
7164 	(tmp_new_field->sql_type == MYSQL_TYPE_VARCHAR &&
7165 	create_info->row_type != ROW_TYPE_FIXED))
7166       create_info->table_options|= HA_OPTION_PACK_RECORD;
7167 
7168     /* Check if field was renamed */
7169     if (my_strcasecmp(system_charset_info,
7170 		      field->field_name,
7171 		      tmp_new_field->field_name))
7172       DBUG_RETURN(false);
7173 
7174     /* Evaluate changes bitmap and send to check_if_incompatible_data() */
7175     uint field_changes= field->is_equal(tmp_new_field);
7176     if (field_changes != IS_EQUAL_YES)
7177       DBUG_RETURN(false);
7178 
7179     changes|= field_changes;
7180   }
7181 
7182   /* Check if changes are compatible with current handler. */
7183   if (table->file->check_if_incompatible_data(create_info, changes))
7184     DBUG_RETURN(false);
7185 
7186   /* Go through keys and check if they are compatible. */
7187   KEY *table_key;
7188   KEY *table_key_end= table->key_info + table->s->keys;
7189   KEY *new_key;
7190   KEY *new_key_end= key_info_buffer + key_count;
7191 
7192   /* Step through all keys of the first table and search matching keys. */
7193   for (table_key= table->key_info; table_key < table_key_end; table_key++)
7194   {
7195     /* Search a key with the same name. */
7196     for (new_key= key_info_buffer; new_key < new_key_end; new_key++)
7197     {
7198       if (! strcmp(table_key->name, new_key->name))
7199         break;
7200     }
7201     if (new_key >= new_key_end)
7202       DBUG_RETURN(false);
7203 
7204     /* Check that the key types are compatible. */
7205     if ((table_key->algorithm != new_key->algorithm) ||
7206 	((table_key->flags & HA_KEYFLAG_MASK) !=
7207          (new_key->flags & HA_KEYFLAG_MASK)) ||
7208         (table_key->user_defined_key_parts != new_key->user_defined_key_parts))
7209       DBUG_RETURN(false);
7210 
7211     /* Check that the key parts remain compatible. */
7212     KEY_PART_INFO *table_part;
7213     KEY_PART_INFO *table_part_end= table_key->key_part +
7214       table_key->user_defined_key_parts;
7215     KEY_PART_INFO *new_part;
7216     for (table_part= table_key->key_part, new_part= new_key->key_part;
7217          table_part < table_part_end;
7218          table_part++, new_part++)
7219     {
7220       /*
7221 	Key definition is different if we are using a different field or
7222 	if the used key part length is different. We know that the fields
7223         are equal. Comparing field numbers is sufficient.
7224       */
7225       if ((table_part->length != new_part->length) ||
7226           (table_part->fieldnr - 1 != new_part->fieldnr))
7227         DBUG_RETURN(false);
7228     }
7229   }
7230 
7231   /* Step through all keys of the second table and find matching keys. */
7232   for (new_key= key_info_buffer; new_key < new_key_end; new_key++)
7233   {
7234     /* Search a key with the same name. */
7235     for (table_key= table->key_info; table_key < table_key_end; table_key++)
7236     {
7237       if (! strcmp(table_key->name, new_key->name))
7238         break;
7239     }
7240     if (table_key >= table_key_end)
7241       DBUG_RETURN(false);
7242   }
7243 
7244   *metadata_equal= true; // Tables are compatible
7245   DBUG_RETURN(false);
7246 }
7247 
7248 
7249 /**
7250    Report a zero date warning if no default value is supplied
7251    for the DATE/DATETIME 'NOT NULL' field and 'NO_ZERO_DATE'
7252    sql_mode is enabled.
7253 
7254    @param thd                Thread handle.
7255    @param datetime_field     DATE/DATETIME column definition.
7256 */
push_zero_date_warning(THD * thd,Create_field * datetime_field)7257 static void push_zero_date_warning(THD *thd, Create_field *datetime_field)
7258 {
7259   uint f_length= 0;
7260   enum enum_mysql_timestamp_type t_type= MYSQL_TIMESTAMP_DATE;
7261 
7262   switch (datetime_field->sql_type)
7263   {
7264   case MYSQL_TYPE_DATE:
7265   case MYSQL_TYPE_NEWDATE:
7266     f_length= MAX_DATE_WIDTH; // "0000-00-00";
7267     t_type= MYSQL_TIMESTAMP_DATE;
7268     break;
7269   case MYSQL_TYPE_DATETIME:
7270   case MYSQL_TYPE_DATETIME2:
7271     f_length= MAX_DATETIME_WIDTH; // "0000-00-00 00:00:00";
7272     t_type= MYSQL_TIMESTAMP_DATETIME;
7273     break;
7274   default:
7275     assert(false);  // Should not get here.
7276   }
7277   make_truncated_value_warning(thd, Sql_condition::SL_WARNING,
7278                                ErrConvString(my_zero_datetime6, f_length),
7279                                t_type, datetime_field->field_name);
7280 }
7281 
7282 
7283 /*
7284   Manages enabling/disabling of indexes for ALTER TABLE
7285 
7286   SYNOPSIS
7287     alter_table_manage_keys()
7288       table                  Target table
7289       indexes_were_disabled  Whether the indexes of the from table
7290                              were disabled
7291       keys_onoff             ENABLE | DISABLE | LEAVE_AS_IS
7292 
7293   RETURN VALUES
7294     FALSE  OK
7295     TRUE   Error
7296 */
7297 
7298 static
alter_table_manage_keys(TABLE * table,int indexes_were_disabled,Alter_info::enum_enable_or_disable keys_onoff)7299 bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
7300                              Alter_info::enum_enable_or_disable keys_onoff)
7301 {
7302   int error= 0;
7303   DBUG_ENTER("alter_table_manage_keys");
7304   DBUG_PRINT("enter", ("table=%p were_disabled=%d on_off=%d",
7305              table, indexes_were_disabled, keys_onoff));
7306 
7307   switch (keys_onoff) {
7308   case Alter_info::ENABLE:
7309     error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
7310     break;
7311   case Alter_info::LEAVE_AS_IS:
7312     if (!indexes_were_disabled)
7313       break;
7314     /* fall-through: disabled indexes */
7315   case Alter_info::DISABLE:
7316     error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
7317   }
7318 
7319   if (error == HA_ERR_WRONG_COMMAND)
7320   {
7321     push_warning_printf(current_thd, Sql_condition::SL_NOTE,
7322                         ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
7323                         table->s->table_name.str);
7324     error= 0;
7325   } else if (error)
7326     table->file->print_error(error, MYF(0));
7327 
7328   DBUG_RETURN(error);
7329 }
7330 
7331 
7332 /**
7333   Check if the pending ALTER TABLE operations support the in-place
7334   algorithm based on restrictions in the SQL layer or given the
7335   nature of the operations themselves. If in-place isn't supported,
7336   it won't be necessary to check with the storage engine.
7337 
7338   @param table        The original TABLE.
7339   @param create_info  Information from the parsing phase about new
7340                       table properties.
7341   @param alter_info   Data related to detected changes.
7342   @param alter_ctx    Runtime context for ALTER TABLE.
7343 
7344   @return false       In-place is possible, check with storage engine.
7345   @return true        Incompatible operations, must use table copy.
7346 */
7347 
is_inplace_alter_impossible(TABLE * table,HA_CREATE_INFO * create_info,const Alter_info * alter_info,const Alter_table_ctx * alter_ctx)7348 static bool is_inplace_alter_impossible(TABLE *table,
7349                                         HA_CREATE_INFO *create_info,
7350                                         const Alter_info *alter_info,
7351                                         const Alter_table_ctx *alter_ctx)
7352 {
7353   DBUG_ENTER("is_inplace_alter_impossible");
7354 
7355   /* At the moment we can't handle altering temporary tables without a copy. */
7356   if (table->s->tmp_table)
7357     DBUG_RETURN(true);
7358 
7359   /*
7360     For the ALTER TABLE tbl_name ORDER BY ... we always use copy
7361     algorithm. In theory, this operation can be done in-place by some
7362     engine, but since a) no current engine does this and b) our current
7363     API lacks infrastructure for passing information about table ordering
7364     to storage engine we simply always do copy now.
7365 
7366     ENABLE/DISABLE KEYS is a MyISAM/Heap specific operation that is
7367     not supported for in-place in combination with other operations.
7368     Alone, it will be done by simple_rename_or_index_change().
7369 
7370     Stored generated columns are evaluated in server, thus can't be added/changed
7371     inplace.
7372   */
7373   if (alter_info->flags & (Alter_info::ALTER_ORDER |
7374                            Alter_info::ALTER_KEYS_ONOFF))
7375     DBUG_RETURN(true);
7376 
7377   /*
7378     If the table engine is changed explicitly (using ENGINE clause)
7379     or implicitly (e.g. when non-partitioned table becomes
7380     partitioned) a regular alter table (copy) needs to be
7381     performed.
7382   */
7383   if (create_info->db_type != table->s->db_type())
7384   {
7385     /*
7386       If we are altering/recreating a table using the generic partitioning
7387       engine ha_partition, but the real engine supports partitioning
7388       natively, do not disallow INPLACE, since it will be handled in
7389       ha_partition/real engine and allow the engine to be upgraded to native
7390       partitioning!
7391     */
7392     if (!is_ha_partition_handlerton(table->s->db_type()) ||
7393         !create_info->db_type->partition_flags ||
7394         table->part_info->default_engine_type != create_info->db_type ||
7395         (create_info->used_fields & HA_CREATE_USED_ENGINE))
7396     {
7397       DBUG_RETURN(true);
7398     }
7399   }
7400 
7401   /*
7402     There was a bug prior to mysql-4.0.25. Number of null fields was
7403     calculated incorrectly. As a result frm and data files gets out of
7404     sync after fast alter table. There is no way to determine by which
7405     mysql version (in 4.0 and 4.1 branches) table was created, thus we
7406     disable fast alter table for all tables created by mysql versions
7407     prior to 5.0 branch.
7408     See BUG#6236.
7409   */
7410   if (!table->s->mysql_version)
7411     DBUG_RETURN(true);
7412 
7413   /*
7414     If default value is changed and the table includes or will include
7415     generated columns that depend on the DEFAULT function, we cannot
7416     do the operation inplace as indexes or value of stored generated
7417     columns might become invalid.
7418   */
7419   if ((alter_info->flags &
7420        (Alter_info::ALTER_CHANGE_COLUMN_DEFAULT |
7421         Alter_info::ALTER_CHANGE_COLUMN)) &&
7422        table->has_gcol())
7423   {
7424     for (Field **vfield= table->vfield; *vfield; vfield++)
7425     {
7426       if ((*vfield)->gcol_info->expr_item->walk(
7427            &Item::check_gcol_depend_default_processor,
7428            Item::WALK_POSTFIX, NULL))
7429         DBUG_RETURN(true);
7430     }
7431   }
7432 
7433   DBUG_RETURN(false);
7434 }
7435 
7436 
7437 /**
7438   Perform in-place alter table.
7439 
7440   @param thd                Thread handle.
7441   @param table_list         TABLE_LIST for the table to change.
7442   @param table              The original TABLE.
7443   @param altered_table      TABLE object for new version of the table.
7444   @param ha_alter_info      Structure describing ALTER TABLE to be carried
7445                             out and serving as a storage place for data
7446                             used during different phases.
7447   @param inplace_supported  Enum describing the locking requirements.
7448   @param target_mdl_request Metadata request/lock on the target table name.
7449   @param alter_ctx          ALTER TABLE runtime context.
7450 
7451   @retval   true              Error
7452   @retval   false             Success
7453 
7454   @note
7455     If mysql_alter_table does not need to copy the table, it is
7456     either an alter table where the storage engine does not
7457     need to know about the change, only the frm will change,
7458     or the storage engine supports performing the alter table
7459     operation directly, in-place without mysql having to copy
7460     the table.
7461 
7462   @note This function frees the TABLE object associated with the new version of
7463         the table and removes the .FRM file for it in case of both success and
7464         failure.
7465 */
7466 
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)7467 static bool mysql_inplace_alter_table(THD *thd,
7468                                       TABLE_LIST *table_list,
7469                                       TABLE *table,
7470                                       TABLE *altered_table,
7471                                       Alter_inplace_info *ha_alter_info,
7472                                       enum_alter_inplace_result inplace_supported,
7473                                       MDL_request *target_mdl_request,
7474                                       Alter_table_ctx *alter_ctx)
7475 {
7476   Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN);
7477   MDL_ticket *mdl_ticket= table->mdl_ticket;
7478   HA_CREATE_INFO *create_info= ha_alter_info->create_info;
7479   Alter_info *alter_info= ha_alter_info->alter_info;
7480   bool reopen_tables= false;
7481 
7482   DBUG_ENTER("mysql_inplace_alter_table");
7483 
7484   /*
7485     Upgrade to EXCLUSIVE lock if:
7486     - This is requested by the storage engine
7487     - Or the storage engine needs exclusive lock for just the prepare
7488       phase
7489     - Or requested by the user
7490 
7491     Note that we handle situation when storage engine needs exclusive
7492     lock for prepare phase under LOCK TABLES in the same way as when
7493     exclusive lock is required for duration of the whole statement.
7494   */
7495   if (inplace_supported == HA_ALTER_INPLACE_EXCLUSIVE_LOCK ||
7496       ((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
7497         inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE) &&
7498        (thd->locked_tables_mode == LTM_LOCK_TABLES ||
7499         thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) ||
7500        alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)
7501   {
7502     if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
7503       goto cleanup;
7504     /*
7505       Get rid of all TABLE instances belonging to this thread
7506       except one to be used for in-place ALTER TABLE.
7507 
7508       This is mostly needed to satisfy InnoDB assumptions/asserts.
7509     */
7510     close_all_tables_for_name(thd, table->s, alter_ctx->is_table_renamed(),
7511                               table);
7512     /*
7513       If we are under LOCK TABLES we will need to reopen tables which we
7514       just have closed in case of error.
7515     */
7516     reopen_tables= true;
7517   }
7518   else if (inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
7519            inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE)
7520   {
7521     /*
7522       Storage engine has requested exclusive lock only for prepare phase
7523       and we are not under LOCK TABLES.
7524       Don't mark TABLE_SHARE as old in this case, as this won't allow opening
7525       of table by other threads during main phase of in-place ALTER TABLE.
7526     */
7527     if (thd->mdl_context.upgrade_shared_lock(table->mdl_ticket, MDL_EXCLUSIVE,
7528                                              thd->variables.lock_wait_timeout))
7529       goto cleanup;
7530 
7531     tdc_remove_table(thd, TDC_RT_REMOVE_NOT_OWN_KEEP_SHARE,
7532                      table->s->db.str, table->s->table_name.str,
7533                      false);
7534   }
7535 
7536   /*
7537     Upgrade to SHARED_NO_WRITE lock if:
7538     - The storage engine needs writes blocked for the whole duration
7539     - Or this is requested by the user
7540     Note that under LOCK TABLES, we will already have SHARED_NO_READ_WRITE.
7541   */
7542   if ((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK ||
7543        alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED) &&
7544       thd->mdl_context.upgrade_shared_lock(table->mdl_ticket,
7545                                            MDL_SHARED_NO_WRITE,
7546                                            thd->variables.lock_wait_timeout))
7547   {
7548     goto cleanup;
7549   }
7550 
7551   // It's now safe to take the table level lock.
7552   if (lock_tables(thd, table_list, alter_ctx->tables_opened, 0))
7553     goto cleanup;
7554 
7555   if (alter_ctx->error_if_not_empty)
7556   {
7557     bool has_records= true;
7558     assert(table->mdl_ticket->get_type() == MDL_EXCLUSIVE);
7559     if (table_list->table->file->ha_table_flags() & HA_HAS_RECORDS)
7560     {
7561       ha_rows tmp= 0;
7562       if (!table_list->table->file->ha_records(&tmp) && tmp == 0)
7563         has_records= false;
7564     }
7565     else if(table_list->table->contains_records(thd, &has_records))
7566     {
7567       my_error(ER_INVALID_USE_OF_NULL, MYF(0));
7568       goto cleanup;
7569     }
7570 
7571     if (has_records)
7572     {
7573       if (alter_ctx->error_if_not_empty &
7574           Alter_table_ctx::GEOMETRY_WITHOUT_DEFAULT)
7575       {
7576         my_error(ER_INVALID_USE_OF_NULL, MYF(0));
7577       }
7578       else if ((alter_ctx->error_if_not_empty &
7579                 Alter_table_ctx::DATETIME_WITHOUT_DEFAULT) &&
7580                (thd->variables.sql_mode & MODE_NO_ZERO_DATE))
7581       {
7582         /*
7583           Report a warning if the NO ZERO DATE MODE is enabled. The
7584           warning will be promoted to an error if strict mode is
7585           also enabled.
7586         */
7587         push_zero_date_warning(thd, alter_ctx->datetime_field);
7588       }
7589 
7590       if (thd->is_error())
7591         goto cleanup;
7592     }
7593 
7594     // Empty table, so don't allow inserts during inplace operation.
7595     if (inplace_supported == HA_ALTER_INPLACE_NO_LOCK ||
7596         inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE)
7597       inplace_supported= HA_ALTER_INPLACE_SHARED_LOCK;
7598   }
7599 
7600   DEBUG_SYNC(thd, "alter_table_inplace_after_lock_upgrade");
7601   THD_STAGE_INFO(thd, stage_alter_inplace_prepare);
7602 
7603   switch (inplace_supported) {
7604   case HA_ALTER_ERROR:
7605   case HA_ALTER_INPLACE_NOT_SUPPORTED:
7606     assert(0);
7607     // fall through
7608   case HA_ALTER_INPLACE_NO_LOCK:
7609   case HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE:
7610     switch (alter_info->requested_lock) {
7611     case Alter_info::ALTER_TABLE_LOCK_DEFAULT:
7612     case Alter_info::ALTER_TABLE_LOCK_NONE:
7613       ha_alter_info->online= true;
7614       break;
7615     case Alter_info::ALTER_TABLE_LOCK_SHARED:
7616     case Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE:
7617       break;
7618     }
7619     break;
7620   case HA_ALTER_INPLACE_EXCLUSIVE_LOCK:
7621   case HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE:
7622   case HA_ALTER_INPLACE_SHARED_LOCK:
7623     break;
7624   }
7625 
7626   if (table->file->ha_prepare_inplace_alter_table(altered_table,
7627                                                   ha_alter_info))
7628   {
7629     goto rollback;
7630   }
7631 
7632   /*
7633     Downgrade the lock if storage engine has told us that exclusive lock was
7634     necessary only for prepare phase (unless we are not under LOCK TABLES) and
7635     user has not explicitly requested exclusive lock.
7636   */
7637   if ((inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
7638        inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE) &&
7639       !(thd->locked_tables_mode == LTM_LOCK_TABLES ||
7640         thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) &&
7641       (alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE))
7642   {
7643     /* If storage engine or user requested shared lock downgrade to SNW. */
7644     if (inplace_supported == HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE ||
7645         alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_SHARED)
7646       table->mdl_ticket->downgrade_lock(MDL_SHARED_NO_WRITE);
7647     else
7648     {
7649       assert(inplace_supported == HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE);
7650       table->mdl_ticket->downgrade_lock(MDL_SHARED_UPGRADABLE);
7651     }
7652   }
7653 
7654   DEBUG_SYNC(thd, "alter_table_inplace_after_lock_downgrade");
7655   THD_STAGE_INFO(thd, stage_alter_inplace);
7656 
7657   if (table->file->ha_inplace_alter_table(altered_table,
7658                                           ha_alter_info))
7659   {
7660     goto rollback;
7661   }
7662 
7663   // Upgrade to EXCLUSIVE before commit.
7664   if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
7665     goto rollback;
7666 
7667   /*
7668     If we are killed after this point, we should ignore and continue.
7669     We have mostly completed the operation at this point, there should
7670     be no long waits left.
7671   */
7672 
7673   DBUG_EXECUTE_IF("alter_table_rollback_new_index", {
7674       table->file->ha_commit_inplace_alter_table(altered_table,
7675                                                  ha_alter_info,
7676                                                  false);
7677       my_error(ER_UNKNOWN_ERROR, MYF(0));
7678       goto cleanup;
7679     });
7680 
7681   DEBUG_SYNC(thd, "alter_table_inplace_before_commit");
7682   THD_STAGE_INFO(thd, stage_alter_inplace_commit);
7683 
7684   /*
7685     Acquire SRO locks on parent tables to prevent concurrent DML on them to
7686     perform cascading actions. These actions require acquring InnoDB locks,
7687     which might otherwise create deadlock with locks acquired by
7688     ha_innobase::commit_inplace_alter_table(). This deadlock can be
7689     be resolved by aborting expensive ALTER TABLE statement, which
7690     we would like to avoid.
7691 
7692     Note that we ignore FOREIGN_KEY_CHECKS=0 setting completely here since
7693     we need to avoid deadlock even if user is ready to sacrifice some
7694     consistency and set FOREIGN_KEY_CHECKS=0.
7695 
7696     It is possible that acquisition of locks on parent tables will result
7697     in MDL deadlocks. But since deadlocks involving two or more DDL
7698     statements should be rare, it is unlikely that our ALTER TABLE will
7699     be aborted due to such deadlock.
7700   */
7701   if (lock_fk_dependent_tables(thd, table))
7702     goto rollback;
7703 
7704   if (table->file->ha_commit_inplace_alter_table(altered_table,
7705                                                  ha_alter_info,
7706                                                  true))
7707   {
7708     goto rollback;
7709   }
7710 
7711   close_all_tables_for_name(thd, table->s, alter_ctx->is_table_renamed(), NULL);
7712   table_list->table= table= NULL;
7713   close_temporary_table(thd, altered_table, true, false);
7714 
7715   /*
7716     Replace the old .FRM with the new .FRM, but keep the old name for now.
7717     Rename to the new name (if needed) will be handled separately below.
7718   */
7719   if (mysql_rename_table(create_info->db_type, alter_ctx->new_db,
7720                          alter_ctx->tmp_name, alter_ctx->db, alter_ctx->alias,
7721                          FN_FROM_IS_TMP | NO_HA_TABLE))
7722   {
7723     // Since changes were done in-place, we can't revert them.
7724     (void) quick_rm_table(thd, create_info->db_type,
7725                           alter_ctx->new_db, alter_ctx->tmp_name,
7726                           FN_IS_TMP | NO_HA_TABLE);
7727     DBUG_RETURN(true);
7728   }
7729 
7730   table_list->mdl_request.ticket= mdl_ticket;
7731   if (open_table(thd, table_list, &ot_ctx))
7732     DBUG_RETURN(true);
7733 
7734   /*
7735     Tell the handler that the changed frm is on disk and table
7736     has been re-opened
7737   */
7738   table_list->table->file->ha_notify_table_changed();
7739 
7740   /*
7741     We might be going to reopen table down on the road, so we have to
7742     restore state of the TABLE object which we used for obtaining of
7743     handler object to make it usable for later reopening.
7744   */
7745   close_thread_table(thd, &thd->open_tables);
7746   table_list->table= NULL;
7747 
7748   // Rename altered table if requested.
7749   if (alter_ctx->is_table_renamed())
7750   {
7751     // Remove TABLE and TABLE_SHARE for old name from TDC.
7752     tdc_remove_table(thd, TDC_RT_REMOVE_ALL,
7753                      alter_ctx->db, alter_ctx->table_name, false);
7754 
7755     if (mysql_rename_table(create_info->db_type, alter_ctx->db,
7756                            alter_ctx->table_name,
7757                            alter_ctx->new_db, alter_ctx->new_alias, 0))
7758     {
7759       /*
7760         If the rename fails we will still have a working table
7761         with the old name, but with other changes applied.
7762       */
7763       DBUG_RETURN(true);
7764     }
7765     if (change_trigger_table_name(thd,
7766                                   alter_ctx->db,
7767                                   alter_ctx->alias,
7768                                   alter_ctx->table_name,
7769                                   alter_ctx->new_db,
7770                                   alter_ctx->new_alias))
7771     {
7772       /*
7773         If the rename of trigger files fails, try to rename the table
7774         back so we at least have matching table and trigger files.
7775       */
7776       (void) mysql_rename_table(create_info->db_type,
7777                                 alter_ctx->new_db, alter_ctx->new_alias,
7778                                 alter_ctx->db, alter_ctx->alias, NO_FK_CHECKS);
7779       DBUG_RETURN(true);
7780     }
7781   }
7782 
7783   DBUG_RETURN(false);
7784 
7785  rollback:
7786   table->file->ha_commit_inplace_alter_table(altered_table,
7787                                              ha_alter_info,
7788                                              false);
7789  cleanup:
7790   if (reopen_tables)
7791   {
7792     /* Close the only table instance which is still around. */
7793     close_all_tables_for_name(thd, table->s, alter_ctx->is_table_renamed(), NULL);
7794     if (thd->locked_tables_list.reopen_tables(thd))
7795       thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
7796     /* QQ; do something about metadata locks ? */
7797   }
7798   close_temporary_table(thd, altered_table, true, false);
7799   // Delete temporary .frm/.par
7800   (void) quick_rm_table(thd, create_info->db_type, alter_ctx->new_db,
7801                         alter_ctx->tmp_name, FN_IS_TMP | NO_HA_TABLE);
7802   DBUG_RETURN(true);
7803 }
7804 
7805 /**
7806   maximum possible length for certain blob types.
7807 
7808   @param[in]      type        Blob type (e.g. MYSQL_TYPE_TINY_BLOB)
7809 
7810   @return
7811     length
7812 */
7813 
7814 static uint
blob_length_by_type(enum_field_types type)7815 blob_length_by_type(enum_field_types type)
7816 {
7817   switch (type)
7818   {
7819   case MYSQL_TYPE_TINY_BLOB:
7820     return 255;
7821   case MYSQL_TYPE_BLOB:
7822     return 65535;
7823   case MYSQL_TYPE_MEDIUM_BLOB:
7824     return 16777215;
7825   case MYSQL_TYPE_LONG_BLOB:
7826     return 4294967295U;
7827   default:
7828     assert(0); // we should never go here
7829     return 0;
7830   }
7831 }
7832 
7833 
7834 /**
7835   Convert the old temporal data types to the new temporal
7836   type format for ADD/CHANGE COLUMN, ADD INDEXES and ALTER
7837   FORCE ALTER operation.
7838 
7839   @param thd                Thread context.
7840   @param alter_info         Alter info parameters.
7841 
7842   @retval true              Error.
7843   @retval false             Either the old temporal data types
7844                             are not present or they are present
7845                             and have been successfully upgraded.
7846 */
7847 
7848 static bool
upgrade_old_temporal_types(THD * thd,Alter_info * alter_info)7849 upgrade_old_temporal_types(THD *thd, Alter_info *alter_info)
7850 {
7851   bool old_temporal_type_present= false;
7852 
7853   DBUG_ENTER("upgrade_old_temporal_types");
7854 
7855   if (!((alter_info->flags & Alter_info::ALTER_ADD_COLUMN) ||
7856       (alter_info->flags & Alter_info::ALTER_ADD_INDEX) ||
7857       (alter_info->flags & Alter_info::ALTER_CHANGE_COLUMN) ||
7858       (alter_info->flags & Alter_info::ALTER_RECREATE)))
7859     DBUG_RETURN(false);
7860 
7861   /*
7862     Upgrade the old temporal types if any, for ADD/CHANGE COLUMN/
7863     ADD INDEXES and FORCE ALTER operation.
7864   */
7865   Create_field *def;
7866   List_iterator<Create_field> create_it(alter_info->create_list);
7867 
7868   while ((def= create_it++))
7869   {
7870     // Check if any old temporal type is present.
7871     if ((def->sql_type == MYSQL_TYPE_TIME) ||
7872         (def->sql_type == MYSQL_TYPE_DATETIME) ||
7873         (def->sql_type == MYSQL_TYPE_TIMESTAMP))
7874     {
7875        old_temporal_type_present= true;
7876        break;
7877     }
7878   }
7879 
7880   // Upgrade is not required since there are no old temporal types.
7881   if (!old_temporal_type_present)
7882     DBUG_RETURN(false);
7883 
7884   // Upgrade old temporal types to the new temporal types.
7885   create_it.rewind();
7886   while ((def= create_it++))
7887   {
7888     enum  enum_field_types sql_type;
7889     Item *default_value= def->def, *update_value= NULL;
7890 
7891     /*
7892        Set CURRENT_TIMESTAMP as default/update value based on
7893        the unireg_check value.
7894     */
7895 
7896     if ((def->sql_type == MYSQL_TYPE_DATETIME ||
7897          def->sql_type == MYSQL_TYPE_TIMESTAMP)
7898         && (def->unireg_check != Field::NONE))
7899     {
7900       Item_func_now_local *now = new (thd->mem_root) Item_func_now_local(0);
7901       if (!now)
7902         DBUG_RETURN(true);
7903 
7904       if (def->unireg_check == Field::TIMESTAMP_DN_FIELD)
7905         default_value= now;
7906       else if (def->unireg_check == Field::TIMESTAMP_UN_FIELD)
7907         update_value= now;
7908       else if (def->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
7909       {
7910         update_value= now;
7911         default_value= now;
7912       }
7913     }
7914 
7915     switch (def->sql_type)
7916     {
7917     case MYSQL_TYPE_TIME:
7918         sql_type= MYSQL_TYPE_TIME2;
7919         break;
7920     case MYSQL_TYPE_DATETIME:
7921         sql_type= MYSQL_TYPE_DATETIME2;
7922         break;
7923     case MYSQL_TYPE_TIMESTAMP:
7924         sql_type= MYSQL_TYPE_TIMESTAMP2;
7925         break;
7926     default:
7927       continue;
7928     }
7929 
7930     assert(!def->gcol_info ||
7931            (def->gcol_info  &&
7932             (def->sql_type != MYSQL_TYPE_DATETIME
7933              || def->sql_type != MYSQL_TYPE_TIMESTAMP)));
7934     // Replace the old temporal field with the new temporal field.
7935     Create_field *temporal_field= NULL;
7936     if (!(temporal_field= new (thd->mem_root) Create_field()) ||
7937         temporal_field->init(thd, def->field_name, sql_type, NULL, NULL,
7938                              (def->flags & NOT_NULL_FLAG), default_value,
7939                              update_value, &def->comment, def->change, NULL,
7940                              NULL, 0, NULL))
7941       DBUG_RETURN(true);
7942 
7943     temporal_field->field= def->field;
7944     create_it.replace(temporal_field);
7945   }
7946 
7947   // Report a NOTE informing about the upgrade.
7948   push_warning(thd, Sql_condition::SL_NOTE,
7949                ER_OLD_TEMPORALS_UPGRADED, ER(ER_OLD_TEMPORALS_UPGRADED));
7950   DBUG_RETURN(false);
7951 }
7952 
7953 
7954 /**
7955   Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
7956 
7957   This function transforms parse output of ALTER TABLE - lists of
7958   columns and keys to add, drop or modify into, essentially,
7959   CREATE TABLE definition - a list of columns and keys of the new
7960   table. While doing so, it also performs some (bug not all)
7961   semantic checks.
7962 
7963   This function is invoked when we know that we're going to
7964   perform ALTER TABLE via a temporary table -- i.e. in-place ALTER TABLE
7965   is not possible, perhaps because the ALTER statement contains
7966   instructions that require change in table data, not only in
7967   table definition or indexes.
7968 
7969   @param[in,out]  thd         thread handle. Used as a memory pool
7970                               and source of environment information.
7971   @param[in]      table       the source table, open and locked
7972                               Used as an interface to the storage engine
7973                               to acquire additional information about
7974                               the original table.
7975   @param[in,out]  create_info A blob with CREATE/ALTER TABLE
7976                               parameters
7977   @param[in,out]  alter_info  Another blob with ALTER/CREATE parameters.
7978                               Originally create_info was used only in
7979                               CREATE TABLE and alter_info only in ALTER TABLE.
7980                               But since ALTER might end-up doing CREATE,
7981                               this distinction is gone and we just carry
7982                               around two structures.
7983   @param[in,out]  alter_ctx   Runtime context for ALTER TABLE.
7984 
7985   @return
7986     Fills various create_info members based on information retrieved
7987     from the storage engine.
7988     Sets create_info->varchar if the table has a VARCHAR column.
7989     Prepares alter_info->create_list and alter_info->key_list with
7990     columns and keys of the new table.
7991   @retval TRUE   error, out of memory or a semantical error in ALTER
7992                  TABLE instructions
7993   @retval FALSE  success
7994 */
7995 
7996 bool
mysql_prepare_alter_table(THD * thd,TABLE * table,HA_CREATE_INFO * create_info,Alter_info * alter_info,Alter_table_ctx * alter_ctx)7997 mysql_prepare_alter_table(THD *thd, TABLE *table,
7998                           HA_CREATE_INFO *create_info,
7999                           Alter_info *alter_info,
8000                           Alter_table_ctx *alter_ctx)
8001 {
8002   /* New column definitions are added here */
8003   List<Create_field> new_create_list;
8004   /* New key definitions are added here */
8005   List<Key> new_key_list;
8006   // DROP instructions for foreign keys and virtual generated columns
8007   List<Alter_drop> new_drop_list;
8008   /*
8009     Alter_info::alter_rename_key_list is also used by fill_alter_inplace_info()
8010     call. So this function should not modify original list but rather work with
8011     its copy.
8012   */
8013   List<Alter_rename_key> rename_key_list(alter_info->alter_rename_key_list,
8014                                          thd->mem_root);
8015   List_iterator<Alter_drop> drop_it(alter_info->drop_list);
8016   List_iterator<Create_field> def_it(alter_info->create_list);
8017   List_iterator<Alter_column> alter_it(alter_info->alter_list);
8018   List_iterator<Key> key_it(alter_info->key_list);
8019   List_iterator<Create_field> find_it(new_create_list);
8020   List_iterator<Create_field> field_it(new_create_list);
8021   List<Key_part_spec> key_parts;
8022   uint db_create_options= (table->s->db_create_options
8023                            & ~(HA_OPTION_PACK_RECORD));
8024   uint used_fields= create_info->used_fields;
8025   KEY *key_info=table->key_info;
8026   bool rc= true;
8027 
8028   DBUG_ENTER("mysql_prepare_alter_table");
8029 
8030   create_info->varchar= FALSE;
8031   /* Let new create options override the old ones */
8032   if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
8033     create_info->min_rows= table->s->min_rows;
8034   if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
8035     create_info->max_rows= table->s->max_rows;
8036   if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
8037     create_info->avg_row_length= table->s->avg_row_length;
8038   if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
8039     create_info->default_table_charset= table->s->table_charset;
8040   if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
8041   {
8042     /* Table has an autoincrement, copy value to new table */
8043     table->file->info(HA_STATUS_AUTO);
8044     create_info->auto_increment_value= table->file->stats.auto_increment_value;
8045   }
8046   if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
8047     create_info->key_block_size= table->s->key_block_size;
8048 
8049   if (!(used_fields & HA_CREATE_USED_STATS_SAMPLE_PAGES))
8050     create_info->stats_sample_pages= table->s->stats_sample_pages;
8051 
8052   if (!(used_fields & HA_CREATE_USED_STATS_AUTO_RECALC))
8053     create_info->stats_auto_recalc= table->s->stats_auto_recalc;
8054 
8055   if (!(used_fields & HA_CREATE_USED_TABLESPACE))
8056     create_info->tablespace= table->s->tablespace;
8057 
8058   if (create_info->storage_media == HA_SM_DEFAULT)
8059     create_info->storage_media= table->s->default_storage_media;
8060 
8061   /* Creation of federated table with LIKE clause needs connection string */
8062   if (!(used_fields & HA_CREATE_USED_CONNECTION))
8063     create_info->connect_string= table->s->connect_string;
8064 
8065   restore_record(table, s->default_values);     // Empty record for DEFAULT
8066   Create_field *def;
8067 
8068   /*
8069     First collect all fields from table which isn't in drop_list
8070   */
8071   Field **f_ptr,*field;
8072   for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
8073   {
8074     if (field->type() == MYSQL_TYPE_STRING)
8075       create_info->varchar= TRUE;
8076     /* Check if field should be dropped */
8077     Alter_drop *drop;
8078     drop_it.rewind();
8079     while ((drop=drop_it++))
8080     {
8081       if (drop->type == Alter_drop::COLUMN &&
8082 	  !my_strcasecmp(system_charset_info,field->field_name, drop->name))
8083       {
8084 	/* Reset auto_increment value if it was dropped */
8085 	if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
8086 	    !(used_fields & HA_CREATE_USED_AUTO))
8087 	{
8088 	  create_info->auto_increment_value=0;
8089 	  create_info->used_fields|=HA_CREATE_USED_AUTO;
8090 	}
8091         /*
8092           If a generated column is dependent on this column, this column
8093           cannot be dropped.
8094         */
8095         if (table->vfield &&
8096             table->is_field_used_by_generated_columns(field->field_index))
8097         {
8098           my_error(ER_DEPENDENT_BY_GENERATED_COLUMN, MYF(0), field->field_name);
8099           goto err;
8100         }
8101 
8102         /*
8103           Mark the drop_column operation is on virtual GC so that a non-rebuild
8104           on table can be done.
8105         */
8106         if (field->is_virtual_gcol())
8107           new_drop_list.push_back(drop);
8108 	break; // Column was found.
8109       }
8110     }
8111     if (drop)
8112     {
8113       drop_it.remove();
8114       continue;
8115     }
8116     /* Check if field is changed */
8117     def_it.rewind();
8118     while ((def=def_it++))
8119     {
8120       if (def->change &&
8121 	  !my_strcasecmp(system_charset_info,field->field_name, def->change))
8122 	break;
8123     }
8124     if (def)
8125     {						// Field is changed
8126       def->field=field;
8127       if (field->stored_in_db != def->stored_in_db)
8128       {
8129         my_error(ER_UNSUPPORTED_ACTION_ON_GENERATED_COLUMN,
8130                  MYF(0),
8131                  "Changing the STORED status");
8132         goto err;
8133       }
8134       /*
8135         Add column being updated to the list of new columns.
8136         Note that columns with AFTER clauses are added to the end
8137         of the list for now. Their positions will be corrected later.
8138       */
8139       new_create_list.push_back(def);
8140       if (!def->after)
8141       {
8142         /*
8143           If this ALTER TABLE doesn't have an AFTER clause for the modified
8144           column then remove this column from the list of columns to be
8145           processed. So later we can iterate over the columns remaining
8146           in this list and process modified columns with AFTER clause or
8147           add new columns.
8148         */
8149         def_it.remove();
8150       }
8151       /*
8152         If the new column type is GEOMETRY (or a subtype) NOT NULL,
8153         and the old column type is nullable and not GEOMETRY (or a
8154         subtype), existing NULL values will be converted into empty
8155         strings in non-strict mode. Empty strings are illegal values
8156         in GEOMETRY columns.
8157       */
8158       if (def->sql_type == MYSQL_TYPE_GEOMETRY &&
8159           (def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
8160           field->type() != MYSQL_TYPE_GEOMETRY &&
8161           field->maybe_null() &&
8162           !thd->is_strict_mode())
8163       {
8164         alter_ctx->error_if_not_empty|=
8165           Alter_table_ctx::GEOMETRY_WITHOUT_DEFAULT;
8166       }
8167     }
8168     else
8169     {
8170       /*
8171         This field was not dropped and not changed, add it to the list
8172         for the new table.
8173       */
8174       def= new Create_field(field, field);
8175       new_create_list.push_back(def);
8176       alter_it.rewind();			// Change default if ALTER
8177       Alter_column *alter;
8178       while ((alter=alter_it++))
8179       {
8180 	if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
8181 	  break;
8182       }
8183       if (alter)
8184       {
8185 	if (def->flags & BLOB_FLAG)
8186 	{
8187 	  my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), field->field_name);
8188           goto err;
8189 	}
8190 
8191 	if ((def->def=alter->def))              // Use new default
8192         {
8193           def->flags&= ~NO_DEFAULT_VALUE_FLAG;
8194           /*
8195             The defaults are explicitly altered for the TIMESTAMP/DATETIME
8196             field, through SET DEFAULT. Hence, set the unireg check
8197             appropriately.
8198           */
8199           if (real_type_with_now_as_default(def->sql_type))
8200           {
8201             if (def->unireg_check == Field::TIMESTAMP_DNUN_FIELD)
8202               def->unireg_check= Field::TIMESTAMP_UN_FIELD;
8203             else if (def->unireg_check == Field::TIMESTAMP_DN_FIELD)
8204               def->unireg_check= Field::NONE;
8205           }
8206         }
8207         else
8208           def->flags|= NO_DEFAULT_VALUE_FLAG;
8209 
8210 	alter_it.remove();
8211       }
8212     }
8213   }
8214   def_it.rewind();
8215   while ((def=def_it++))			// Add new columns
8216   {
8217     if (def->change && ! def->field)
8218     {
8219       my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
8220       goto err;
8221     }
8222 
8223     /*
8224       New columns of type DATE/DATETIME/GEOMETRIC with NOT NULL constraint
8225       added as part of ALTER operation will generate zero date for DATE/
8226       DATETIME types and empty string for GEOMETRIC types when the table
8227       is not empty. Hence certain additional checks needs to be performed
8228       as described below. This cannot be caught by SE(For INPLACE ALTER)
8229       since it checks for only NULL value. Zero date and empty string
8230       does not violate the NOT NULL value constraint.
8231     */
8232     if (!def->change)
8233     {
8234       /*
8235         Check that the DATE/DATETIME not null field we are going to add is
8236         either has a default value or the '0000-00-00' is allowed by the
8237         set sql mode.
8238         If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
8239         flag to allow ALTER TABLE only if the table to be altered is empty.
8240       */
8241       if ((def->sql_type == MYSQL_TYPE_DATE ||
8242            def->sql_type == MYSQL_TYPE_NEWDATE ||
8243            def->sql_type == MYSQL_TYPE_DATETIME ||
8244            def->sql_type == MYSQL_TYPE_DATETIME2) &&
8245           !alter_ctx->datetime_field &&
8246           !(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)))
8247       {
8248         alter_ctx->datetime_field= def;
8249         alter_ctx->error_if_not_empty|=
8250           Alter_table_ctx::DATETIME_WITHOUT_DEFAULT;
8251       }
8252 
8253       /*
8254         New GEOMETRY (and subtypes) columns can't be NOT NULL. To add a
8255         GEOMETRY NOT NULL column, first create a GEOMETRY NULL column,
8256         UPDATE the table to set a different value than NULL, and then do
8257         a ALTER TABLE MODIFY COLUMN to set NOT NULL.
8258 
8259         This restriction can be lifted once MySQL supports default
8260         values (i.e., functions) for geometry columns. The new
8261         restriction would then be for added GEOMETRY NOT NULL columns to
8262         always have a provided default value.
8263       */
8264       if (def->sql_type == MYSQL_TYPE_GEOMETRY &&
8265           (def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)))
8266       {
8267         alter_ctx->error_if_not_empty|= Alter_table_ctx::GEOMETRY_WITHOUT_DEFAULT;
8268       }
8269     }
8270 
8271     if (!def->after)
8272       new_create_list.push_back(def);
8273     else
8274     {
8275       Create_field *find;
8276       if (def->change)
8277       {
8278         find_it.rewind();
8279         /*
8280           For columns being modified with AFTER clause we should first remove
8281           these columns from the list and then add them back at their correct
8282           positions.
8283         */
8284         while ((find=find_it++))
8285         {
8286           /*
8287             Create_fields representing changed columns are added directly
8288             from Alter_info::create_list to new_create_list. We can therefore
8289             safely use pointer equality rather than name matching here.
8290             This prevents removing the wrong column in case of column rename.
8291           */
8292           if (find == def)
8293           {
8294             find_it.remove();
8295             break;
8296           }
8297         }
8298       }
8299       if (def->after == first_keyword)
8300         new_create_list.push_front(def);
8301       else
8302       {
8303         find_it.rewind();
8304         while ((find=find_it++))
8305         {
8306           if (!my_strcasecmp(system_charset_info, def->after, find->field_name))
8307             break;
8308         }
8309         if (!find)
8310         {
8311           my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
8312           goto err;
8313         }
8314         find_it.after(def);			// Put column after this
8315       }
8316     }
8317   }
8318   if (alter_info->alter_list.elements)
8319   {
8320     my_error(ER_BAD_FIELD_ERROR, MYF(0),
8321              alter_info->alter_list.head()->name, table->s->table_name.str);
8322     goto err;
8323   }
8324   if (!new_create_list.elements)
8325   {
8326     my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
8327                MYF(0));
8328     goto err;
8329   }
8330 
8331   /*
8332     Collect all keys which isn't in drop list. Add only those
8333     for which some fields exists.
8334   */
8335 
8336   for (uint i=0 ; i < table->s->keys ; i++,key_info++)
8337   {
8338     const char *key_name= key_info->name;
8339     bool index_column_dropped= false;
8340     Alter_drop *drop;
8341     drop_it.rewind();
8342     while ((drop=drop_it++))
8343     {
8344       if (drop->type == Alter_drop::KEY &&
8345 	  !my_strcasecmp(system_charset_info,key_name, drop->name))
8346 	break;
8347     }
8348     if (drop)
8349     {
8350       drop_it.remove();
8351       continue;
8352     }
8353 
8354     KEY_PART_INFO *key_part= key_info->key_part;
8355     key_parts.empty();
8356     for (uint j=0 ; j < key_info->user_defined_key_parts ; j++,key_part++)
8357     {
8358       if (!key_part->field)
8359 	continue;				// Wrong field (from UNIREG)
8360       const char *key_part_name=key_part->field->field_name;
8361       Create_field *cfield;
8362       field_it.rewind();
8363       while ((cfield=field_it++))
8364       {
8365 	if (cfield->change)
8366 	{
8367 	  if (!my_strcasecmp(system_charset_info, key_part_name,
8368 			     cfield->change))
8369 	    break;
8370 	}
8371 	else if (!my_strcasecmp(system_charset_info,
8372 				key_part_name, cfield->field_name))
8373 	  break;
8374       }
8375       if (!cfield)
8376       {
8377         /*
8378            We are dropping a column associated with an index.
8379         */
8380         index_column_dropped= true;
8381 	continue;				// Field is removed
8382       }
8383       uint key_part_length=key_part->length;
8384       if (cfield->field)			// Not new field
8385       {
8386         /*
8387           If the field can't have only a part used in a key according to its
8388           new type, or should not be used partially according to its
8389           previous type, or the field length is less than the key part
8390           length, unset the key part length.
8391 
8392           We also unset the key part length if it is the same as the
8393           old field's length, so the whole new field will be used.
8394 
8395           BLOBs may have cfield->length == 0, which is why we test it before
8396           checking whether cfield->length < key_part_length (in chars).
8397 
8398           In case of TEXTs we check the data type maximum length *in bytes*
8399           to key part length measured *in characters* (i.e. key_part_length
8400           devided to mbmaxlen). This is because it's OK to have:
8401           CREATE TABLE t1 (a tinytext, key(a(254)) character set utf8);
8402           In case of this example:
8403           - data type maximum length is 255.
8404           - key_part_length is 1016 (=254*4, where 4 is mbmaxlen)
8405          */
8406         if (!Field::type_can_have_key_part(cfield->field->type()) ||
8407             !Field::type_can_have_key_part(cfield->sql_type) ||
8408             /* spatial keys can't have sub-key length */
8409             (key_info->flags & HA_SPATIAL) ||
8410             (cfield->field->field_length == key_part_length &&
8411              !f_is_blob(key_part->key_type)) ||
8412             (cfield->length && (((cfield->sql_type >= MYSQL_TYPE_TINY_BLOB &&
8413                                   cfield->sql_type <= MYSQL_TYPE_BLOB) ?
8414                                 blob_length_by_type(cfield->sql_type) :
8415                                 cfield->length) <
8416 	     key_part_length / key_part->field->charset()->mbmaxlen)))
8417 	  key_part_length= 0;			// Use whole field
8418       }
8419       key_part_length /= key_part->field->charset()->mbmaxlen;
8420       key_parts.push_back(new Key_part_spec(cfield->field_name,
8421                                             strlen(cfield->field_name),
8422 					    key_part_length));
8423     }
8424     if (key_parts.elements)
8425     {
8426       KEY_CREATE_INFO key_create_info;
8427       Key *key;
8428       keytype key_type;
8429       memset(&key_create_info, 0, sizeof(key_create_info));
8430 
8431       /* If this index is to stay in the table check if it has to be renamed. */
8432       List_iterator<Alter_rename_key> rename_key_it(rename_key_list);
8433       Alter_rename_key *rename_key;
8434 
8435       while ((rename_key= rename_key_it++))
8436       {
8437         if (! my_strcasecmp(system_charset_info, key_name,
8438                             rename_key->old_name))
8439         {
8440           if (! my_strcasecmp(system_charset_info, key_name,
8441                               primary_key_name))
8442           {
8443             my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->old_name);
8444             goto err;
8445           }
8446           else if (! my_strcasecmp(system_charset_info, rename_key->new_name,
8447                                    primary_key_name))
8448           {
8449             my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), rename_key->new_name);
8450             goto err;
8451           }
8452 
8453           key_name= rename_key->new_name;
8454           rename_key_it.remove();
8455           /*
8456             If the user has explicitly renamed the key, we should no longer
8457             treat it as generated. Otherwise this key might be automatically
8458             dropped by mysql_prepare_create_table() and this will confuse
8459             code in fill_alter_inplace_info().
8460           */
8461           key_info->flags &= ~HA_GENERATED_KEY;
8462           break;
8463         }
8464       }
8465 
8466       key_create_info.algorithm= key_info->algorithm;
8467       if (key_info->flags & HA_USES_BLOCK_SIZE)
8468         key_create_info.block_size= key_info->block_size;
8469       if (key_info->flags & HA_USES_PARSER)
8470         key_create_info.parser_name= *plugin_name(key_info->parser);
8471       if (key_info->flags & HA_USES_COMMENT)
8472         key_create_info.comment= key_info->comment;
8473 
8474       if (key_info->flags & HA_SPATIAL)
8475         key_type= KEYTYPE_SPATIAL;
8476       else if (key_info->flags & HA_NOSAME)
8477       {
8478         if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
8479           key_type= KEYTYPE_PRIMARY;
8480         else
8481           key_type= KEYTYPE_UNIQUE;
8482       }
8483       else if (key_info->flags & HA_FULLTEXT)
8484         key_type= KEYTYPE_FULLTEXT;
8485       else
8486         key_type= KEYTYPE_MULTIPLE;
8487 
8488       if (index_column_dropped)
8489       {
8490         /*
8491            We have dropped a column associated with an index,
8492            this warrants a check for duplicate indexes
8493         */
8494         key_create_info.check_for_duplicate_indexes= true;
8495       }
8496 
8497       key= new Key(key_type, key_name, strlen(key_name),
8498                    &key_create_info,
8499                    MY_TEST(key_info->flags & HA_GENERATED_KEY),
8500                    key_parts);
8501       new_key_list.push_back(key);
8502     }
8503   }
8504   {
8505     Key *key;
8506     while ((key=key_it++))			// Add new keys
8507     {
8508       if (key->type == KEYTYPE_FOREIGN &&
8509           ((Foreign_key *)key)->validate(new_create_list))
8510         goto err;
8511       new_key_list.push_back(key);
8512       if (key->name.str &&
8513 	  !my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
8514       {
8515 	my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
8516         goto err;
8517       }
8518     }
8519   }
8520 
8521   if (alter_info->drop_list.elements)
8522   {
8523     // Now this contains only DROP for foreign keys and not-found objects
8524     Alter_drop *drop;
8525     drop_it.rewind();
8526     while ((drop=drop_it++)) {
8527       switch (drop->type) {
8528       case Alter_drop::KEY:
8529       case Alter_drop::COLUMN:
8530         my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
8531                  alter_info->drop_list.head()->name);
8532         goto err;
8533       case Alter_drop::FOREIGN_KEY:
8534         break;
8535       default:
8536         assert(false);
8537         break;
8538       }
8539     }
8540     // new_drop_list has DROP for virtual generated columns; add foreign keys:
8541     new_drop_list.concat(&alter_info->drop_list);
8542   }
8543   if (rename_key_list.elements)
8544   {
8545     my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), rename_key_list.head()->old_name,
8546              table->s->table_name.str);
8547     goto err;
8548   }
8549 
8550   if (!create_info->comment.str)
8551   {
8552     create_info->comment.str= table->s->comment.str;
8553     create_info->comment.length= table->s->comment.length;
8554   }
8555 
8556   if (!create_info->compress.str)
8557   {
8558     create_info->compress.str= table->s->compress.str;
8559     create_info->compress.length= table->s->compress.length;
8560   }
8561 
8562   if (!create_info->encrypt_type.str)
8563   {
8564     create_info->encrypt_type.str= table->s->encrypt_type.str;
8565     create_info->encrypt_type.length= table->s->encrypt_type.length;
8566   }
8567 
8568   /* Do not pass the update_create_info through to each partition. */
8569   if (table->file->ht->db_type == DB_TYPE_PARTITION_DB)
8570 	  create_info->data_file_name = (char*) -1;
8571 
8572   table->file->update_create_info(create_info);
8573   if ((create_info->table_options &
8574        (HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
8575       (used_fields & HA_CREATE_USED_PACK_KEYS))
8576     db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
8577   if ((create_info->table_options &
8578        (HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT)) ||
8579       (used_fields & HA_CREATE_USED_STATS_PERSISTENT))
8580     db_create_options&= ~(HA_OPTION_STATS_PERSISTENT | HA_OPTION_NO_STATS_PERSISTENT);
8581   if (create_info->table_options &
8582       (HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
8583     db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
8584   if (create_info->table_options &
8585       (HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
8586     db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
8587 			  HA_OPTION_NO_DELAY_KEY_WRITE);
8588   create_info->table_options|= db_create_options;
8589 
8590   if (table->s->tmp_table)
8591     create_info->options|=HA_LEX_CREATE_TMP_TABLE;
8592 
8593   rc= false;
8594   alter_info->create_list.swap(new_create_list);
8595   alter_info->key_list.swap(new_key_list);
8596   alter_info->drop_list.swap(new_drop_list);
8597 err:
8598   DBUG_RETURN(rc);
8599 }
8600 
8601 
8602 /**
8603   Get Create_field object for newly created table by its name
8604   in the old version of table.
8605 
8606   @param alter_info  Alter_info describing newly created table.
8607   @param old_name    Name of field in old table.
8608 
8609   @returns Pointer to Create_field object, NULL - if field is
8610            not present in new version of table.
8611 */
8612 
get_field_by_old_name(Alter_info * alter_info,const char * old_name)8613 static Create_field *get_field_by_old_name(Alter_info *alter_info,
8614                                            const char *old_name)
8615 {
8616   List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
8617   Create_field *new_field;
8618 
8619   while ((new_field= new_field_it++))
8620   {
8621     if (new_field->field &&
8622         (my_strcasecmp(system_charset_info,
8623                        new_field->field->field_name,
8624                        old_name) == 0))
8625       break;
8626   }
8627   return new_field;
8628 }
8629 
8630 
8631 /** Type of change to foreign key column, */
8632 
8633 enum fk_column_change_type
8634 {
8635   FK_COLUMN_NO_CHANGE, FK_COLUMN_DATA_CHANGE,
8636   FK_COLUMN_RENAMED, FK_COLUMN_DROPPED
8637 };
8638 
8639 
8640 /**
8641   Check that ALTER TABLE's changes on columns of a foreign key are allowed.
8642 
8643   @param[in]   thd              Thread context.
8644   @param[in]   alter_info       Alter_info describing changes to be done
8645                                 by ALTER TABLE.
8646   @param[in]   fk_columns       List of columns of the foreign key to check.
8647   @param[out]  bad_column_name  Name of field on which ALTER TABLE tries to
8648                                 do prohibited operation.
8649 
8650   @note This function takes into account value of @@foreign_key_checks
8651         setting.
8652 
8653   @retval FK_COLUMN_NO_CHANGE    No significant changes are to be done on
8654                                  foreign key columns.
8655   @retval FK_COLUMN_DATA_CHANGE  ALTER TABLE might result in value
8656                                  change in foreign key column (and
8657                                  foreign_key_checks is on).
8658   @retval FK_COLUMN_RENAMED      Foreign key column is renamed.
8659   @retval FK_COLUMN_DROPPED      Foreign key column is dropped.
8660 */
8661 
8662 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)8663 fk_check_column_changes(THD *thd, Alter_info *alter_info,
8664                         List<LEX_STRING> &fk_columns,
8665                         const char **bad_column_name)
8666 {
8667   List_iterator_fast<LEX_STRING> column_it(fk_columns);
8668   LEX_STRING *column;
8669 
8670   *bad_column_name= NULL;
8671 
8672   while ((column= column_it++))
8673   {
8674     Create_field *new_field= get_field_by_old_name(alter_info, column->str);
8675 
8676     if (new_field)
8677     {
8678       Field *old_field= new_field->field;
8679 
8680       if (my_strcasecmp(system_charset_info, old_field->field_name,
8681                         new_field->field_name))
8682       {
8683         /*
8684           Copy algorithm doesn't support proper renaming of columns in
8685           the foreign key yet. At the moment we lack API which will tell
8686           SE that foreign keys should be updated to use new name of column
8687           like it happens in case of in-place algorithm.
8688         */
8689         *bad_column_name= column->str;
8690         return FK_COLUMN_RENAMED;
8691       }
8692 
8693       if ((old_field->is_equal(new_field) == IS_EQUAL_NO) ||
8694           ((new_field->flags & NOT_NULL_FLAG) &&
8695            !(old_field->flags & NOT_NULL_FLAG)))
8696       {
8697         if (!(thd->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS))
8698         {
8699           /*
8700             Column in a FK has changed significantly. Unless
8701             foreign_key_checks are off we prohibit this since this
8702             means values in this column might be changed by ALTER
8703             and thus referential integrity might be broken,
8704           */
8705           *bad_column_name= column->str;
8706           return FK_COLUMN_DATA_CHANGE;
8707         }
8708       }
8709       assert(old_field->is_gcol() == new_field->is_gcol() &&
8710              old_field->is_virtual_gcol() == new_field->is_virtual_gcol());
8711       assert(!old_field->is_gcol() ||
8712              old_field->gcol_expr_is_equal(new_field));
8713     }
8714     else
8715     {
8716       /*
8717         Column in FK was dropped. Most likely this will break
8718         integrity constraints of InnoDB data-dictionary (and thus
8719         InnoDB will emit an error), so we prohibit this right away
8720         even if foreign_key_checks are off.
8721         This also includes a rare case when another field replaces
8722         field being dropped since it is easy to break referential
8723         integrity in this case.
8724       */
8725       *bad_column_name= column->str;
8726       return FK_COLUMN_DROPPED;
8727     }
8728   }
8729 
8730   return FK_COLUMN_NO_CHANGE;
8731 }
8732 
8733 
8734 /**
8735   Check if ALTER TABLE we are about to execute using COPY algorithm
8736   is not supported as it might break referential integrity.
8737 
8738   @note If foreign_key_checks is disabled (=0), we allow to break
8739         referential integrity. But we still disallow some operations
8740         like dropping or renaming columns in foreign key since they
8741         are likely to break consistency of InnoDB data-dictionary
8742         and thus will end-up in error anyway.
8743 
8744   @param[in]  thd          Thread context.
8745   @param[in]  table        Table to be altered.
8746   @param[in]  alter_info   Lists of fields, keys to be changed, added
8747                            or dropped.
8748 
8749   @retval false  Success.
8750   @retval true   Error, ALTER - tries to do change which is not compatible
8751                  with foreign key definitions on the table.
8752 */
8753 
fk_check_copy_alter_table(THD * thd,TABLE * table,Alter_info * alter_info)8754 static bool fk_check_copy_alter_table(THD *thd, TABLE *table,
8755                                       Alter_info *alter_info)
8756 {
8757   List <FOREIGN_KEY_INFO> fk_parent_key_list;
8758   List <FOREIGN_KEY_INFO> fk_child_key_list;
8759   FOREIGN_KEY_INFO *f_key;
8760 
8761   DBUG_ENTER("fk_check_copy_alter_table");
8762 
8763   table->file->get_parent_foreign_key_list(thd, &fk_parent_key_list);
8764 
8765   /* OOM when building list. */
8766   if (thd->is_error())
8767     DBUG_RETURN(true);
8768 
8769   /*
8770     Remove from the list all foreign keys in which table participates as
8771     parent which are to be dropped by this ALTER TABLE. This is possible
8772     when a foreign key has the same table as child and parent.
8773   */
8774   List_iterator<FOREIGN_KEY_INFO> fk_parent_key_it(fk_parent_key_list);
8775 
8776   while ((f_key= fk_parent_key_it++))
8777   {
8778     Alter_drop *drop;
8779     List_iterator_fast<Alter_drop> drop_it(alter_info->drop_list);
8780 
8781     while ((drop= drop_it++))
8782     {
8783       /*
8784         InnoDB treats foreign key names in case-insensitive fashion.
8785         So we do it here too. For database and table name type of
8786         comparison used depends on lower-case-table-names setting.
8787         For l_c_t_n = 0 we use case-sensitive comparison, for
8788         l_c_t_n > 0 modes case-insensitive comparison is used.
8789       */
8790       if ((drop->type == Alter_drop::FOREIGN_KEY) &&
8791           (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
8792                          drop->name) == 0) &&
8793           (my_strcasecmp(table_alias_charset, f_key->foreign_db->str,
8794                          table->s->db.str) == 0) &&
8795           (my_strcasecmp(table_alias_charset, f_key->foreign_table->str,
8796                          table->s->table_name.str) == 0))
8797         fk_parent_key_it.remove();
8798     }
8799   }
8800 
8801   fk_parent_key_it.rewind();
8802   while ((f_key= fk_parent_key_it++))
8803   {
8804     enum fk_column_change_type changes;
8805     const char *bad_column_name;
8806 
8807     changes= fk_check_column_changes(thd, alter_info,
8808                                      f_key->referenced_fields,
8809                                      &bad_column_name);
8810 
8811     switch(changes)
8812     {
8813     case FK_COLUMN_NO_CHANGE:
8814       /* No significant changes. We can proceed with ALTER! */
8815       break;
8816     case FK_COLUMN_DATA_CHANGE:
8817     {
8818       char buff[NAME_LEN*2+2];
8819       strxnmov(buff, sizeof(buff)-1, f_key->foreign_db->str, ".",
8820                f_key->foreign_table->str, NullS);
8821       my_error(ER_FK_COLUMN_CANNOT_CHANGE_CHILD, MYF(0), bad_column_name,
8822                f_key->foreign_id->str, buff);
8823       DBUG_RETURN(true);
8824     }
8825     case FK_COLUMN_RENAMED:
8826       my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
8827                "ALGORITHM=COPY",
8828                ER(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME),
8829                "ALGORITHM=INPLACE");
8830       DBUG_RETURN(true);
8831     case FK_COLUMN_DROPPED:
8832     {
8833       char buff[NAME_LEN*2+2];
8834       strxnmov(buff, sizeof(buff)-1, f_key->foreign_db->str, ".",
8835                f_key->foreign_table->str, NullS);
8836       my_error(ER_FK_COLUMN_CANNOT_DROP_CHILD, MYF(0), bad_column_name,
8837                f_key->foreign_id->str, buff);
8838       DBUG_RETURN(true);
8839     }
8840     default:
8841       assert(0);
8842     }
8843   }
8844 
8845   table->file->get_foreign_key_list(thd, &fk_child_key_list);
8846 
8847   /* OOM when building list. */
8848   if (thd->is_error())
8849     DBUG_RETURN(true);
8850 
8851   /*
8852     Remove from the list all foreign keys which are to be dropped
8853     by this ALTER TABLE.
8854   */
8855   List_iterator<FOREIGN_KEY_INFO> fk_key_it(fk_child_key_list);
8856 
8857   while ((f_key= fk_key_it++))
8858   {
8859     Alter_drop *drop;
8860     List_iterator_fast<Alter_drop> drop_it(alter_info->drop_list);
8861 
8862     while ((drop= drop_it++))
8863     {
8864       /* Names of foreign keys in InnoDB are case-insensitive. */
8865       if ((drop->type == Alter_drop::FOREIGN_KEY) &&
8866           (my_strcasecmp(system_charset_info, f_key->foreign_id->str,
8867                          drop->name) == 0))
8868         fk_key_it.remove();
8869     }
8870   }
8871 
8872   fk_key_it.rewind();
8873   while ((f_key= fk_key_it++))
8874   {
8875     enum fk_column_change_type changes;
8876     const char *bad_column_name;
8877 
8878     changes= fk_check_column_changes(thd, alter_info,
8879                                      f_key->foreign_fields,
8880                                      &bad_column_name);
8881 
8882     switch(changes)
8883     {
8884     case FK_COLUMN_NO_CHANGE:
8885       /* No significant changes. We can proceed with ALTER! */
8886       break;
8887     case FK_COLUMN_DATA_CHANGE:
8888       my_error(ER_FK_COLUMN_CANNOT_CHANGE, MYF(0), bad_column_name,
8889                f_key->foreign_id->str);
8890       DBUG_RETURN(true);
8891     case FK_COLUMN_RENAMED:
8892       my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
8893                "ALGORITHM=COPY",
8894                ER(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_FK_RENAME),
8895                "ALGORITHM=INPLACE");
8896       DBUG_RETURN(true);
8897     case FK_COLUMN_DROPPED:
8898       my_error(ER_FK_COLUMN_CANNOT_DROP, MYF(0), bad_column_name,
8899                f_key->foreign_id->str);
8900       DBUG_RETURN(true);
8901     default:
8902       assert(0);
8903     }
8904   }
8905 
8906   DBUG_RETURN(false);
8907 }
8908 
8909 
8910 /**
8911   Rename table and/or turn indexes on/off without touching .FRM
8912 
8913   @param thd            Thread handler
8914   @param table_list     TABLE_LIST for the table to change
8915   @param keys_onoff     ENABLE or DISABLE KEYS?
8916   @param alter_ctx      ALTER TABLE runtime context.
8917 
8918   @return Operation status
8919     @retval false           Success
8920     @retval true            Failure
8921 */
8922 
8923 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)8924 simple_rename_or_index_change(THD *thd, TABLE_LIST *table_list,
8925                               Alter_info::enum_enable_or_disable keys_onoff,
8926                               Alter_table_ctx *alter_ctx)
8927 {
8928   TABLE *table= table_list->table;
8929   MDL_ticket *mdl_ticket= table->mdl_ticket;
8930   int error= 0;
8931   DBUG_ENTER("simple_rename_or_index_change");
8932 
8933   if (keys_onoff != Alter_info::LEAVE_AS_IS)
8934   {
8935     if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
8936       DBUG_RETURN(true);
8937 
8938     // It's now safe to take the table level lock.
8939     if (lock_tables(thd, table_list, alter_ctx->tables_opened, 0))
8940       DBUG_RETURN(true);
8941 
8942     if (keys_onoff == Alter_info::ENABLE)
8943     {
8944       DEBUG_SYNC(thd,"alter_table_enable_indexes");
8945       DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000););
8946       error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
8947     }
8948     else if (keys_onoff == Alter_info::DISABLE)
8949       error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
8950 
8951     if (error == HA_ERR_WRONG_COMMAND)
8952     {
8953       push_warning_printf(thd, Sql_condition::SL_NOTE,
8954                           ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
8955                           table->alias);
8956       error= 0;
8957     }
8958     else if (error > 0)
8959     {
8960       table->file->print_error(error, MYF(0));
8961       error= -1;
8962     }
8963   }
8964 
8965   if (!error && alter_ctx->is_table_renamed())
8966   {
8967     THD_STAGE_INFO(thd, stage_rename);
8968     handlerton *old_db_type= table->s->db_type();
8969     /*
8970       Then do a 'simple' rename of the table. First we need to close all
8971       instances of 'source' table.
8972       Note that if wait_while_table_is_used() returns error here (i.e. if
8973       this thread was killed) then it must be that previous step of
8974       simple rename did nothing and therefore we can safely return
8975       without additional clean-up.
8976     */
8977     if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
8978       DBUG_RETURN(true);
8979     close_all_tables_for_name(thd, table->s, true, NULL);
8980 
8981     if (mysql_rename_table(old_db_type, alter_ctx->db, alter_ctx->table_name,
8982                            alter_ctx->new_db, alter_ctx->new_alias, 0))
8983       error= -1;
8984     else if (change_trigger_table_name(thd,
8985                                        alter_ctx->db,
8986                                        alter_ctx->alias,
8987                                        alter_ctx->table_name,
8988                                        alter_ctx->new_db,
8989                                        alter_ctx->new_alias))
8990     {
8991       (void) mysql_rename_table(old_db_type,
8992                                 alter_ctx->new_db, alter_ctx->new_alias,
8993                                 alter_ctx->db, alter_ctx->table_name,
8994                                 NO_FK_CHECKS);
8995       error= -1;
8996     }
8997   }
8998 
8999   if (!error)
9000   {
9001     error= write_bin_log(thd, true, thd->query().str, thd->query().length);
9002     if (!error)
9003       my_ok(thd);
9004   }
9005   table_list->table= NULL;                    // For query cache
9006   query_cache.invalidate(thd, table_list, FALSE);
9007 
9008   if ((thd->locked_tables_mode == LTM_LOCK_TABLES ||
9009        thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES))
9010   {
9011     /*
9012       Under LOCK TABLES we should adjust meta-data locks before finishing
9013       statement. Otherwise we can rely on them being released
9014       along with the implicit commit.
9015     */
9016     if (alter_ctx->is_table_renamed())
9017       thd->mdl_context.release_all_locks_for_name(mdl_ticket);
9018     else
9019       mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
9020   }
9021   DBUG_RETURN(error != 0);
9022 }
9023 
9024 
9025 /**
9026   Auxiliary class implementing RAII principle for getting permission for/
9027   notification about finished ALTER TABLE from interested storage engines.
9028 
9029   @see handlerton::notify_alter_table for details.
9030 */
9031 
9032 class Alter_table_hton_notification_guard
9033 {
9034 public:
Alter_table_hton_notification_guard(THD * thd,const MDL_key * key)9035   Alter_table_hton_notification_guard(THD *thd, const MDL_key *key)
9036     : m_hton_notified(false), m_thd(thd), m_key(key)
9037   {
9038   }
9039 
notify()9040   bool notify()
9041   {
9042     if (!ha_notify_alter_table(m_thd, &m_key, HA_NOTIFY_PRE_EVENT))
9043     {
9044       m_hton_notified= true;
9045       return false;
9046     }
9047     my_error(ER_LOCK_REFUSED_BY_ENGINE, MYF(0));
9048     return true;
9049   }
9050 
~Alter_table_hton_notification_guard()9051   ~Alter_table_hton_notification_guard()
9052   {
9053     if (m_hton_notified)
9054       (void) ha_notify_alter_table(m_thd, &m_key, HA_NOTIFY_POST_EVENT);
9055   }
9056 private:
9057   bool m_hton_notified;
9058   THD *m_thd;
9059   const MDL_key m_key;
9060 };
9061 
9062 
9063 /**
9064   Alter table
9065 
9066   @param thd              Thread handle
9067   @param new_db           If there is a RENAME clause
9068   @param new_name         If there is a RENAME clause
9069   @param create_info      Information from the parsing phase about new
9070                           table properties.
9071   @param table_list       The table to change.
9072   @param alter_info       Lists of fields, keys to be changed, added
9073                           or dropped.
9074 
9075   @retval   true          Error
9076   @retval   false         Success
9077 
9078   This is a veery long function and is everything but the kitchen sink :)
9079   It is used to alter a table and not only by ALTER TABLE but also
9080   CREATE|DROP INDEX are mapped on this function.
9081 
9082   When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
9083   or both, then this function short cuts its operation by renaming
9084   the table and/or enabling/disabling the keys. In this case, the FRM is
9085   not changed, directly by mysql_alter_table. However, if there is a
9086   RENAME + change of a field, or an index, the short cut is not used.
9087   See how `create_list` is used to generate the new FRM regarding the
9088   structure of the fields. The same is done for the indices of the table.
9089 
9090   Altering a table can be done in two ways. The table can be modified
9091   directly using an in-place algorithm, or the changes can be done using
9092   an intermediate temporary table (copy). In-place is the preferred
9093   algorithm as it avoids copying table data. The storage engine
9094   selects which algorithm to use in check_if_supported_inplace_alter()
9095   based on information about the table changes from fill_alter_inplace_info().
9096 */
9097 
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)9098 bool mysql_alter_table(THD *thd, const char *new_db, const char *new_name,
9099                        HA_CREATE_INFO *create_info,
9100                        TABLE_LIST *table_list,
9101                        Alter_info *alter_info)
9102 {
9103   class Silence_deprecation_warnings: public Internal_error_handler
9104   {
9105   private:
9106     THD *m_thd;
9107   public:
9108     Silence_deprecation_warnings(THD *thd): m_thd(thd)
9109     { m_thd->push_internal_handler(this); }
9110     bool handle_condition(THD *thd,
9111                           uint sql_errno,
9112                           const char* sqlstate,
9113                           Sql_condition::enum_severity_level *level,
9114                           const char* msg)
9115     {
9116       if (sql_errno == ER_WARN_DEPRECATED_SYNTAX)
9117         return true;
9118 
9119       return false;
9120     }
9121     void pop()
9122     {
9123       if (m_thd)
9124         m_thd->pop_internal_handler();
9125       m_thd= NULL;
9126     }
9127     ~Silence_deprecation_warnings()
9128     { pop(); }
9129   };
9130 
9131   DBUG_ENTER("mysql_alter_table");
9132 
9133   Silence_deprecation_warnings deprecation_silencer(thd);
9134   bool is_partitioned= false;
9135 
9136   /*
9137     Check if we attempt to alter mysql.slow_log or
9138     mysql.general_log table and return an error if
9139     it is the case.
9140     TODO: this design is obsolete and will be removed.
9141   */
9142   enum_log_table_type table_kind=
9143     query_logger.check_if_log_table(table_list, false);
9144 
9145   if (table_kind != QUERY_LOG_NONE)
9146   {
9147     /* Disable alter of enabled query log tables */
9148     if (query_logger.is_log_table_enabled(table_kind))
9149     {
9150       my_error(ER_BAD_LOG_STATEMENT, MYF(0), "ALTER");
9151       DBUG_RETURN(true);
9152     }
9153 
9154     /* Disable alter of log tables to unsupported engine */
9155     if ((create_info->used_fields & HA_CREATE_USED_ENGINE) &&
9156         (!create_info->db_type || /* unknown engine */
9157          !(create_info->db_type->flags & HTON_SUPPORT_LOG_TABLES)))
9158     {
9159       my_error(ER_UNSUPORTED_LOG_ENGINE, MYF(0));
9160       DBUG_RETURN(true);
9161     }
9162 
9163     if (alter_info->flags & Alter_info::ALTER_PARTITION)
9164     {
9165       my_error(ER_WRONG_USAGE, MYF(0), "PARTITION", "log table");
9166       DBUG_RETURN(true);
9167     }
9168   }
9169 
9170   if (alter_info->with_validation != Alter_info::ALTER_VALIDATION_DEFAULT &&
9171       !(alter_info->flags &
9172         (Alter_info::ALTER_ADD_COLUMN | Alter_info::ALTER_CHANGE_COLUMN)))
9173   {
9174     my_error(ER_WRONG_USAGE, MYF(0), "ALTER","WITH VALIDATION");
9175     DBUG_RETURN(true);
9176   }
9177 
9178   THD_STAGE_INFO(thd, stage_init);
9179 
9180   /*
9181     Assign target tablespace name to enable locking in lock_table_names().
9182     Reject invalid names.
9183   */
9184   if (create_info->tablespace)
9185   {
9186     if (check_tablespace_name(create_info->tablespace) != IDENT_NAME_OK)
9187       DBUG_RETURN(true);
9188 
9189     if (!thd->make_lex_string(&table_list->target_tablespace_name,
9190                               create_info->tablespace,
9191                               strlen(create_info->tablespace), false))
9192     {
9193       my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
9194       DBUG_RETURN(true);
9195     }
9196   }
9197 
9198   // Reject invalid tablespace names specified for partitions.
9199   if (check_partition_tablespace_names(thd->lex->part_info))
9200     DBUG_RETURN(true);
9201 
9202   /*
9203     Assign the partition info, so that the locks on tablespaces
9204     assigned for any new partitions added would be acuired during
9205     open_table.
9206   */
9207   thd->work_part_info= thd->lex->part_info;
9208 
9209   /*
9210     Code below can handle only base tables so ensure that we won't open a view.
9211     Note that RENAME TABLE the only ALTER clause which is supported for views
9212     has been already processed.
9213   */
9214   table_list->required_type= FRMTYPE_TABLE;
9215 
9216   /*
9217     If we are about to ALTER non-temporary table we need to get permission
9218     from/notify interested storage engines.
9219   */
9220   Alter_table_hton_notification_guard notification_guard(thd,
9221                                         &table_list->mdl_request.key);
9222 
9223   if (!is_temporary_table(table_list) && notification_guard.notify())
9224     DBUG_RETURN(true);
9225 
9226   Alter_table_prelocking_strategy alter_prelocking_strategy;
9227 
9228   DEBUG_SYNC(thd, "alter_table_before_open_tables");
9229   uint tables_opened;
9230   bool error= open_tables(thd, &table_list, &tables_opened, 0,
9231                           &alter_prelocking_strategy);
9232 
9233   DEBUG_SYNC(thd, "alter_opened_table");
9234 
9235 #ifdef WITH_WSREP
9236   DBUG_EXECUTE_IF("sync.alter_opened_table",
9237                   {
9238                     const char act[]=
9239                       "now "
9240                       "wait_for signal.alter_opened_table";
9241                     assert(!debug_sync_set_action(thd,
9242                                                        STRING_WITH_LEN(act)));
9243                   };);
9244 #endif // WITH_WSREP
9245 
9246   if (error)
9247     DBUG_RETURN(true);
9248 
9249   /*
9250     Check if ALTER TABLE ... ENGINE is disallowed by the desired storage
9251     engine.
9252   */
9253   if (table_list->table->s->db_type() != create_info->db_type &&
9254       (alter_info->flags & Alter_info::ALTER_OPTIONS) &&
9255       (create_info->used_fields & HA_CREATE_USED_ENGINE) &&
9256        ha_is_storage_engine_disabled(create_info->db_type))
9257   {
9258     /*
9259       If NO_ENGINE_SUBSTITUTION is disabled, then report a warning and do not
9260       alter the table.
9261     */
9262     if (is_engine_substitution_allowed(thd))
9263     {
9264       push_warning_printf(thd, Sql_condition::SL_WARNING,
9265                           ER_UNKNOWN_STORAGE_ENGINE,
9266                           ER(ER_UNKNOWN_STORAGE_ENGINE),
9267                           ha_resolve_storage_engine_name(create_info->db_type));
9268       create_info->db_type= table_list->table->s->db_type();
9269     }
9270     else
9271     {
9272       my_error(ER_DISABLED_STORAGE_ENGINE, MYF(0),
9273                ha_resolve_storage_engine_name(create_info->db_type));
9274       DBUG_RETURN(true);
9275     }
9276   }
9277 
9278   TABLE *table= table_list->table;
9279   table->use_all_columns();
9280   MDL_ticket *mdl_ticket= table->mdl_ticket;
9281 
9282   /*
9283     Check if the source table is non-natively partitioned. This will be
9284     used for pushing a deprecation warning in cases like adding/dropping
9285     partitions, table rename, and ALTER INPLACE. For ALTER COPY, we need
9286     to check the destination table.
9287   */
9288   is_partitioned= table->s->db_type() &&
9289           is_ha_partition_handlerton(table->s->db_type());
9290 
9291   /*
9292     Prohibit changing of the UNION list of a non-temporary MERGE table
9293     under LOCK tables. It would be quite difficult to reuse a shrinked
9294     set of tables from the old table or to open a new TABLE object for
9295     an extended list and verify that they belong to locked tables.
9296   */
9297   if ((thd->locked_tables_mode == LTM_LOCK_TABLES ||
9298        thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES) &&
9299       (create_info->used_fields & HA_CREATE_USED_UNION) &&
9300       (table->s->tmp_table == NO_TMP_TABLE))
9301   {
9302     my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
9303     DBUG_RETURN(true);
9304   }
9305 
9306   Alter_table_ctx alter_ctx(thd, table_list, tables_opened, new_db, new_name);
9307 
9308   /*
9309     Add old and new (if any) databases to the list of accessed databases
9310     for this statement. Needed for MTS.
9311   */
9312   thd->add_to_binlog_accessed_dbs(alter_ctx.db);
9313   if (alter_ctx.is_database_changed())
9314     thd->add_to_binlog_accessed_dbs(alter_ctx.new_db);
9315 
9316   MDL_request target_mdl_request;
9317 
9318   /* Check that we are not trying to rename to an existing table */
9319   if (alter_ctx.is_table_renamed())
9320   {
9321     if (table->s->tmp_table != NO_TMP_TABLE)
9322     {
9323       if (find_temporary_table(thd, alter_ctx.new_db, alter_ctx.new_name))
9324       {
9325         my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alter_ctx.new_alias);
9326         DBUG_RETURN(true);
9327       }
9328     }
9329     else
9330     {
9331       MDL_request_list mdl_requests;
9332       MDL_request target_db_mdl_request;
9333 
9334       MDL_REQUEST_INIT(&target_mdl_request,
9335                        MDL_key::TABLE,
9336                        alter_ctx.new_db, alter_ctx.new_name,
9337                        MDL_EXCLUSIVE, MDL_TRANSACTION);
9338       mdl_requests.push_front(&target_mdl_request);
9339 
9340       /*
9341         If we are moving the table to a different database, we also
9342         need IX lock on the database name so that the target database
9343         is protected by MDL while the table is moved.
9344       */
9345       if (alter_ctx.is_database_changed())
9346       {
9347         MDL_REQUEST_INIT(&target_db_mdl_request,
9348                          MDL_key::SCHEMA, alter_ctx.new_db, "",
9349                          MDL_INTENTION_EXCLUSIVE,
9350                          MDL_TRANSACTION);
9351         mdl_requests.push_front(&target_db_mdl_request);
9352       }
9353 
9354       /*
9355         Global intention exclusive lock must have been already acquired when
9356         table to be altered was open, so there is no need to do it here.
9357       */
9358       assert(thd->mdl_context.owns_equal_or_stronger_lock(MDL_key::GLOBAL,
9359                                                           "", "", MDL_INTENTION_EXCLUSIVE));
9360 
9361       if (thd->mdl_context.acquire_locks(&mdl_requests,
9362                                          thd->variables.lock_wait_timeout))
9363         DBUG_RETURN(true);
9364 
9365       DEBUG_SYNC(thd, "locked_table_name");
9366       /*
9367         Table maybe does not exist, but we got an exclusive lock
9368         on the name, now we can safely try to find out for sure.
9369       */
9370       if (!access(alter_ctx.get_new_filename(), F_OK))
9371       {
9372         /* Table will be closed in do_command() */
9373         my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alter_ctx.new_alias);
9374         DBUG_RETURN(true);
9375       }
9376     }
9377   }
9378 
9379   if (!create_info->db_type)
9380   {
9381     if (table->part_info &&
9382         create_info->used_fields & HA_CREATE_USED_ENGINE)
9383     {
9384       /*
9385         This case happens when the user specified
9386         ENGINE = x where x is a non-existing storage engine
9387         We set create_info->db_type to default_engine_type
9388         to ensure we don't change underlying engine type
9389         due to a erroneously given engine name.
9390       */
9391       create_info->db_type= table->part_info->default_engine_type;
9392     }
9393     else
9394       create_info->db_type= table->s->db_type();
9395   }
9396 
9397   if (check_engine(thd, alter_ctx.new_db, alter_ctx.new_name, create_info))
9398     DBUG_RETURN(true);
9399 
9400   if (create_info->db_type != table->s->db_type() &&
9401       !table->file->can_switch_engines())
9402   {
9403     my_error(ER_ROW_IS_REFERENCED, MYF(0));
9404     DBUG_RETURN(true);
9405   }
9406 
9407   /*
9408    If foreign key is added then check permission to access parent table.
9409 
9410    In function "check_fk_parent_table_access", create_info->db_type is used
9411    to identify whether engine supports FK constraint or not. Since
9412    create_info->db_type is set here, check to parent table access is delayed
9413    till this point for the alter operation.
9414   */
9415   if ((alter_info->flags & Alter_info::ADD_FOREIGN_KEY) &&
9416       check_fk_parent_table_access(thd, alter_ctx.new_db,
9417                                    create_info, alter_info))
9418     DBUG_RETURN(true);
9419 
9420   /*
9421    If this is an ALTER TABLE and no explicit row type specified reuse
9422    the table's row type.
9423    Note : this is the same as if the row type was specified explicitly.
9424   */
9425   if (create_info->row_type == ROW_TYPE_NOT_USED)
9426   {
9427     /* ALTER TABLE without explicit row type */
9428     create_info->row_type= table->s->row_type;
9429   }
9430   else
9431   {
9432     /* ALTER TABLE with specific row type */
9433     create_info->used_fields |= HA_CREATE_USED_ROW_FORMAT;
9434   }
9435 
9436   DBUG_PRINT("info", ("old type: %s  new type: %s",
9437              ha_resolve_storage_engine_name(table->s->db_type()),
9438              ha_resolve_storage_engine_name(create_info->db_type)));
9439   if (ha_check_storage_engine_flag(table->s->db_type(), HTON_ALTER_NOT_SUPPORTED) ||
9440       ha_check_storage_engine_flag(create_info->db_type, HTON_ALTER_NOT_SUPPORTED))
9441   {
9442     DBUG_PRINT("info", ("doesn't support alter"));
9443     my_error(ER_ILLEGAL_HA, MYF(0), table_list->table_name);
9444     DBUG_RETURN(true);
9445   }
9446 
9447   THD_STAGE_INFO(thd, stage_setup);
9448   if (!(alter_info->flags & ~(Alter_info::ALTER_RENAME |
9449                               Alter_info::ALTER_KEYS_ONOFF)) &&
9450       alter_info->requested_algorithm !=
9451       Alter_info::ALTER_TABLE_ALGORITHM_COPY &&
9452       !table->s->tmp_table) // no need to touch frm
9453   {
9454     // This requires X-lock, no other lock levels supported.
9455     if (alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_DEFAULT &&
9456         alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE)
9457     {
9458       my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
9459                "LOCK=NONE/SHARED", "LOCK=EXCLUSIVE");
9460       DBUG_RETURN(true);
9461     }
9462     deprecation_silencer.pop();
9463     if (is_partitioned)
9464       push_warning_printf(thd, Sql_condition::SL_WARNING,
9465                           ER_WARN_DEPRECATED_SYNTAX,
9466                           ER_THD(thd,
9467                                  ER_PARTITION_ENGINE_DEPRECATED_FOR_TABLE),
9468                           alter_ctx.new_db, alter_ctx.new_alias);
9469     DBUG_RETURN(simple_rename_or_index_change(thd, table_list,
9470                                               alter_info->keys_onoff,
9471                                               &alter_ctx));
9472   }
9473 
9474   /* We have to do full alter table. */
9475 
9476   bool partition_changed= false;
9477   partition_info *new_part_info= NULL;
9478   {
9479     if (prep_alter_part_table(thd, table, alter_info, create_info,
9480                               &alter_ctx, &partition_changed,
9481                               &new_part_info))
9482     {
9483       DBUG_RETURN(true);
9484     }
9485     if (partition_changed &&
9486         (!table->file->ht->partition_flags ||
9487          (table->file->ht->partition_flags() & HA_CANNOT_PARTITION_FK)) &&
9488         !table->file->can_switch_engines())
9489     {
9490       /*
9491         Partitioning was changed (added/changed/removed) and the current
9492         handler does not support partitioning and FK relationship exists
9493         for the table.
9494 
9495         Since the current handler does not support native partitioning, it will
9496         be altered to use ha_partition which does not support foreign keys.
9497       */
9498       my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
9499       DBUG_RETURN(true);
9500     }
9501   }
9502 
9503   if (mysql_prepare_alter_table(thd, table, create_info, alter_info,
9504                                 &alter_ctx))
9505   {
9506     DBUG_RETURN(true);
9507   }
9508 
9509   set_table_default_charset(thd, create_info, const_cast<char*>(alter_ctx.db));
9510 
9511   if (new_part_info)
9512   {
9513     /*
9514       ALGORITHM and LOCK clauses are generally not allowed by the
9515       parser for operations related to partitioning.
9516       The exceptions are ALTER_PARTITION, ALTER_UPGRADE_PARTITIONING
9517       and ALTER_REMOVE_PARTITIONING.
9518       The two first should be meta-data only changes and allowed with
9519       INPLACE.
9520       For consistency, we report ER_ALTER_OPERATION_NOT_SUPPORTED for other
9521       combinations.
9522     */
9523     if (alter_info->requested_lock !=
9524         Alter_info::ALTER_TABLE_LOCK_DEFAULT)
9525     {
9526       my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
9527                "LOCK=NONE/SHARED/EXCLUSIVE",
9528                ER(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_PARTITION),
9529                "LOCK=DEFAULT");
9530       DBUG_RETURN(true);
9531     }
9532     else if (alter_info->requested_algorithm !=
9533              Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT &&
9534              !((alter_info->flags == Alter_info::ALTER_PARTITION ||
9535                 alter_info->flags == Alter_info::ALTER_UPGRADE_PARTITIONING) &&
9536                alter_info->requested_algorithm ==
9537                  Alter_info::ALTER_TABLE_ALGORITHM_INPLACE))
9538     {
9539       my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
9540                "ALGORITHM=COPY/INPLACE",
9541                ER(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_PARTITION),
9542                "ALGORITHM=DEFAULT");
9543       DBUG_RETURN(true);
9544     }
9545 
9546     /*
9547       Upgrade from MDL_SHARED_UPGRADABLE to MDL_SHARED_NO_WRITE.
9548       Afterwards it's safe to take the table level lock.
9549     */
9550     if (thd->mdl_context.upgrade_shared_lock(mdl_ticket, MDL_SHARED_NO_WRITE,
9551                                              thd->variables.lock_wait_timeout)
9552         || lock_tables(thd, table_list, alter_ctx.tables_opened, 0))
9553     {
9554       DBUG_RETURN(true);
9555     }
9556 
9557     char* table_name= const_cast<char*>(alter_ctx.table_name);
9558     deprecation_silencer.pop();
9559     if (is_partitioned)
9560       push_warning_printf(thd, Sql_condition::SL_WARNING,
9561                           ER_WARN_DEPRECATED_SYNTAX,
9562                           ER_THD(thd,
9563                                  ER_PARTITION_ENGINE_DEPRECATED_FOR_TABLE),
9564                           alter_ctx.new_db, alter_ctx.new_alias);
9565     // In-place execution of ALTER TABLE for partitioning.
9566     DBUG_RETURN(fast_alter_partition_table(thd, table, alter_info,
9567                                            create_info, table_list,
9568                                            const_cast<char*>(alter_ctx.db),
9569                                            table_name,
9570                                            new_part_info));
9571   }
9572 
9573   /*
9574     Use copy algorithm if:
9575     - old_alter_table system variable is set without in-place requested using
9576       the ALGORITHM clause.
9577     - Or if in-place is impossible for given operation.
9578     - Changes to partitioning which were not handled by
9579       fast_alter_partition_table() needs to be handled using table copying
9580       algorithm unless the engine supports auto-partitioning as such engines
9581       can do some changes using in-place API.
9582   */
9583   if ((thd->variables.old_alter_table &&
9584        alter_info->requested_algorithm !=
9585        Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
9586       || is_inplace_alter_impossible(table, create_info, alter_info, &alter_ctx)
9587       || (partition_changed &&
9588           !(table->s->db_type()->partition_flags() & HA_USE_AUTO_PARTITION))
9589      )
9590   {
9591     if (alter_info->requested_algorithm ==
9592         Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
9593     {
9594       my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
9595                "ALGORITHM=INPLACE", "ALGORITHM=COPY");
9596       DBUG_RETURN(true);
9597     }
9598     alter_info->requested_algorithm= Alter_info::ALTER_TABLE_ALGORITHM_COPY;
9599   }
9600 
9601   /*
9602     If 'avoid_temporal_upgrade' mode is not enabled, then the
9603     pre MySQL 5.6.4 old temporal types if present is upgraded to the
9604     current format.
9605   */
9606 
9607   mysql_mutex_lock(&LOCK_global_system_variables);
9608   bool check_temporal_upgrade= !avoid_temporal_upgrade;
9609   mysql_mutex_unlock(&LOCK_global_system_variables);
9610 
9611   if (check_temporal_upgrade)
9612   {
9613     if (upgrade_old_temporal_types(thd, alter_info))
9614       DBUG_RETURN(true);
9615   }
9616 
9617   /*
9618     ALTER TABLE ... ENGINE to the same engine is a common way to
9619     request table rebuild. Set ALTER_RECREATE flag to force table
9620     rebuild.
9621   */
9622   if (create_info->db_type == table->s->db_type() &&
9623       create_info->used_fields & HA_CREATE_USED_ENGINE)
9624     alter_info->flags|= Alter_info::ALTER_RECREATE;
9625 
9626   /*
9627     If the old table had partitions and we are doing ALTER TABLE ...
9628     engine= <new_engine>, the new table must preserve the original
9629     partitioning. This means that the new engine is still the
9630     partitioning engine, not the engine specified in the parser.
9631     This is discovered in prep_alter_part_table, which in such case
9632     updates create_info->db_type.
9633     It's therefore important that the assignment below is done
9634     after prep_alter_part_table.
9635   */
9636   handlerton *new_db_type= create_info->db_type;
9637   handlerton *old_db_type= table->s->db_type();
9638   TABLE *new_table= NULL;
9639   ha_rows copied=0,deleted=0;
9640 
9641   /*
9642     Handling of symlinked tables:
9643     If no rename:
9644       Create new data file and index file on the same disk as the
9645       old data and index files.
9646       Copy data.
9647       Rename new data file over old data file and new index file over
9648       old index file.
9649       Symlinks are not changed.
9650 
9651    If rename:
9652       Create new data file and index file on the same disk as the
9653       old data and index files.  Create also symlinks to point at
9654       the new tables.
9655       Copy data.
9656       At end, rename intermediate tables, and symlinks to intermediate
9657       table, to final table name.
9658       Remove old table and old symlinks
9659 
9660     If rename is made to another database:
9661       Create new tables in new database.
9662       Copy data.
9663       Remove old table and symlinks.
9664   */
9665   char index_file[FN_REFLEN], data_file[FN_REFLEN];
9666 
9667   if (!alter_ctx.is_database_changed())
9668   {
9669     if (create_info->index_file_name)
9670     {
9671       /* Fix index_file_name to have 'tmp_name' as basename */
9672       my_stpcpy(index_file, alter_ctx.tmp_name);
9673       create_info->index_file_name=fn_same(index_file,
9674                                            create_info->index_file_name,
9675                                            1);
9676     }
9677     if (create_info->data_file_name)
9678     {
9679       /* Fix data_file_name to have 'tmp_name' as basename */
9680       my_stpcpy(data_file, alter_ctx.tmp_name);
9681       create_info->data_file_name=fn_same(data_file,
9682                                           create_info->data_file_name,
9683                                           1);
9684     }
9685   }
9686   else
9687   {
9688     /* Ignore symlink if db is changed. */
9689     create_info->data_file_name=create_info->index_file_name=0;
9690   }
9691 
9692   DEBUG_SYNC(thd, "alter_table_before_create_table_no_lock");
9693   DBUG_EXECUTE_IF("sleep_before_create_table_no_lock",
9694                   my_sleep(100000););
9695   /*
9696     Promote first timestamp column, when explicit_defaults_for_timestamp
9697     is not set
9698   */
9699   if (!thd->variables.explicit_defaults_for_timestamp)
9700     promote_first_timestamp_column(&alter_info->create_list);
9701 
9702   /*
9703     Create .FRM for new version of table with a temporary name.
9704     We don't log the statement, it will be logged later.
9705 
9706     Keep information about keys in newly created table as it
9707     will be used later to construct Alter_inplace_info object
9708     and by fill_alter_inplace_info() call.
9709   */
9710   KEY *key_info;
9711   uint key_count;
9712   /*
9713     Remember if the new definition has new VARCHAR column;
9714     create_info->varchar will be reset in create_table_impl()/
9715     mysql_prepare_create_table().
9716   */
9717   bool varchar= create_info->varchar;
9718 
9719   tmp_disable_binlog(thd);
9720   error= create_table_impl(thd, alter_ctx.new_db, alter_ctx.tmp_name,
9721                            alter_ctx.table_name,
9722                            alter_ctx.get_tmp_path(),
9723                            create_info, alter_info,
9724                            true, 0, true, NULL,
9725                            &key_info, &key_count);
9726   reenable_binlog(thd);
9727 
9728   if (error)
9729     DBUG_RETURN(true);
9730 
9731   /*
9732     We want warnings/errors about data truncation emitted when new
9733     version of table is created in COPY algorithm or when values of
9734     virtual columns are evaluated in INPLACE algorithm.
9735   */
9736   thd->count_cuted_fields= CHECK_FIELD_WARN;
9737   thd->cuted_fields= 0L;
9738 
9739   /* Remember that we have not created table in storage engine yet. */
9740   bool no_ha_table= true;
9741 
9742   if (alter_info->requested_algorithm != Alter_info::ALTER_TABLE_ALGORITHM_COPY)
9743   {
9744     Alter_inplace_info ha_alter_info(create_info, alter_info,
9745                                      key_info, key_count,
9746                                      thd->work_part_info
9747                                      );
9748     TABLE *altered_table= NULL;
9749     bool use_inplace= true;
9750 
9751     /* Fill the Alter_inplace_info structure. */
9752     if (fill_alter_inplace_info(thd, table, varchar, &ha_alter_info))
9753       goto err_new_table_cleanup;
9754 
9755     DBUG_EXECUTE_IF("innodb_index_drop_count_zero",
9756                     {
9757                       if (ha_alter_info.index_drop_count)
9758                       {
9759                         my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
9760                                  "Index rebuild", "Without rebuild");
9761                         DBUG_RETURN(true);
9762                       }
9763                     };);
9764 
9765    DBUG_EXECUTE_IF("innodb_index_drop_count_one",
9766                     {
9767                       if (ha_alter_info.index_drop_count != 1)
9768                       {
9769                         my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
9770                                  "Index change", "Index rebuild");
9771                         DBUG_RETURN(true);
9772                       }
9773                     };);
9774 
9775     // We assume that the table is non-temporary.
9776    assert(!table->s->tmp_table);
9777 
9778     if (!(altered_table= open_table_uncached(thd, alter_ctx.get_tmp_path(),
9779                                              alter_ctx.new_db,
9780                                              alter_ctx.tmp_name,
9781                                              true, false)))
9782       goto err_new_table_cleanup;
9783 
9784     /* Set markers for fields in TABLE object for altered table. */
9785     update_altered_table(ha_alter_info, altered_table);
9786 
9787     /*
9788       Mark all columns in 'altered_table' as used to allow usage
9789       of its record[0] buffer and Field objects during in-place
9790       ALTER TABLE.
9791     */
9792     altered_table->column_bitmaps_set_no_signal(&altered_table->s->all_set,
9793                                                 &altered_table->s->all_set);
9794 
9795     set_column_defaults(altered_table, alter_info->create_list);
9796 
9797     if (ha_alter_info.handler_flags == 0)
9798     {
9799       /*
9800         No-op ALTER, no need to call handler API functions.
9801 
9802         If this code path is entered for an ALTER statement that
9803         should not be a real no-op, new handler flags should be added
9804         and fill_alter_inplace_info() adjusted.
9805 
9806         Note that we can end up here if an ALTER statement has clauses
9807         that cancel each other out (e.g. ADD/DROP identically index).
9808 
9809         Also note that we ignore the LOCK clause here.
9810       */
9811       close_temporary_table(thd, altered_table, true, false);
9812       (void) quick_rm_table(thd, new_db_type, alter_ctx.new_db,
9813                             alter_ctx.tmp_name, FN_IS_TMP | NO_HA_TABLE);
9814       goto end_inplace;
9815     }
9816 
9817     // Ask storage engine whether to use copy or in-place
9818     enum_alter_inplace_result inplace_supported=
9819       table->file->check_if_supported_inplace_alter(altered_table,
9820                                                     &ha_alter_info);
9821 
9822     switch (inplace_supported) {
9823     case HA_ALTER_INPLACE_EXCLUSIVE_LOCK:
9824       // If SHARED lock and no particular algorithm was requested, use COPY.
9825       if (alter_info->requested_lock ==
9826           Alter_info::ALTER_TABLE_LOCK_SHARED &&
9827           alter_info->requested_algorithm ==
9828           Alter_info::ALTER_TABLE_ALGORITHM_DEFAULT)
9829       {
9830         use_inplace= false;
9831       }
9832       // Otherwise, if weaker lock was requested, report errror.
9833       else if (alter_info->requested_lock ==
9834                Alter_info::ALTER_TABLE_LOCK_NONE ||
9835                alter_info->requested_lock ==
9836                Alter_info::ALTER_TABLE_LOCK_SHARED)
9837       {
9838         ha_alter_info.report_unsupported_error("LOCK=NONE/SHARED",
9839                                                "LOCK=EXCLUSIVE");
9840         close_temporary_table(thd, altered_table, true, false);
9841         goto err_new_table_cleanup;
9842       }
9843       break;
9844     case HA_ALTER_INPLACE_SHARED_LOCK_AFTER_PREPARE:
9845     case HA_ALTER_INPLACE_SHARED_LOCK:
9846       // If weaker lock was requested, report errror.
9847       if (alter_info->requested_lock ==
9848           Alter_info::ALTER_TABLE_LOCK_NONE)
9849       {
9850         ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
9851         close_temporary_table(thd, altered_table, true, false);
9852         goto err_new_table_cleanup;
9853       }
9854       break;
9855     case HA_ALTER_INPLACE_NO_LOCK_AFTER_PREPARE:
9856     case HA_ALTER_INPLACE_NO_LOCK:
9857       break;
9858     case HA_ALTER_INPLACE_NOT_SUPPORTED:
9859       // If INPLACE was requested, report error.
9860       if (alter_info->requested_algorithm ==
9861           Alter_info::ALTER_TABLE_ALGORITHM_INPLACE)
9862       {
9863         ha_alter_info.report_unsupported_error("ALGORITHM=INPLACE",
9864                                                "ALGORITHM=COPY");
9865         close_temporary_table(thd, altered_table, true, false);
9866         goto err_new_table_cleanup;
9867       }
9868       // COPY with LOCK=NONE is not supported, no point in trying.
9869       if (alter_info->requested_lock ==
9870           Alter_info::ALTER_TABLE_LOCK_NONE)
9871       {
9872         ha_alter_info.report_unsupported_error("LOCK=NONE", "LOCK=SHARED");
9873         close_temporary_table(thd, altered_table, true, false);
9874         goto err_new_table_cleanup;
9875       }
9876       // Otherwise use COPY
9877       use_inplace= false;
9878       break;
9879     case HA_ALTER_ERROR:
9880     default:
9881       close_temporary_table(thd, altered_table, true, false);
9882       goto err_new_table_cleanup;
9883     }
9884 
9885     if (use_inplace)
9886     {
9887       if (mysql_inplace_alter_table(thd, table_list, table,
9888                                     altered_table,
9889                                     &ha_alter_info,
9890                                     inplace_supported, &target_mdl_request,
9891                                     &alter_ctx))
9892       {
9893         thd->count_cuted_fields= CHECK_FIELD_IGNORE;
9894         DBUG_RETURN(true);
9895       }
9896 
9897       goto end_inplace;
9898     }
9899     else
9900     {
9901       close_temporary_table(thd, altered_table, true, false);
9902     }
9903   }
9904 
9905   /* ALTER TABLE using copy algorithm. */
9906 
9907   /* Check if ALTER TABLE is compatible with foreign key definitions. */
9908   if (fk_check_copy_alter_table(thd, table, alter_info))
9909     goto err_new_table_cleanup;
9910 
9911   if (!table->s->tmp_table)
9912   {
9913     // COPY algorithm doesn't work with concurrent writes.
9914     if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE)
9915     {
9916       my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
9917                "LOCK=NONE",
9918                ER(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON_COPY),
9919                "LOCK=SHARED");
9920       goto err_new_table_cleanup;
9921     }
9922 
9923     // If EXCLUSIVE lock is requested, upgrade already.
9924     if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE &&
9925         wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
9926       goto err_new_table_cleanup;
9927 
9928     /*
9929       Otherwise upgrade to SHARED_NO_WRITE.
9930       Note that under LOCK TABLES, we will already have SHARED_NO_READ_WRITE.
9931     */
9932     if (alter_info->requested_lock != Alter_info::ALTER_TABLE_LOCK_EXCLUSIVE &&
9933         thd->mdl_context.upgrade_shared_lock(mdl_ticket, MDL_SHARED_NO_WRITE,
9934                                              thd->variables.lock_wait_timeout))
9935       goto err_new_table_cleanup;
9936 
9937     DEBUG_SYNC(thd, "alter_table_copy_after_lock_upgrade");
9938   }
9939 
9940   // It's now safe to take the table level lock.
9941   if (lock_tables(thd, table_list, alter_ctx.tables_opened, 0))
9942     goto err_new_table_cleanup;
9943 
9944   {
9945     if (ha_create_table(thd, alter_ctx.get_tmp_path(),
9946                         alter_ctx.new_db, alter_ctx.tmp_name,
9947                         create_info, false))
9948       goto err_new_table_cleanup;
9949 
9950     /* Mark that we have created table in storage engine. */
9951     no_ha_table= false;
9952 
9953     if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
9954     {
9955       if (!open_table_uncached(thd, alter_ctx.get_tmp_path(),
9956                                alter_ctx.new_db, alter_ctx.tmp_name,
9957                                true, true))
9958         goto err_new_table_cleanup;
9959       /* in case of alter temp table send the tracker in OK packet */
9960       if (thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)->is_enabled())
9961         thd->session_tracker.get_tracker(SESSION_STATE_CHANGE_TRACKER)->mark_as_changed(thd, NULL);
9962     }
9963   }
9964 
9965 
9966   /* Open the table since we need to copy the data. */
9967   if (table->s->tmp_table != NO_TMP_TABLE)
9968   {
9969     TABLE_LIST tbl;
9970     tbl.init_one_table(alter_ctx.new_db, strlen(alter_ctx.new_db),
9971                        alter_ctx.tmp_name, strlen(alter_ctx.tmp_name),
9972                        alter_ctx.tmp_name, TL_READ_NO_INSERT);
9973     /* Table is in thd->temporary_tables */
9974     (void) open_temporary_table(thd, &tbl);
9975     new_table= tbl.table;
9976   }
9977   else
9978   {
9979     /* table is a normal table: Create temporary table in same directory */
9980     /* Open our intermediate table. */
9981     new_table= open_table_uncached(thd, alter_ctx.get_tmp_path(),
9982                                    alter_ctx.new_db, alter_ctx.tmp_name,
9983                                    true, true);
9984   }
9985   if (!new_table)
9986     goto err_new_table_cleanup;
9987   /*
9988     Note: In case of MERGE table, we do not attach children. We do not
9989     copy data for MERGE tables. Only the children have data.
9990   */
9991 
9992   /*
9993     We do not copy data for MERGE tables. Only the children have data.
9994     MERGE tables have HA_NO_COPY_ON_ALTER set.
9995   */
9996   if (!(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
9997   {
9998     new_table->next_number_field=new_table->found_next_number_field;
9999     THD_STAGE_INFO(thd, stage_copy_to_tmp_table);
10000     DBUG_EXECUTE_IF("abort_copy_table", {
10001         my_error(ER_LOCK_WAIT_TIMEOUT, MYF(0));
10002         goto err_new_table_cleanup;
10003       });
10004 
10005     /*
10006       Acquire SRO locks on parent tables to prevent concurrent DML on them to
10007       perform cascading actions. Since InnoDB releases locks on table being
10008       altered periodically these actions might be able to succeed and
10009       can create orphan rows in our table otherwise.
10010 
10011       Note that we ignore FOREIGN_KEY_CHECKS=0 setting here because, unlike
10012       for DML operations it is hard to predict what kind of inconsistencies
10013       ignoring foreign keys will create (ignoring foreign keys in this case
10014       is similar to forcing other connections to ignore them).
10015 
10016       It is possible that acquisition of locks on parent tables will result
10017       in MDL deadlocks. But since deadlocks involving two or more DDL
10018       statements should be rare, it is unlikely that our ALTER TABLE will
10019       be aborted due to such deadlock.
10020     */
10021     if (lock_fk_dependent_tables(thd, table))
10022       goto err_new_table_cleanup;
10023 
10024     if (copy_data_between_tables(thd->m_stage_progress_psi,
10025                                  table, new_table,
10026                                  alter_info->create_list,
10027                                  &copied, &deleted,
10028                                  alter_info->keys_onoff,
10029                                  &alter_ctx))
10030       goto err_new_table_cleanup;
10031   }
10032   else
10033   {
10034     /* Should be MERGE only */
10035     assert(new_table->file->ht->db_type == DB_TYPE_MRG_MYISAM);
10036     if (!table->s->tmp_table &&
10037         wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
10038       goto err_new_table_cleanup;
10039     THD_STAGE_INFO(thd, stage_manage_keys);
10040     DEBUG_SYNC(thd, "alter_table_manage_keys");
10041     alter_table_manage_keys(table, table->file->indexes_are_disabled(),
10042                             alter_info->keys_onoff);
10043     if (trans_commit_stmt(thd) || trans_commit_implicit(thd))
10044       goto err_new_table_cleanup;
10045   }
10046 
10047   if (table->s->tmp_table != NO_TMP_TABLE)
10048   {
10049     /* Close lock if this is a transactional table */
10050     if (thd->lock)
10051     {
10052       if (thd->locked_tables_mode != LTM_LOCK_TABLES &&
10053           thd->locked_tables_mode != LTM_PRELOCKED_UNDER_LOCK_TABLES)
10054       {
10055         mysql_unlock_tables(thd, thd->lock);
10056         thd->lock= NULL;
10057       }
10058       else
10059       {
10060         /*
10061           If LOCK TABLES list is not empty and contains this table,
10062           unlock the table and remove the table from this list.
10063         */
10064         mysql_lock_remove(thd, thd->lock, table);
10065       }
10066     }
10067     /* Remove link to old table and rename the new one */
10068     close_temporary_table(thd, table, true, true);
10069     /* Should pass the 'new_name' as we store table name in the cache */
10070     if (rename_temporary_table(thd, new_table,
10071                                alter_ctx.new_db, alter_ctx.new_name))
10072       goto err_new_table_cleanup;
10073     /* We don't replicate alter table statement on temporary tables */
10074     if (!thd->is_current_stmt_binlog_format_row() &&
10075         write_bin_log(thd, true, thd->query().str, thd->query().length))
10076     {
10077       thd->count_cuted_fields= CHECK_FIELD_IGNORE;
10078       DBUG_RETURN(true);
10079     }
10080     goto end_temporary;
10081   }
10082 
10083   /*
10084     At this point, we must check whether the destination table is
10085     non-natively partitioned.
10086   */
10087   is_partitioned= new_table->s->db_type() &&
10088           is_ha_partition_handlerton(new_table->s->db_type());
10089   /*
10090     Close the intermediate table that will be the new table, but do
10091     not delete it! Even altough MERGE tables do not have their children
10092     attached here it is safe to call close_temporary_table().
10093   */
10094   close_temporary_table(thd, new_table, true, false);
10095   new_table= NULL;
10096 
10097   DEBUG_SYNC(thd, "alter_table_before_rename_result_table");
10098 
10099   /*
10100     Data is copied. Now we:
10101     1) Wait until all other threads will stop using old version of table
10102        by upgrading shared metadata lock to exclusive one.
10103     2) Close instances of table open by this thread and replace them
10104        with placeholders to simplify reopen process.
10105     3) Rename the old table to a temp name, rename the new one to the
10106        old name.
10107     4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
10108        we reopen new version of table.
10109     5) Write statement to the binary log.
10110     6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
10111        remove placeholders and release metadata locks.
10112     7) If we are not not under LOCK TABLES we rely on the caller
10113       (mysql_execute_command()) to release metadata locks.
10114   */
10115 
10116   THD_STAGE_INFO(thd, stage_rename_result_table);
10117 
10118   if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
10119     goto err_new_table_cleanup;
10120 
10121   close_all_tables_for_name(thd, table->s, alter_ctx.is_table_renamed(), NULL);
10122   table_list->table= table= NULL;                  /* Safety */
10123 
10124   /*
10125     Rename the old table to temporary name to have a backup in case
10126     anything goes wrong while renaming the new table.
10127   */
10128   char backup_name[32];
10129   assert(sizeof(my_thread_id) == 4);
10130   my_snprintf(backup_name, sizeof(backup_name), "%s2-%lx-%lx", tmp_file_prefix,
10131               current_pid, thd->thread_id());
10132   if (lower_case_table_names)
10133     my_casedn_str(files_charset_info, backup_name);
10134   if (mysql_rename_table(old_db_type, alter_ctx.db, alter_ctx.table_name,
10135                          alter_ctx.db, backup_name, FN_TO_IS_TMP))
10136   {
10137     // Rename to temporary name failed, delete the new table, abort ALTER.
10138     (void) quick_rm_table(thd, new_db_type, alter_ctx.new_db,
10139                           alter_ctx.tmp_name, FN_IS_TMP);
10140     goto err_with_mdl;
10141   }
10142 
10143   // Rename the new table to the correct name.
10144   if (mysql_rename_table(new_db_type, alter_ctx.new_db, alter_ctx.tmp_name,
10145                          alter_ctx.new_db, alter_ctx.new_alias,
10146                          FN_FROM_IS_TMP))
10147   {
10148     // Rename failed, delete the temporary table.
10149     (void) quick_rm_table(thd, new_db_type, alter_ctx.new_db,
10150                           alter_ctx.tmp_name, FN_IS_TMP);
10151 
10152     // Restore the backup of the original table to the old name.
10153     (void) mysql_rename_table(old_db_type, alter_ctx.db, backup_name,
10154                               alter_ctx.db, alter_ctx.alias,
10155                               FN_FROM_IS_TMP | NO_FK_CHECKS);
10156 
10157     goto err_with_mdl;
10158   }
10159 
10160   // Check if we renamed the table and if so update trigger files.
10161   if (alter_ctx.is_table_renamed() &&
10162       change_trigger_table_name(thd,
10163                                 alter_ctx.db,
10164                                 alter_ctx.alias,
10165                                 alter_ctx.table_name,
10166                                 alter_ctx.new_db,
10167                                 alter_ctx.new_alias))
10168   {
10169     // Rename succeeded, delete the new table.
10170     (void) quick_rm_table(thd, new_db_type,
10171                           alter_ctx.new_db, alter_ctx.new_alias, 0);
10172     // Restore the backup of the original table to the old name.
10173     (void) mysql_rename_table(old_db_type, alter_ctx.db, backup_name,
10174                               alter_ctx.db, alter_ctx.alias,
10175                               FN_FROM_IS_TMP | NO_FK_CHECKS);
10176     goto err_with_mdl;
10177   }
10178 
10179   // ALTER TABLE succeeded, delete the backup of the old table.
10180   if (quick_rm_table(thd, old_db_type, alter_ctx.db, backup_name, FN_IS_TMP))
10181   {
10182     /*
10183       The fact that deletion of the backup failed is not critical
10184       error, but still worth reporting as it might indicate serious
10185       problem with server.
10186     */
10187     goto err_with_mdl;
10188   }
10189 
10190 end_inplace:
10191   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
10192 
10193   if (thd->locked_tables_list.reopen_tables(thd))
10194     goto err_with_mdl;
10195 
10196   deprecation_silencer.pop();
10197   if (is_partitioned)
10198     push_warning_printf(thd, Sql_condition::SL_WARNING,
10199                         ER_WARN_DEPRECATED_SYNTAX,
10200                         ER_THD(thd,
10201                                ER_PARTITION_ENGINE_DEPRECATED_FOR_TABLE),
10202                         alter_ctx.new_db, alter_ctx.new_alias);
10203 
10204   THD_STAGE_INFO(thd, stage_end);
10205 
10206   DBUG_EXECUTE_IF("sleep_alter_before_main_binlog", my_sleep(6000000););
10207   DEBUG_SYNC(thd, "alter_table_before_main_binlog");
10208 
10209   ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
10210                       thd->query().str, thd->query().length,
10211                       alter_ctx.db, alter_ctx.table_name);
10212 
10213   assert(!(mysql_bin_log.is_open() &&
10214            thd->is_current_stmt_binlog_format_row() &&
10215            (create_info->options & HA_LEX_CREATE_TMP_TABLE)));
10216   if (write_bin_log(thd, true, thd->query().str, thd->query().length))
10217     DBUG_RETURN(true);
10218 
10219   if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
10220   {
10221     /*
10222       For the alter table to be properly flushed to the logs, we
10223       have to open the new table.  If not, we get a problem on server
10224       shutdown. But we do not need to attach MERGE children.
10225     */
10226     TABLE *t_table;
10227     t_table= open_table_uncached(thd, alter_ctx.get_new_path(),
10228                                  alter_ctx.new_db, alter_ctx.new_name,
10229                                  false, true);
10230     if (t_table)
10231       intern_close_table(t_table);
10232     else
10233       sql_print_warning("Could not open table %s.%s after rename\n",
10234                         alter_ctx.new_db, alter_ctx.table_name);
10235     ha_flush_logs(old_db_type);
10236   }
10237   table_list->table= NULL;			// For query cache
10238   query_cache.invalidate(thd, table_list, FALSE);
10239 
10240   if (thd->locked_tables_mode == LTM_LOCK_TABLES ||
10241       thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)
10242   {
10243     if (alter_ctx.is_table_renamed())
10244       thd->mdl_context.release_all_locks_for_name(mdl_ticket);
10245     else
10246       mdl_ticket->downgrade_lock(MDL_SHARED_NO_READ_WRITE);
10247   }
10248 
10249 end_temporary:
10250   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
10251 
10252   my_snprintf(alter_ctx.tmp_name, sizeof(alter_ctx.tmp_name),
10253               ER(ER_INSERT_INFO),
10254 	      (long) (copied + deleted), (long) deleted,
10255 	      (long) thd->get_stmt_da()->current_statement_cond_count());
10256   my_ok(thd, copied + deleted, 0L, alter_ctx.tmp_name);
10257   DBUG_RETURN(false);
10258 
10259 err_new_table_cleanup:
10260   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
10261 
10262   if (new_table)
10263   {
10264     /* close_temporary_table() frees the new_table pointer. */
10265     close_temporary_table(thd, new_table, true, true);
10266   }
10267   else
10268     (void) quick_rm_table(thd, new_db_type,
10269                           alter_ctx.new_db, alter_ctx.tmp_name,
10270                           (FN_IS_TMP | (no_ha_table ? NO_HA_TABLE : 0)));
10271 
10272   if (alter_ctx.error_if_not_empty & Alter_table_ctx::GEOMETRY_WITHOUT_DEFAULT)
10273   {
10274     my_error(ER_INVALID_USE_OF_NULL, MYF(0));
10275   }
10276 
10277   /*
10278     No default value was provided for a DATE/DATETIME field, the
10279     current sql_mode doesn't allow the '0000-00-00' value and
10280     the table to be altered isn't empty.
10281     Report error here.
10282   */
10283   if ((alter_ctx.error_if_not_empty &
10284        Alter_table_ctx::DATETIME_WITHOUT_DEFAULT) &&
10285       (thd->variables.sql_mode & MODE_NO_ZERO_DATE) &&
10286       thd->get_stmt_da()->current_row_for_condition())
10287     push_zero_date_warning(thd, alter_ctx.datetime_field);
10288   DBUG_RETURN(true);
10289 
10290 err_with_mdl:
10291   thd->count_cuted_fields= CHECK_FIELD_IGNORE;
10292 
10293   /*
10294     An error happened while we were holding exclusive name metadata lock
10295     on table being altered. To be safe under LOCK TABLES we should
10296     remove all references to the altered table from the list of locked
10297     tables and release the exclusive metadata lock.
10298   */
10299   thd->locked_tables_list.unlink_all_closed_tables(thd, NULL, 0);
10300   thd->mdl_context.release_all_locks_for_name(mdl_ticket);
10301   DBUG_RETURN(true);
10302 }
10303 /* mysql_alter_table */
10304 
10305 
10306 
10307 /**
10308   Prepare the transaction for the alter table's copy phase.
10309 */
10310 
mysql_trans_prepare_alter_copy_data(THD * thd)10311 bool mysql_trans_prepare_alter_copy_data(THD *thd)
10312 {
10313   DBUG_ENTER("mysql_prepare_alter_copy_data");
10314   /*
10315     Turn off recovery logging since rollback of an alter table is to
10316     delete the new table so there is no need to log the changes to it.
10317 
10318     This needs to be done before external_lock.
10319   */
10320   if (ha_enable_transaction(thd, FALSE))
10321     DBUG_RETURN(TRUE);
10322   DBUG_RETURN(FALSE);
10323 }
10324 
10325 
10326 /**
10327   Commit the copy phase of the alter table.
10328 */
10329 
mysql_trans_commit_alter_copy_data(THD * thd)10330 bool mysql_trans_commit_alter_copy_data(THD *thd)
10331 {
10332   bool error= FALSE;
10333   DBUG_ENTER("mysql_commit_alter_copy_data");
10334 
10335   if (ha_enable_transaction(thd, TRUE))
10336     DBUG_RETURN(TRUE);
10337 
10338   DEBUG_SYNC(thd, "commit_alter_copy_table");
10339 
10340   /*
10341     Ensure that the new table is saved properly to disk before installing
10342     the new .frm.
10343     And that InnoDB's internal latches are released, to avoid deadlock
10344     when waiting on other instances of the table before rename (Bug#54747).
10345   */
10346   if (trans_commit_stmt(thd))
10347     error= TRUE;
10348   if (trans_commit_implicit(thd))
10349     error= TRUE;
10350 
10351   DBUG_RETURN(error);
10352 }
10353 
10354 
10355 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)10356 copy_data_between_tables(PSI_stage_progress *psi,
10357                          TABLE *from,TABLE *to,
10358 			 List<Create_field> &create,
10359 			 ha_rows *copied,
10360 			 ha_rows *deleted,
10361                          Alter_info::enum_enable_or_disable keys_onoff,
10362                          Alter_table_ctx *alter_ctx)
10363 {
10364   int error;
10365   Copy_field *copy,*copy_end;
10366   ulong found_count,delete_count;
10367   THD *thd= current_thd;
10368   READ_RECORD info;
10369   TABLE_LIST   tables;
10370   List<Item>   fields;
10371   List<Item>   all_fields;
10372   ha_rows examined_rows, found_rows, returned_rows;
10373   bool auto_increment_field_copied= 0;
10374   sql_mode_t save_sql_mode;
10375   QEP_TAB_standalone qep_tab_st;
10376   QEP_TAB &qep_tab= qep_tab_st.as_QEP_TAB();
10377   DBUG_ENTER("copy_data_between_tables");
10378 
10379   if (mysql_trans_prepare_alter_copy_data(thd))
10380     DBUG_RETURN(-1);
10381 
10382   if (!(copy= new Copy_field[to->s->fields]))
10383     DBUG_RETURN(-1);				/* purecov: inspected */
10384 
10385   if (to->file->ha_external_lock(thd, F_WRLCK))
10386     DBUG_RETURN(-1);
10387 
10388   /* We need external lock before we can disable/enable keys */
10389   alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
10390 
10391   from->file->info(HA_STATUS_VARIABLE);
10392   to->file->ha_start_bulk_insert(from->file->stats.records);
10393 
10394   mysql_stage_set_work_estimated(psi, from->file->stats.records);
10395 
10396   save_sql_mode= thd->variables.sql_mode;
10397 
10398   List_iterator<Create_field> it(create);
10399   Create_field *def;
10400   copy_end=copy;
10401   for (Field **ptr=to->field ; *ptr ; ptr++)
10402   {
10403     def=it++;
10404     if (def->field)
10405     {
10406       if (*ptr == to->next_number_field)
10407       {
10408         auto_increment_field_copied= TRUE;
10409         /*
10410           If we are going to copy contents of one auto_increment column to
10411           another auto_increment column it is sensible to preserve zeroes.
10412           This condition also covers case when we are don't actually alter
10413           auto_increment column.
10414         */
10415         if (def->field == from->found_next_number_field)
10416           thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
10417       }
10418       (copy_end++)->set(*ptr,def->field,0);
10419     }
10420 
10421   }
10422 
10423   found_count=delete_count=0;
10424 
10425   SELECT_LEX *const select_lex= thd->lex->select_lex;
10426   ORDER *const order= select_lex->order_list.first;
10427 
10428   if (order)
10429   {
10430     if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
10431     {
10432       char warn_buff[MYSQL_ERRMSG_SIZE];
10433       my_snprintf(warn_buff, sizeof(warn_buff),
10434                   "ORDER BY ignored as there is a user-defined clustered index"
10435                   " in the table '%-.192s'", from->s->table_name.str);
10436       push_warning(thd, Sql_condition::SL_WARNING, ER_UNKNOWN_ERROR,
10437                    warn_buff);
10438     }
10439     else
10440     {
10441       from->sort.io_cache=(IO_CACHE*) my_malloc(key_memory_TABLE_sort_io_cache,
10442                                                 sizeof(IO_CACHE),
10443                                                 MYF(MY_FAE | MY_ZEROFILL));
10444       tables.table= from;
10445       tables.alias= tables.table_name= from->s->table_name.str;
10446       tables.db= from->s->db.str;
10447       error= 1;
10448 
10449       Column_privilege_tracker column_privilege(thd, SELECT_ACL);
10450 
10451       if (select_lex->setup_ref_array(thd))
10452         goto err;            /* purecov: inspected */
10453       if (setup_order(thd, select_lex->ref_pointer_array,
10454                       &tables, fields, all_fields, order))
10455         goto err;
10456       qep_tab.set_table(from);
10457       Filesort fsort(&qep_tab, order, HA_POS_ERROR);
10458       if (filesort(thd, &fsort, true,
10459                    &examined_rows, &found_rows, &returned_rows))
10460         goto err;
10461 
10462       from->sort.found_records= returned_rows;
10463     }
10464   };
10465 
10466   /* Tell handler that we have values for all columns in the to table */
10467   to->use_all_columns();
10468   if (init_read_record(&info, thd, from, NULL, 1, 1, FALSE))
10469   {
10470     error= 1;
10471     goto err;
10472   }
10473   thd->get_stmt_da()->reset_current_row_for_condition();
10474 
10475   set_column_defaults(to, create);
10476 
10477   while (!(error=info.read_record(&info)))
10478   {
10479     if (thd->killed)
10480     {
10481       thd->send_kill_message();
10482       error= 1;
10483       break;
10484     }
10485     /*
10486       Return error if source table isn't empty.
10487 
10488       For a DATE/DATETIME field, return error only if strict mode
10489       and No ZERO DATE mode is enabled.
10490     */
10491     if ((alter_ctx->error_if_not_empty &
10492          Alter_table_ctx::GEOMETRY_WITHOUT_DEFAULT) ||
10493         ((alter_ctx->error_if_not_empty &
10494           Alter_table_ctx::DATETIME_WITHOUT_DEFAULT) &&
10495          (thd->variables.sql_mode & MODE_NO_ZERO_DATE) &&
10496          thd->is_strict_mode()))
10497     {
10498       error= 1;
10499       break;
10500     }
10501     if (to->next_number_field)
10502     {
10503       if (auto_increment_field_copied)
10504         to->auto_increment_field_not_null= TRUE;
10505       else
10506         to->next_number_field->reset();
10507     }
10508 
10509     for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
10510     {
10511       copy_ptr->invoke_do_copy(copy_ptr);
10512     }
10513     if ((to->vfield && update_generated_write_fields(to->write_set, to)) ||
10514       thd->is_error())
10515     {
10516       error= 1;
10517       break;
10518     }
10519 
10520     error=to->file->ha_write_row(to->record[0]);
10521     to->auto_increment_field_not_null= FALSE;
10522     if (error)
10523     {
10524       if (!to->file->is_ignorable_error(error))
10525       {
10526         /* Not a duplicate key error. */
10527 	to->file->print_error(error, MYF(0));
10528 	break;
10529       }
10530       else
10531       {
10532         /* Report duplicate key error. */
10533         uint key_nr= to->file->get_dup_key(error);
10534         if ((int) key_nr >= 0)
10535         {
10536           const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
10537           if (key_nr == 0 &&
10538               (to->key_info[0].key_part[0].field->flags &
10539                AUTO_INCREMENT_FLAG))
10540             err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
10541           print_keydup_error(to, key_nr == MAX_KEY ? NULL :
10542                              &to->key_info[key_nr],
10543                              err_msg, MYF(0));
10544         }
10545         else
10546           to->file->print_error(error, MYF(0));
10547         break;
10548       }
10549     }
10550     else
10551     {
10552       DEBUG_SYNC(thd, "copy_data_between_tables_before");
10553       found_count++;
10554       mysql_stage_set_work_completed(psi, found_count);
10555     }
10556     thd->get_stmt_da()->inc_current_row_for_condition();
10557   }
10558   end_read_record(&info);
10559   free_io_cache(from);
10560   delete [] copy;				// This is never 0
10561 
10562   if (to->file->ha_end_bulk_insert() && error <= 0)
10563   {
10564     to->file->print_error(my_errno(),MYF(0));
10565     error= 1;
10566   }
10567 
10568   if (mysql_trans_commit_alter_copy_data(thd))
10569     error= 1;
10570 
10571  err:
10572   thd->variables.sql_mode= save_sql_mode;
10573   free_io_cache(from);
10574   *copied= found_count;
10575   *deleted=delete_count;
10576   to->file->ha_release_auto_increment();
10577   if (to->file->ha_external_lock(thd,F_UNLCK))
10578     error=1;
10579   if (error < 0 && to->file->extra(HA_EXTRA_PREPARE_FOR_RENAME))
10580     error= 1;
10581   DBUG_RETURN(error > 0 ? -1 : 0);
10582 }
10583 
10584 
10585 /*
10586   Recreates tables by calling mysql_alter_table().
10587 
10588   SYNOPSIS
10589     mysql_recreate_table()
10590     thd			Thread handler
10591     tables		Tables to recreate
10592     table_copy          Recreate the table by using
10593                         ALTER TABLE COPY algorithm
10594 
10595  RETURN
10596     Like mysql_alter_table().
10597 */
mysql_recreate_table(THD * thd,TABLE_LIST * table_list,bool table_copy)10598 bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool table_copy)
10599 {
10600   HA_CREATE_INFO create_info;
10601   Alter_info alter_info;
10602 
10603   DBUG_ENTER("mysql_recreate_table");
10604   assert(!table_list->next_global);
10605   /* Set lock type which is appropriate for ALTER TABLE. */
10606   table_list->lock_type= TL_READ_NO_INSERT;
10607   /* Same applies to MDL request. */
10608   table_list->mdl_request.set_type(MDL_SHARED_NO_WRITE);
10609 
10610   create_info.row_type=ROW_TYPE_NOT_USED;
10611   create_info.default_table_charset=default_charset_info;
10612   /* Force alter table to recreate table */
10613   alter_info.flags= (Alter_info::ALTER_CHANGE_COLUMN |
10614                      Alter_info::ALTER_RECREATE);
10615 
10616   if (table_copy)
10617     alter_info.requested_algorithm= Alter_info::ALTER_TABLE_ALGORITHM_COPY;
10618 
10619   const bool ret= mysql_alter_table(thd, NullS, NullS, &create_info,
10620                                     table_list, &alter_info);
10621   DBUG_RETURN(ret);
10622 }
10623 
10624 
mysql_checksum_table(THD * thd,TABLE_LIST * tables,HA_CHECK_OPT * check_opt)10625 bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
10626                           HA_CHECK_OPT *check_opt)
10627 {
10628   TABLE_LIST *table;
10629   List<Item> field_list;
10630   Item *item;
10631   Protocol *protocol= thd->get_protocol();
10632   DBUG_ENTER("mysql_checksum_table");
10633 
10634   /*
10635     CHECKSUM TABLE returns results and rollbacks statement transaction,
10636     so it should not be used in stored function or trigger.
10637   */
10638   assert(! thd->in_sub_stmt);
10639 
10640   field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
10641   item->maybe_null= 1;
10642   field_list.push_back(item= new Item_int(NAME_STRING("Checksum"),
10643                                           (longlong) 1,
10644                                           MY_INT64_NUM_DECIMAL_DIGITS));
10645   item->maybe_null= 1;
10646   if (thd->send_result_metadata(&field_list,
10647                                 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
10648     DBUG_RETURN(TRUE);
10649 
10650   /*
10651     Close all temporary tables which were pre-open to simplify
10652     privilege checking. Clear all references to closed tables.
10653   */
10654   close_thread_tables(thd);
10655   for (table= tables; table; table= table->next_local)
10656     table->table= NULL;
10657 
10658   /* Open one table after the other to keep lock time as short as possible. */
10659   for (table= tables; table; table= table->next_local)
10660   {
10661     char table_name[NAME_LEN*2+2];
10662     TABLE *t;
10663     TABLE_LIST *save_next_global;
10664 
10665     strxmov(table_name, table->db ,".", table->table_name, NullS);
10666 
10667     /* Remember old 'next' pointer and break the list.  */
10668     save_next_global= table->next_global;
10669     table->next_global= NULL;
10670     table->lock_type= TL_READ;
10671     /* Allow to open real tables only. */
10672     table->required_type= FRMTYPE_TABLE;
10673 
10674     if (open_temporary_tables(thd, table) ||
10675         open_and_lock_tables(thd, table, 0))
10676     {
10677       t= NULL;
10678     }
10679     else
10680       t= table->table;
10681 
10682     table->next_global= save_next_global;
10683 
10684     protocol->start_row();
10685     protocol->store(table_name, system_charset_info);
10686 
10687     if (!t)
10688     {
10689       /* Table didn't exist */
10690       protocol->store_null();
10691     }
10692     else
10693     {
10694       if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
10695 	  !(check_opt->flags & T_EXTEND))
10696 	protocol->store((ulonglong)t->file->checksum());
10697       else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
10698 	       (check_opt->flags & T_QUICK))
10699 	protocol->store_null();
10700       else
10701       {
10702 	/* calculating table's checksum */
10703 	ha_checksum crc= 0;
10704         uchar null_mask=256 -  (1 << t->s->last_null_bit_pos);
10705 
10706         t->use_all_columns();
10707 
10708 	if (t->file->ha_rnd_init(1))
10709 	  protocol->store_null();
10710 	else
10711 	{
10712 	  for (;;)
10713 	  {
10714             if (thd->killed)
10715             {
10716               /*
10717                  we've been killed; let handler clean up, and remove the
10718                  partial current row from the recordset (embedded lib)
10719               */
10720               t->file->ha_rnd_end();
10721               protocol->abort_row();
10722               goto err;
10723             }
10724 	    ha_checksum row_crc= 0;
10725             int error= t->file->ha_rnd_next(t->record[0]);
10726             if (unlikely(error))
10727             {
10728               if (error == HA_ERR_RECORD_DELETED)
10729                 continue;
10730               break;
10731             }
10732 	    if (t->s->null_bytes)
10733             {
10734               /* fix undefined null bits */
10735               t->record[0][t->s->null_bytes-1] |= null_mask;
10736               if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
10737                 t->record[0][0] |= 1;
10738 
10739 	      row_crc= checksum_crc32(row_crc, t->record[0], t->s->null_bytes);
10740             }
10741 
10742 	    for (uint i= 0; i < t->s->fields; i++ )
10743 	    {
10744 	      Field *f= t->field[i];
10745 
10746              /*
10747                BLOB and VARCHAR have pointers in their field, we must convert
10748                to string; GEOMETRY is implemented on top of BLOB.
10749                BIT may store its data among NULL bits, convert as well.
10750              */
10751               switch (f->type()) {
10752                 case MYSQL_TYPE_BLOB:
10753                 case MYSQL_TYPE_VARCHAR:
10754                 case MYSQL_TYPE_GEOMETRY:
10755                 case MYSQL_TYPE_BIT:
10756                 {
10757                   String tmp;
10758                   f->val_str(&tmp);
10759                   row_crc= checksum_crc32(row_crc, (uchar*) tmp.ptr(),
10760                            tmp.length());
10761                   break;
10762                 }
10763                 default:
10764                   row_crc= checksum_crc32(row_crc, f->ptr, f->pack_length());
10765                   break;
10766 	      }
10767 	    }
10768 
10769 	    crc+= row_crc;
10770 	  }
10771 	  protocol->store((ulonglong)crc);
10772           t->file->ha_rnd_end();
10773 	}
10774       }
10775       trans_rollback_stmt(thd);
10776       close_thread_tables(thd);
10777     }
10778 
10779     if (thd->transaction_rollback_request)
10780     {
10781       /*
10782         If transaction rollback was requested we honor it. To do this we
10783         abort statement and return error as not only CHECKSUM TABLE is
10784         rolled back but the whole transaction in which it was used.
10785       */
10786       protocol->abort_row();
10787       goto err;
10788     }
10789 
10790     /* Hide errors from client. Return NULL for problematic tables instead. */
10791     thd->clear_error();
10792 
10793     if (protocol->end_row())
10794       goto err;
10795   }
10796 
10797   my_eof(thd);
10798   DBUG_RETURN(FALSE);
10799 
10800 err:
10801   DBUG_RETURN(TRUE);
10802 }
10803 
10804 // Return true if ENCRYPTION clause requests for table encryption.
is_encrypted(const std::string type)10805 static inline bool is_encrypted(const std::string type) {
10806   return (type.empty() == false && type != "" && type != "N" && type != "n");
10807 }
10808 
10809 /**
10810   @brief Check if the table can be created in the specified storage engine.
10811 
10812   Checks if the storage engine is enabled and supports the given table
10813   type (e.g. normal, temporary, system). May do engine substitution
10814   if the requested engine is disabled.
10815 
10816   @param thd          Thread descriptor.
10817   @param db_name      Database name.
10818   @param table_name   Name of table to be created.
10819   @param create_info  Create info from parser, including engine.
10820 
10821   @retval true  Engine not available/supported, error has been reported.
10822   @retval false Engine available/supported.
10823 */
check_engine(THD * thd,const char * db_name,const char * table_name,HA_CREATE_INFO * create_info)10824 static bool check_engine(THD *thd, const char *db_name,
10825                          const char *table_name, HA_CREATE_INFO *create_info)
10826 {
10827   DBUG_ENTER("check_engine");
10828   handlerton **new_engine= &create_info->db_type;
10829   handlerton *req_engine= *new_engine;
10830   bool no_substitution=
10831         MY_TEST(!is_engine_substitution_allowed(thd));
10832   if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
10833                                   no_substitution, 1)))
10834     DBUG_RETURN(true);
10835 
10836   if (req_engine && req_engine != *new_engine)
10837   {
10838     push_warning_printf(thd, Sql_condition::SL_NOTE,
10839                        ER_WARN_USING_OTHER_HANDLER,
10840                        ER(ER_WARN_USING_OTHER_HANDLER),
10841                        ha_resolve_storage_engine_name(*new_engine),
10842                        table_name);
10843   }
10844   if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
10845       ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
10846   {
10847     if (create_info->used_fields & HA_CREATE_USED_ENGINE)
10848     {
10849       my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
10850                ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
10851       *new_engine= 0;
10852       DBUG_RETURN(true);
10853     }
10854     *new_engine= myisam_hton;
10855   }
10856 
10857   /*
10858     Check, if the given table name is system table, and if the storage engine
10859     does supports it.
10860   */
10861   if ((create_info->used_fields & HA_CREATE_USED_ENGINE) &&
10862       !ha_is_valid_system_or_user_table(*new_engine, db_name, table_name))
10863   {
10864     my_error(ER_UNSUPPORTED_ENGINE, MYF(0),
10865              ha_resolve_storage_engine_name(*new_engine), db_name, table_name);
10866     *new_engine= NULL;
10867     DBUG_RETURN(true);
10868   }
10869 
10870   // Check if the storage engine supports encryption.
10871   if (create_info->encrypt_type.str &&
10872       is_encrypted(create_info->encrypt_type.str) &&
10873       !((*new_engine)->flags & HTON_SUPPORTS_TABLE_ENCRYPTION))
10874   {
10875      my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
10876 	      ha_resolve_storage_engine_name(*new_engine), "ENCRYPTION");
10877      DBUG_RETURN(true);
10878   }
10879 
10880   DBUG_RETURN(false);
10881 }
10882