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