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