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