MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
sql_db.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 /* create and drop of databases */
19 
20 #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
21 #include "sql_priv.h"
22 #include "unireg.h"
23 #include "sql_db.h"
24 #include "sql_cache.h" // query_cache_*
25 #include "lock.h" // lock_schema_name
26 #include "sql_table.h" // build_table_filename,
27  // filename_to_tablename
28 #include "sql_rename.h" // mysql_rename_tables
29 #include "sql_acl.h" // SELECT_ACL, DB_ACLS,
30  // acl_get, check_grant_db
31 #include "log_event.h" // Query_log_event
32 #include "sql_base.h" // lock_table_names, tdc_remove_table
33 #include "sql_handler.h" // mysql_ha_rm_tables
34 #include <mysys_err.h>
35 #include "sp.h"
36 #include "events.h"
37 #include <my_dir.h>
38 #include <m_ctype.h>
39 #include "log.h"
40 #include "binlog.h" // mysql_bin_log
41 #include "log_event.h"
42 #ifdef __WIN__
43 #include <direct.h>
44 #endif
45 #include "debug_sync.h"
46 
47 #define MAX_DROP_TABLE_Q_LEN 1024
48 
49 const char *del_exts[]= {".frm", ".BAK", ".TMD", ".opt", ".OLD", NullS};
50 static TYPELIB deletable_extentions=
51 {array_elements(del_exts)-1,"del_exts", del_exts, NULL};
52 
53 static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp,
54  const char *db,
55  const char *path,
56  TABLE_LIST **tables,
57  bool *found_other_files);
58 
59 long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path);
60 static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error);
61 static void mysql_change_db_impl(THD *thd,
62  LEX_STRING *new_db_name,
63  ulong new_db_access,
64  const CHARSET_INFO *new_db_charset);
65 
66 
67 /* Database options hash */
68 static HASH dboptions;
69 static my_bool dboptions_init= 0;
70 static mysql_rwlock_t LOCK_dboptions;
71 
72 /* Structure for database options */
73 typedef struct my_dbopt_st
74 {
75  char *name; /* Database name */
76  uint name_length; /* Database length name */
77  const CHARSET_INFO *charset; /* Database default character set */
78 } my_dbopt_t;
79 
80 
81 /*
82  Function we use in the creation of our hash to get key.
83 */
84 
85 extern "C" uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length,
86  my_bool not_used);
87 
88 uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length,
89  my_bool not_used __attribute__((unused)))
90 {
91  *length= opt->name_length;
92  return (uchar*) opt->name;
93 }
94 
95 
96 /*
97  Helper function to write a query to binlog used by mysql_rm_db()
98 */
99 
100 static inline int write_to_binlog(THD *thd, char *query, uint q_len,
101  char *db, uint db_len)
102 {
103  Query_log_event qinfo(thd, query, q_len, FALSE, TRUE, FALSE, 0);
104  qinfo.db= db;
105  qinfo.db_len= db_len;
106  return mysql_bin_log.write_event(&qinfo);
107 }
108 
109 
110 /*
111  Function to free dboptions hash element
112 */
113 
114 extern "C" void free_dbopt(void *dbopt);
115 
116 void free_dbopt(void *dbopt)
117 {
118  my_free(dbopt);
119 }
120 
121 #ifdef HAVE_PSI_INTERFACE
122 static PSI_rwlock_key key_rwlock_LOCK_dboptions;
123 
124 static PSI_rwlock_info all_database_names_rwlocks[]=
125 {
126  { &key_rwlock_LOCK_dboptions, "LOCK_dboptions", PSI_FLAG_GLOBAL}
127 };
128 
129 static void init_database_names_psi_keys(void)
130 {
131  const char* category= "sql";
132  int count;
133 
134  count= array_elements(all_database_names_rwlocks);
135  mysql_rwlock_register(category, all_database_names_rwlocks, count);
136 }
137 #endif
138 
148 bool my_dboptions_cache_init(void)
149 {
150 #ifdef HAVE_PSI_INTERFACE
151  init_database_names_psi_keys();
152 #endif
153 
154  bool error= 0;
155  mysql_rwlock_init(key_rwlock_LOCK_dboptions, &LOCK_dboptions);
156  if (!dboptions_init)
157  {
158  dboptions_init= 1;
159  error= my_hash_init(&dboptions, lower_case_table_names ?
160  &my_charset_bin : system_charset_info,
161  32, 0, 0, (my_hash_get_key) dboptions_get_key,
162  free_dbopt,0);
163  }
164  return error;
165 }
166 
167 
168 
173 void my_dboptions_cache_free(void)
174 {
175  if (dboptions_init)
176  {
177  dboptions_init= 0;
178  my_hash_free(&dboptions);
179  mysql_rwlock_destroy(&LOCK_dboptions);
180  }
181 }
182 
183 
188 void my_dbopt_cleanup(void)
189 {
190  mysql_rwlock_wrlock(&LOCK_dboptions);
191  my_hash_free(&dboptions);
192  my_hash_init(&dboptions, lower_case_table_names ?
193  &my_charset_bin : system_charset_info,
194  32, 0, 0, (my_hash_get_key) dboptions_get_key,
195  free_dbopt,0);
196  mysql_rwlock_unlock(&LOCK_dboptions);
197 }
198 
199 
200 /*
201  Find database options in the hash.
202 
203  DESCRIPTION
204  Search a database options in the hash, usings its path.
205  Fills "create" on success.
206 
207  RETURN VALUES
208  0 on success.
209  1 on error.
210 */
211 
212 static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
213 {
214  my_dbopt_t *opt;
215  uint length;
216  my_bool error= 1;
217 
218  length= (uint) strlen(dbname);
219 
220  mysql_rwlock_rdlock(&LOCK_dboptions);
221  if ((opt= (my_dbopt_t*) my_hash_search(&dboptions, (uchar*) dbname, length)))
222  {
223  create->default_table_charset= opt->charset;
224  error= 0;
225  }
226  mysql_rwlock_unlock(&LOCK_dboptions);
227  return error;
228 }
229 
230 
231 /*
232  Writes database options into the hash.
233 
234  DESCRIPTION
235  Inserts database options into the hash, or updates
236  options if they are already in the hash.
237 
238  RETURN VALUES
239  0 on success.
240  1 on error.
241 */
242 
243 static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
244 {
245  my_dbopt_t *opt;
246  uint length;
247  my_bool error= 0;
248  DBUG_ENTER("put_dbopt");
249 
250  length= (uint) strlen(dbname);
251 
252  mysql_rwlock_wrlock(&LOCK_dboptions);
253  if (!(opt= (my_dbopt_t*) my_hash_search(&dboptions, (uchar*) dbname,
254  length)))
255  {
256  /* Options are not in the hash, insert them */
257  char *tmp_name;
258  if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
259  &opt, (uint) sizeof(*opt), &tmp_name, (uint) length+1,
260  NullS))
261  {
262  error= 1;
263  goto end;
264  }
265 
266  opt->name= tmp_name;
267  strmov(opt->name, dbname);
268  opt->name_length= length;
269 
270  if ((error= my_hash_insert(&dboptions, (uchar*) opt)))
271  {
272  my_free(opt);
273  goto end;
274  }
275  }
276 
277  /* Update / write options in hash */
278  opt->charset= create->default_table_charset;
279 
280 end:
281  mysql_rwlock_unlock(&LOCK_dboptions);
282  DBUG_RETURN(error);
283 }
284 
285 
286 /*
287  Deletes database options from the hash.
288 */
289 
290 static void del_dbopt(const char *path)
291 {
292  my_dbopt_t *opt;
293  mysql_rwlock_wrlock(&LOCK_dboptions);
294  if ((opt= (my_dbopt_t *)my_hash_search(&dboptions, (const uchar*) path,
295  strlen(path))))
296  my_hash_delete(&dboptions, (uchar*) opt);
297  mysql_rwlock_unlock(&LOCK_dboptions);
298 }
299 
300 
301 /*
302  Create database options file:
303 
304  DESCRIPTION
305  Currently database default charset is only stored there.
306 
307  RETURN VALUES
308  0 ok
309  1 Could not create file or write to it. Error sent through my_error()
310 */
311 
312 static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
313 {
314  register File file;
315  char buf[256]; // Should be enough for one option
316  bool error=1;
317 
318  if (!create->default_table_charset)
319  create->default_table_charset= thd->variables.collation_server;
320 
321  if (put_dbopt(path, create))
322  return 1;
323 
324  if ((file= mysql_file_create(key_file_dbopt, path, CREATE_MODE,
325  O_RDWR | O_TRUNC, MYF(MY_WME))) >= 0)
326  {
327  ulong length;
328  length= (ulong) (strxnmov(buf, sizeof(buf)-1, "default-character-set=",
329  create->default_table_charset->csname,
330  "\ndefault-collation=",
331  create->default_table_charset->name,
332  "\n", NullS) - buf);
333 
334  /* Error is written by mysql_file_write */
335  if (!mysql_file_write(file, (uchar*) buf, length, MYF(MY_NABP+MY_WME)))
336  error=0;
337  mysql_file_close(file, MYF(0));
338  }
339  return error;
340 }
341 
342 
343 /*
344  Load database options file
345 
346  load_db_opt()
347  path Path for option file
348  create Where to store the read options
349 
350  DESCRIPTION
351 
352  RETURN VALUES
353  0 File found
354  1 No database file or could not open it
355 
356 */
357 
358 bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
359 {
360  File file;
361  char buf[256];
362  DBUG_ENTER("load_db_opt");
363  bool error=1;
364  uint nbytes;
365 
366  memset(create, 0, sizeof(*create));
367  create->default_table_charset= thd->variables.collation_server;
368 
369  /* Check if options for this database are already in the hash */
370  if (!get_dbopt(path, create))
371  DBUG_RETURN(0);
372 
373  /* Otherwise, load options from the .opt file */
374  if ((file= mysql_file_open(key_file_dbopt,
375  path, O_RDONLY | O_SHARE, MYF(0))) < 0)
376  goto err1;
377 
378  IO_CACHE cache;
379  if (init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0)))
380  goto err2;
381 
382  while ((int) (nbytes= my_b_gets(&cache, (char*) buf, sizeof(buf))) > 0)
383  {
384  char *pos= buf+nbytes-1;
385  /* Remove end space and control characters */
386  while (pos > buf && !my_isgraph(&my_charset_latin1, pos[-1]))
387  pos--;
388  *pos=0;
389  if ((pos= strchr(buf, '=')))
390  {
391  if (!strncmp(buf,"default-character-set", (pos-buf)))
392  {
393  /*
394  Try character set name, and if it fails
395  try collation name, probably it's an old
396  4.1.0 db.opt file, which didn't have
397  separate default-character-set and
398  default-collation commands.
399  */
400  if (!(create->default_table_charset=
401  get_charset_by_csname(pos+1, MY_CS_PRIMARY, MYF(0))) &&
402  !(create->default_table_charset=
403  get_charset_by_name(pos+1, MYF(0))))
404  {
405  sql_print_error("Error while loading database options: '%s':",path);
406  sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1);
407  create->default_table_charset= default_charset_info;
408  }
409  }
410  else if (!strncmp(buf,"default-collation", (pos-buf)))
411  {
412  if (!(create->default_table_charset= get_charset_by_name(pos+1,
413  MYF(0))))
414  {
415  sql_print_error("Error while loading database options: '%s':",path);
416  sql_print_error(ER(ER_UNKNOWN_COLLATION),pos+1);
417  create->default_table_charset= default_charset_info;
418  }
419  }
420  }
421  }
422  /*
423  Put the loaded value into the hash.
424  Note that another thread could've added the same
425  entry to the hash after we called get_dbopt(),
426  but it's not an error, as put_dbopt() takes this
427  possibility into account.
428  */
429  error= put_dbopt(path, create);
430 
431  end_io_cache(&cache);
432 err2:
433  mysql_file_close(file, MYF(0));
434 err1:
435  DBUG_RETURN(error);
436 }
437 
438 
439 /*
440  Retrieve database options by name. Load database options file or fetch from
441  cache.
442 
443  SYNOPSIS
444  load_db_opt_by_name()
445  db_name Database name
446  db_create_info Where to store the database options
447 
448  DESCRIPTION
449  load_db_opt_by_name() is a shortcut for load_db_opt().
450 
451  NOTE
452  Although load_db_opt_by_name() (and load_db_opt()) returns status of
453  the operation, it is useless usually and should be ignored. The problem
454  is that there are 1) system databases ("mysql") and 2) virtual
455  databases ("information_schema"), which do not contain options file.
456  So, load_db_opt[_by_name]() returns FALSE for these databases, but this
457  is not an error.
458 
459  load_db_opt[_by_name]() clears db_create_info structure in any case, so
460  even on failure it contains valid data. So, common use case is just
461  call load_db_opt[_by_name]() without checking return value and use
462  db_create_info right after that.
463 
464  RETURN VALUES (read NOTE!)
465  FALSE Success
466  TRUE Failed to retrieve options
467 */
468 
469 bool load_db_opt_by_name(THD *thd, const char *db_name,
470  HA_CREATE_INFO *db_create_info)
471 {
472  char db_opt_path[FN_REFLEN + 1];
473 
474  /*
475  Pass an empty file name, and the database options file name as extension
476  to avoid table name to file name encoding.
477  */
478  (void) build_table_filename(db_opt_path, sizeof(db_opt_path) - 1,
479  db_name, "", MY_DB_OPT_FILE, 0);
480 
481  return load_db_opt(thd, db_opt_path, db_create_info);
482 }
483 
484 
495 const CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
496 {
497  HA_CREATE_INFO db_info;
498 
499  if (thd->db != NULL && strcmp(db_name, thd->db) == 0)
500  return thd->db_charset;
501 
502  load_db_opt_by_name(thd, db_name, &db_info);
503 
504  /*
505  NOTE: even if load_db_opt_by_name() fails,
506  db_info.default_table_charset contains valid character set
507  (collation_server). We should not fail if load_db_opt_by_name() fails,
508  because it is valid case. If a database has been created just by
509  "mkdir", it does not contain db.opt file, but it is valid database.
510  */
511 
512  return db_info.default_table_charset;
513 }
514 
515 
516 /*
517  Create a database
518 
519  SYNOPSIS
520  mysql_create_db()
521  thd Thread handler
522  db Name of database to create
523  Function assumes that this is already validated.
524  create_info Database create options (like character set)
525  silent Used by replication when internally creating a database.
526  In this case the entry should not be logged.
527 
528  SIDE-EFFECTS
529  1. Report back to client that command succeeded (my_ok)
530  2. Report errors to client
531  3. Log event to binary log
532  (The 'silent' flags turns off 1 and 3.)
533 
534  RETURN VALUES
535  FALSE ok
536  TRUE Error
537 
538 */
539 
540 int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
541  bool silent)
542 {
543  char path[FN_REFLEN+16];
544  char tmp_query[FN_REFLEN+16];
545  long result= 1;
546  int error= 0;
547  MY_STAT stat_info;
548  uint create_options= create_info ? create_info->options : 0;
549  uint path_len;
550  bool was_truncated;
551  DBUG_ENTER("mysql_create_db");
552 
553  /* do not create 'information_schema' db */
554  if (is_infoschema_db(db))
555  {
556  my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
557  DBUG_RETURN(-1);
558  }
559 
560  if (lock_schema_name(thd, db))
561  DBUG_RETURN(-1);
562 
563  /* Check directory */
564  path_len= build_table_filename(path, sizeof(path) - 1, db, "", "", 0,
565  &was_truncated);
566  if (was_truncated)
567  {
568  my_error(ER_IDENT_CAUSES_TOO_LONG_PATH, MYF(0), sizeof(path)-1, path);
569  DBUG_RETURN(-1);
570  }
571  path[path_len-1]= 0; // Remove last '/' from path
572 
573  if (mysql_file_stat(key_file_misc, path, &stat_info, MYF(0)))
574  {
575  if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
576  {
577  my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
578  error= -1;
579  goto exit;
580  }
581  push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
582  ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
583  error= 0;
584  goto not_silent;
585  }
586  else
587  {
588  if (my_errno != ENOENT)
589  {
590  char errbuf[MYSYS_STRERROR_SIZE];
591  my_error(EE_STAT, MYF(0), path,
592  my_errno, my_strerror(errbuf, sizeof(errbuf), my_errno));
593  goto exit;
594  }
595  if (my_mkdir(path,0777,MYF(0)) < 0)
596  {
597  my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno);
598  error= -1;
599  goto exit;
600  }
601  }
602 
603  path[path_len-1]= FN_LIBCHAR;
604  strmake(path+path_len, MY_DB_OPT_FILE, sizeof(path)-path_len-1);
605  if (write_db_opt(thd, path, create_info))
606  {
607  /*
608  Could not create options file.
609  Restore things to beginning.
610  */
611  path[path_len]= 0;
612  if (rmdir(path) >= 0)
613  {
614  error= -1;
615  goto exit;
616  }
617  /*
618  We come here when we managed to create the database, but not the option
619  file. In this case it's best to just continue as if nothing has
620  happened. (This is a very unlikely senario)
621  */
622  thd->clear_error();
623  }
624 
625 not_silent:
626  if (!silent)
627  {
628  char *query;
629  uint query_length;
630  char db_name_quoted[2 * FN_REFLEN + sizeof("create database ") + 2];
631  int id_len= 0;
632 
633  if (!thd->query()) // Only in replication
634  {
635  id_len= my_strmov_quoted_identifier(thd, (char *) db_name_quoted, db,
636  0);
637  db_name_quoted[id_len]= '\0';
638  query= tmp_query;
639  query_length= (uint) (strxmov(tmp_query,"create database ",
640  db_name_quoted, NullS) - tmp_query);
641  }
642  else
643  {
644  query= thd->query();
645  query_length= thd->query_length();
646  }
647 
648  ha_binlog_log_query(thd, 0, LOGCOM_CREATE_DB,
649  query, query_length,
650  db, "");
651 
652  if (mysql_bin_log.is_open())
653  {
654  int errcode= query_error_code(thd, TRUE);
655  Query_log_event qinfo(thd, query, query_length, FALSE, TRUE,
656  /* suppress_use */ TRUE, errcode);
657 
658  /*
659  Write should use the database being created as the "current
660  database" and not the threads current database, which is the
661  default. If we do not change the "current database" to the
662  database being created, the CREATE statement will not be
663  replicated when using --binlog-do-db to select databases to be
664  replicated.
665 
666  An example (--binlog-do-db=sisyfos):
667 
668  CREATE DATABASE bob; # Not replicated
669  USE bob; # 'bob' is the current database
670  CREATE DATABASE sisyfos; # Not replicated since 'bob' is
671  # current database.
672  USE sisyfos; # Will give error on slave since
673  # database does not exist.
674  */
675  qinfo.db = db;
676  qinfo.db_len = strlen(db);
677  thd->add_to_binlog_accessed_dbs(db);
678  /*
679  These DDL methods and logging are protected with the exclusive
680  metadata lock on the schema
681  */
682  if (mysql_bin_log.write_event(&qinfo))
683  {
684  error= -1;
685  goto exit;
686  }
687  }
688  my_ok(thd, result);
689  }
690 
691 exit:
692  DBUG_RETURN(error);
693 }
694 
695 
696 /* db-name is already validated when we come here */
697 
698 bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
699 {
700  char path[FN_REFLEN+16];
701  long result=1;
702  int error= 0;
703  DBUG_ENTER("mysql_alter_db");
704 
705  if (lock_schema_name(thd, db))
706  DBUG_RETURN(TRUE);
707 
708  /*
709  Recreate db options file: /dbpath/.db.opt
710  We pass MY_DB_OPT_FILE as "extension" to avoid
711  "table name to file name" encoding.
712  */
713  build_table_filename(path, sizeof(path) - 1, db, "", MY_DB_OPT_FILE, 0);
714  if ((error=write_db_opt(thd, path, create_info)))
715  goto exit;
716 
717  /* Change options if current database is being altered. */
718 
719  if (thd->db && !strcmp(thd->db,db))
720  {
721  thd->db_charset= create_info->default_table_charset ?
722  create_info->default_table_charset :
723  thd->variables.collation_server;
724  thd->variables.collation_database= thd->db_charset;
725  }
726 
727  ha_binlog_log_query(thd, 0, LOGCOM_ALTER_DB,
728  thd->query(), thd->query_length(),
729  db, "");
730 
731  if (mysql_bin_log.is_open())
732  {
733  int errcode= query_error_code(thd, TRUE);
734  Query_log_event qinfo(thd, thd->query(), thd->query_length(), FALSE, TRUE,
735  /* suppress_use */ TRUE, errcode);
736  /*
737  Write should use the database being created as the "current
738  database" and not the threads current database, which is the
739  default.
740  */
741  qinfo.db = db;
742  qinfo.db_len = strlen(db);
743 
744  /*
745  These DDL methods and logging are protected with the exclusive
746  metadata lock on the schema.
747  */
748  if ((error= mysql_bin_log.write_event(&qinfo)))
749  goto exit;
750  }
751  my_ok(thd, result);
752 
753 exit:
754  DBUG_RETURN(error);
755 }
756 
757 
773 bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
774 {
775  ulong deleted_tables= 0;
776  bool error= true;
777  char path[2 * FN_REFLEN + 16];
778  MY_DIR *dirp;
779  uint length;
780  bool found_other_files= false;
781  TABLE_LIST *tables= NULL;
782  TABLE_LIST *table;
783  Drop_table_error_handler err_handler;
784  DBUG_ENTER("mysql_rm_db");
785 
786 
787  if (lock_schema_name(thd, db))
788  DBUG_RETURN(true);
789 
790  length= build_table_filename(path, sizeof(path) - 1, db, "", "", 0);
791  strmov(path+length, MY_DB_OPT_FILE); // Append db option file name
792  del_dbopt(path); // Remove dboption hash entry
793  path[length]= '\0'; // Remove file name
794 
795  /* See if the directory exists */
796  if (!(dirp= my_dir(path,MYF(MY_DONT_SORT))))
797  {
798  if (!if_exists)
799  {
800  my_error(ER_DB_DROP_EXISTS, MYF(0), db);
801  DBUG_RETURN(true);
802  }
803  else
804  {
805  push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
806  ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
807  error= false;
808  goto update_binlog;
809  }
810  }
811 
812  if (find_db_tables_and_rm_known_files(thd, dirp, db, path, &tables,
813  &found_other_files))
814  goto exit;
815 
816  /*
817  Disable drop of enabled log tables, must be done before name locking.
818  This check is only needed if we are dropping the "mysql" database.
819  */
820  if ((my_strcasecmp(system_charset_info, MYSQL_SCHEMA_NAME.str, db) == 0))
821  {
822  for (table= tables; table; table= table->next_local)
823  {
824  if (check_if_log_table(table->db_length, table->db,
825  table->table_name_length, table->table_name, true))
826  {
827  my_error(ER_BAD_LOG_STATEMENT, MYF(0), "DROP");
828  goto exit;
829  }
830  }
831  }
832 
833  /* Lock all tables and stored routines about to be dropped. */
834  if (lock_table_names(thd, tables, NULL, thd->variables.lock_wait_timeout, 0) ||
835  lock_db_routines(thd, db))
836  goto exit;
837 
838  /* mysql_ha_rm_tables() requires a non-null TABLE_LIST. */
839  if (tables)
840  mysql_ha_rm_tables(thd, tables);
841 
842  for (table= tables; table; table= table->next_local)
843  {
844  tdc_remove_table(thd, TDC_RT_REMOVE_ALL, table->db, table->table_name,
845  false);
846  deleted_tables++;
847  }
848 
849  thd->push_internal_handler(&err_handler);
850  if (!thd->killed &&
851  !(tables &&
852  mysql_rm_table_no_locks(thd, tables, true, false, true, true)))
853  {
854  /*
855  We temporarily disable the binary log while dropping the objects
856  in the database. Since the DROP DATABASE statement is always
857  replicated as a statement, execution of it will drop all objects
858  in the database on the slave as well, so there is no need to
859  replicate the removal of the individual objects in the database
860  as well.
861 
862  This is more of a safety precaution, since normally no objects
863  should be dropped while the database is being cleaned, but in
864  the event that a change in the code to remove other objects is
865  made, these drops should still not be logged.
866 
867  Notice that the binary log have to be enabled over the call to
868  ha_drop_database(), since NDB otherwise detects the binary log
869  as disabled and will not log the drop database statement on any
870  other connected server.
871  */
872 
873  ha_drop_database(path);
874  tmp_disable_binlog(thd);
875  query_cache_invalidate1(db);
876  (void) sp_drop_db_routines(thd, db); /* @todo Do not ignore errors */
877 #ifdef HAVE_EVENT_SCHEDULER
879 #endif
880  reenable_binlog(thd);
881 
882  /*
883  If the directory is a symbolic link, remove the link first, then
884  remove the directory the symbolic link pointed at
885  */
886  if (found_other_files)
887  my_error(ER_DB_DROP_RMDIR, MYF(0), path, EEXIST);
888  else
889  error= rm_dir_w_symlink(path, true);
890  }
891  thd->pop_internal_handler();
892 
893 update_binlog:
894  if (!silent && !error)
895  {
896  const char *query;
897  ulong query_length;
898  // quoted db name + wraping quote
899  char buffer_temp [2 * FN_REFLEN + 2];
900  int id_len= 0;
901  if (!thd->query())
902  {
903  /* The client used the old obsolete mysql_drop_db() call */
904  query= path;
905  id_len= my_strmov_quoted_identifier(thd, buffer_temp, db, strlen(db));
906  buffer_temp[id_len] ='\0';
907  query_length= (uint) (strxmov(path, "DROP DATABASE ", buffer_temp, "",
908  NullS) - path);
909  }
910  else
911  {
912  query= thd->query();
913  query_length= thd->query_length();
914  }
915  if (mysql_bin_log.is_open())
916  {
917  int errcode= query_error_code(thd, TRUE);
918  Query_log_event qinfo(thd, query, query_length, FALSE, TRUE,
919  /* suppress_use */ TRUE, errcode);
920  /*
921  Write should use the database being created as the "current
922  database" and not the threads current database, which is the
923  default.
924  */
925  qinfo.db = db;
926  qinfo.db_len = strlen(db);
927 
928  /*
929  These DDL methods and logging are protected with the exclusive
930  metadata lock on the schema.
931  */
932  if (mysql_bin_log.write_event(&qinfo))
933  {
934  error= true;
935  goto exit;
936  }
937  }
938  thd->clear_error();
939  thd->server_status|= SERVER_STATUS_DB_DROPPED;
940  my_ok(thd, deleted_tables);
941  }
942  else if (mysql_bin_log.is_open() && !silent)
943  {
944  char *query, *query_pos, *query_end, *query_data_start;
945  char temp_identifier[ 2 * FN_REFLEN + 2];
946  TABLE_LIST *tbl;
947  uint db_len, id_length=0;
948 
949  if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN)))
950  goto exit; /* not much else we can do */
951  query_pos= query_data_start= strmov(query,"DROP TABLE IF EXISTS ");
952  query_end= query + MAX_DROP_TABLE_Q_LEN;
953  db_len= strlen(db);
954 
955  for (tbl= tables; tbl; tbl= tbl->next_local)
956  {
957  uint tbl_name_len;
958  bool exists;
959 
960  // Only write drop table to the binlog for tables that no longer exist.
961  if (check_if_table_exists(thd, tbl, &exists))
962  {
963  error= true;
964  goto exit;
965  }
966  if (exists)
967  continue;
968 
969  /* 3 for the quotes and the comma*/
970  tbl_name_len= strlen(tbl->table_name) + 3;
971  if (query_pos + tbl_name_len + 1 >= query_end)
972  {
973  /*
974  These DDL methods and logging are protected with the exclusive
975  metadata lock on the schema.
976  */
977  if (write_to_binlog(thd, query, query_pos -1 - query, db, db_len))
978  {
979  error= true;
980  goto exit;
981  }
982  query_pos= query_data_start;
983  }
984  id_length= my_strmov_quoted_identifier(thd, (char *)temp_identifier,
985  tbl->table_name, 0);
986  temp_identifier[id_length]= '\0';
987  query_pos= strmov(query_pos,(char *)&temp_identifier);
988  *query_pos++ = ',';
989  }
990 
991  if (query_pos != query_data_start)
992  {
993  thd->add_to_binlog_accessed_dbs(db);
994  /*
995  These DDL methods and logging are protected with the exclusive
996  metadata lock on the schema.
997  */
998  if (write_to_binlog(thd, query, query_pos -1 - query, db, db_len))
999  {
1000  error= true;
1001  goto exit;
1002  }
1003  }
1004  }
1005 
1006 exit:
1007  /*
1008  If this database was the client's selected database, we silently
1009  change the client's selected database to nothing (to have an empty
1010  SELECT DATABASE() in the future). For this we free() thd->db and set
1011  it to 0.
1012  */
1013  if (thd->db && !strcmp(thd->db, db) && !error)
1014  mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
1015  my_dirend(dirp);
1016  DBUG_RETURN(error);
1017 }
1018 
1019 
1020 static bool find_db_tables_and_rm_known_files(THD *thd, MY_DIR *dirp,
1021  const char *db,
1022  const char *path,
1023  TABLE_LIST **tables,
1024  bool *found_other_files)
1025 {
1026  char filePath[FN_REFLEN];
1027  TABLE_LIST *tot_list=0, **tot_list_next_local, **tot_list_next_global;
1028  DBUG_ENTER("find_db_tables_and_rm_known_files");
1029  DBUG_PRINT("enter",("path: %s", path));
1030  TYPELIB *known_extensions= ha_known_exts();
1031 
1032  tot_list_next_local= tot_list_next_global= &tot_list;
1033 
1034  for (uint idx=0 ;
1035  idx < (uint) dirp->number_off_files && !thd->killed ;
1036  idx++)
1037  {
1038  FILEINFO *file=dirp->dir_entry+idx;
1039  char *extension;
1040  DBUG_PRINT("info",("Examining: %s", file->name));
1041 
1042  /* skiping . and .. */
1043  if (file->name[0] == '.' && (!file->name[1] ||
1044  (file->name[1] == '.' && !file->name[2])))
1045  continue;
1046 
1047  if (file->name[0] == 'a' && file->name[1] == 'r' &&
1048  file->name[2] == 'c' && file->name[3] == '\0')
1049  {
1050  /* .frm archive:
1051  Those archives are obsolete, but following code should
1052  exist to remove existent "arc" directories.
1053  */
1054  char newpath[FN_REFLEN];
1055  MY_DIR *new_dirp;
1056  strxmov(newpath, path, "/", "arc", NullS);
1057  (void) unpack_filename(newpath, newpath);
1058  if ((new_dirp = my_dir(newpath, MYF(MY_DONT_SORT))))
1059  {
1060  DBUG_PRINT("my",("Archive subdir found: %s", newpath));
1061  if ((mysql_rm_arc_files(thd, new_dirp, newpath)) < 0)
1062  DBUG_RETURN(true);
1063  continue;
1064  }
1065  *found_other_files= true;
1066  continue;
1067  }
1068  if (!(extension= strrchr(file->name, '.')))
1069  extension= strend(file->name);
1070  if (find_type(extension, &deletable_extentions, FIND_TYPE_NO_PREFIX) <= 0)
1071  {
1072  if (find_type(extension, known_extensions, FIND_TYPE_NO_PREFIX) <= 0)
1073  *found_other_files= true;
1074  continue;
1075  }
1076  /* just for safety we use files_charset_info */
1077  if (db && !my_strcasecmp(files_charset_info,
1078  extension, reg_ext))
1079  {
1080  /* Drop the table nicely */
1081  *extension= 0; // Remove extension
1082  TABLE_LIST *table_list=(TABLE_LIST*)
1083  thd->calloc(sizeof(*table_list) +
1084  strlen(db) + 1 +
1085  MYSQL50_TABLE_NAME_PREFIX_LENGTH +
1086  strlen(file->name) + 1);
1087 
1088  if (!table_list)
1089  DBUG_RETURN(true);
1090  table_list->db= (char*) (table_list+1);
1091  table_list->db_length= strmov(table_list->db, db) - table_list->db;
1092  table_list->table_name= table_list->db + table_list->db_length + 1;
1093  table_list->table_name_length= filename_to_tablename(file->name,
1094  table_list->table_name,
1095  MYSQL50_TABLE_NAME_PREFIX_LENGTH +
1096  strlen(file->name) + 1);
1097  table_list->open_type= OT_BASE_ONLY;
1098 
1099  /* To be able to correctly look up the table in the table cache. */
1100  if (lower_case_table_names)
1101  table_list->table_name_length= my_casedn_str(files_charset_info,
1102  table_list->table_name);
1103 
1104  table_list->alias= table_list->table_name; // If lower_case_table_names=2
1105  table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix);
1106  table_list->mdl_request.init(MDL_key::TABLE, table_list->db,
1107  table_list->table_name, MDL_EXCLUSIVE,
1108  MDL_TRANSACTION);
1109  /* Link into list */
1110  (*tot_list_next_local)= table_list;
1111  (*tot_list_next_global)= table_list;
1112  tot_list_next_local= &table_list->next_local;
1113  tot_list_next_global= &table_list->next_global;
1114  }
1115  else
1116  {
1117  strxmov(filePath, path, "/", file->name, NullS);
1118  /*
1119  We ignore ENOENT error in order to skip files that was deleted
1120  by concurrently running statement like REAPIR TABLE ...
1121  */
1122  if (my_delete_with_symlink(filePath, MYF(0)) &&
1123  my_errno != ENOENT)
1124  {
1125  char errbuf[MYSYS_STRERROR_SIZE];
1126  my_error(EE_DELETE, MYF(0), filePath,
1127  my_errno, my_strerror(errbuf, sizeof(errbuf), my_errno));
1128  DBUG_RETURN(true);
1129  }
1130  }
1131  }
1132  *tables= tot_list;
1133  DBUG_RETURN(false);
1134 }
1135 
1136 
1137 /*
1138  Remove directory with symlink
1139 
1140  SYNOPSIS
1141  rm_dir_w_symlink()
1142  org_path path of derictory
1143  send_error send errors
1144  RETURN
1145  0 OK
1146  1 ERROR
1147 */
1148 
1149 static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error)
1150 {
1151  char tmp_path[FN_REFLEN], *pos;
1152  char *path= tmp_path;
1153  DBUG_ENTER("rm_dir_w_symlink");
1154  unpack_filename(tmp_path, org_path);
1155 #ifdef HAVE_READLINK
1156  int error;
1157  char tmp2_path[FN_REFLEN];
1158 
1159  /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
1160  pos= strend(path);
1161  if (pos > path && pos[-1] == FN_LIBCHAR)
1162  *--pos=0;
1163 
1164  if ((error= my_readlink(tmp2_path, path, MYF(MY_WME))) < 0)
1165  DBUG_RETURN(1);
1166  if (!error)
1167  {
1168  if (mysql_file_delete(key_file_misc, path, MYF(send_error ? MY_WME : 0)))
1169  {
1170  DBUG_RETURN(send_error);
1171  }
1172  /* Delete directory symbolic link pointed at */
1173  path= tmp2_path;
1174  }
1175 #endif
1176  /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
1177  pos= strend(path);
1178 
1179  if (pos > path && pos[-1] == FN_LIBCHAR)
1180  *--pos=0;
1181  if (rmdir(path) < 0 && send_error)
1182  {
1183  my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
1184  DBUG_RETURN(1);
1185  }
1186  DBUG_RETURN(0);
1187 }
1188 
1189 
1190 /*
1191  Remove .frm archives from directory
1192 
1193  SYNOPSIS
1194  thd thread handler
1195  dirp list of files in archive directory
1196  db data base name
1197  org_path path of archive directory
1198 
1199  RETURN
1200  > 0 number of removed files
1201  -1 error
1202 
1203  NOTE
1204  A support of "arc" directories is obsolete, however this
1205  function should exist to remove existent "arc" directories.
1206 */
1207 long mysql_rm_arc_files(THD *thd, MY_DIR *dirp, const char *org_path)
1208 {
1209  long deleted= 0;
1210  ulong found_other_files= 0;
1211  char filePath[FN_REFLEN];
1212  DBUG_ENTER("mysql_rm_arc_files");
1213  DBUG_PRINT("enter", ("path: %s", org_path));
1214 
1215  for (uint idx=0 ;
1216  idx < (uint) dirp->number_off_files && !thd->killed ;
1217  idx++)
1218  {
1219  FILEINFO *file=dirp->dir_entry+idx;
1220  char *extension, *revision;
1221  DBUG_PRINT("info",("Examining: %s", file->name));
1222 
1223  /* skiping . and .. */
1224  if (file->name[0] == '.' && (!file->name[1] ||
1225  (file->name[1] == '.' && !file->name[2])))
1226  continue;
1227 
1228  extension= fn_ext(file->name);
1229  if (extension[0] != '.' ||
1230  extension[1] != 'f' || extension[2] != 'r' ||
1231  extension[3] != 'm' || extension[4] != '-')
1232  {
1233  found_other_files++;
1234  continue;
1235  }
1236  revision= extension+5;
1237  while (*revision && my_isdigit(system_charset_info, *revision))
1238  revision++;
1239  if (*revision)
1240  {
1241  found_other_files++;
1242  continue;
1243  }
1244  strxmov(filePath, org_path, "/", file->name, NullS);
1245  if (mysql_file_delete_with_symlink(key_file_misc, filePath, MYF(MY_WME)))
1246  {
1247  goto err;
1248  }
1249  deleted++;
1250  }
1251  if (thd->killed)
1252  goto err;
1253 
1254  my_dirend(dirp);
1255 
1256  /*
1257  If the directory is a symbolic link, remove the link first, then
1258  remove the directory the symbolic link pointed at
1259  */
1260  if (!found_other_files &&
1261  rm_dir_w_symlink(org_path, 0))
1262  DBUG_RETURN(-1);
1263  DBUG_RETURN(deleted);
1264 
1265 err:
1266  my_dirend(dirp);
1267  DBUG_RETURN(-1);
1268 }
1269 
1270 
1283 static void mysql_change_db_impl(THD *thd,
1284  LEX_STRING *new_db_name,
1285  ulong new_db_access,
1286  const CHARSET_INFO *new_db_charset)
1287 {
1288  /* 1. Change current database in THD. */
1289 
1290  if (new_db_name == NULL)
1291  {
1292  /*
1293  THD::set_db() does all the job -- it frees previous database name and
1294  sets the new one.
1295  */
1296 
1297  thd->set_db(NULL, 0);
1298  }
1299  else if (new_db_name == &INFORMATION_SCHEMA_NAME)
1300  {
1301  /*
1302  Here we must use THD::set_db(), because we want to copy
1303  INFORMATION_SCHEMA_NAME constant.
1304  */
1305 
1306  thd->set_db(INFORMATION_SCHEMA_NAME.str, INFORMATION_SCHEMA_NAME.length);
1307  }
1308  else
1309  {
1310  /*
1311  Here we already have a copy of database name to be used in THD. So,
1312  we just call THD::reset_db(). Since THD::reset_db() does not releases
1313  the previous database name, we should do it explicitly.
1314  */
1315  mysql_mutex_lock(&thd->LOCK_thd_data);
1316  if (thd->db)
1317  my_free(thd->db);
1318  DEBUG_SYNC(thd, "after_freeing_thd_db");
1319  thd->reset_db(new_db_name->str, new_db_name->length);
1320  mysql_mutex_unlock(&thd->LOCK_thd_data);
1321  }
1322 
1323  /* 2. Update security context. */
1324 
1325 #ifndef NO_EMBEDDED_ACCESS_CHECKS
1326  thd->security_ctx->db_access= new_db_access;
1327 #endif
1328 
1329  /* 3. Update db-charset environment variables. */
1330 
1331  thd->db_charset= new_db_charset;
1332  thd->variables.collation_database= new_db_charset;
1333 }
1334 
1335 
1336 
1352 static void backup_current_db_name(THD *thd,
1353  LEX_STRING *saved_db_name)
1354 {
1355  if (!thd->db)
1356  {
1357  /* No current (default) database selected. */
1358 
1359  saved_db_name->str= NULL;
1360  saved_db_name->length= 0;
1361  }
1362  else
1363  {
1364  strmake(saved_db_name->str, thd->db, saved_db_name->length - 1);
1365  saved_db_name->length= thd->db_length;
1366  }
1367 }
1368 
1369 
1381 static inline bool
1382 cmp_db_names(const char *db1_name,
1383  const char *db2_name)
1384 {
1385  return
1386  /* db1 is NULL and db2 is NULL */
1387  (!db1_name && !db2_name) ||
1388 
1389  /* db1 is not-NULL, db2 is not-NULL, db1 == db2. */
1390  (db1_name && db2_name &&
1391  my_strcasecmp(system_charset_info, db1_name, db2_name) == 0);
1392 }
1393 
1394 
1457 bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
1458 {
1459  LEX_STRING new_db_file_name;
1460 
1461  Security_context *sctx= thd->security_ctx;
1462  ulong db_access= sctx->db_access;
1463  const CHARSET_INFO *db_default_cl;
1464 
1465  DBUG_ENTER("mysql_change_db");
1466  DBUG_PRINT("enter",("name: '%s'", new_db_name->str));
1467 
1468  if (new_db_name == NULL ||
1469  new_db_name->length == 0)
1470  {
1471  if (force_switch)
1472  {
1473  /*
1474  This can happen only if we're switching the current database back
1475  after loading stored program. The thing is that loading of stored
1476  program can happen when there is no current database.
1477 
1478  TODO: actually, new_db_name and new_db_name->str seem to be always
1479  non-NULL. In case of stored program, new_db_name->str == "" and
1480  new_db_name->length == 0.
1481  */
1482 
1483  mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
1484 
1485  DBUG_RETURN(FALSE);
1486  }
1487  else
1488  {
1489  my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1490 
1491  DBUG_RETURN(TRUE);
1492  }
1493  }
1494 
1495  if (is_infoschema_db(new_db_name->str, new_db_name->length))
1496  {
1497  /* Switch the current database to INFORMATION_SCHEMA. */
1498 
1499  mysql_change_db_impl(thd, &INFORMATION_SCHEMA_NAME, SELECT_ACL,
1500  system_charset_info);
1501 
1502  DBUG_RETURN(FALSE);
1503  }
1504 
1505  /*
1506  Now we need to make a copy because check_db_name requires a
1507  non-constant argument. Actually, it takes database file name.
1508 
1509  TODO: fix check_db_name().
1510  */
1511 
1512  new_db_file_name.str= my_strndup(new_db_name->str, new_db_name->length,
1513  MYF(MY_WME));
1514  new_db_file_name.length= new_db_name->length;
1515 
1516  if (new_db_file_name.str == NULL)
1517  DBUG_RETURN(TRUE); /* the error is set */
1518 
1519  /*
1520  NOTE: if check_db_name() fails, we should throw an error in any case,
1521  even if we are called from sp_head::execute().
1522 
1523  It's next to impossible however to get this error when we are called
1524  from sp_head::execute(). But let's switch the current database to NULL
1525  in this case to be sure.
1526  */
1527 
1528  if (check_and_convert_db_name(&new_db_file_name, FALSE) != IDENT_NAME_OK)
1529  {
1530  my_free(new_db_file_name.str);
1531 
1532  if (force_switch)
1533  mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
1534  DBUG_RETURN(TRUE);
1535  }
1536 
1537  DBUG_PRINT("info",("Use database: %s", new_db_file_name.str));
1538 
1539 #ifndef NO_EMBEDDED_ACCESS_CHECKS
1540  db_access=
1541  test_all_bits(sctx->master_access, DB_ACLS) ?
1542  DB_ACLS :
1543  acl_get(sctx->get_host()->ptr(),
1544  sctx->get_ip()->ptr(),
1545  sctx->priv_user,
1546  new_db_file_name.str,
1547  FALSE) | sctx->master_access;
1548 
1549  if (!force_switch &&
1550  !(db_access & DB_ACLS) &&
1551  check_grant_db(thd, new_db_file_name.str))
1552  {
1553  my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
1554  sctx->priv_user,
1555  sctx->priv_host,
1556  new_db_file_name.str);
1557  general_log_print(thd, COM_INIT_DB, ER(ER_DBACCESS_DENIED_ERROR),
1558  sctx->priv_user, sctx->priv_host, new_db_file_name.str);
1559  my_free(new_db_file_name.str);
1560  DBUG_RETURN(TRUE);
1561  }
1562 #endif
1563 
1564  DEBUG_SYNC(thd, "before_db_dir_check");
1565 
1566  if (check_db_dir_existence(new_db_file_name.str))
1567  {
1568  if (force_switch)
1569  {
1570  /* Throw a warning and free new_db_file_name. */
1571 
1572  push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
1573  ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
1574  new_db_file_name.str);
1575 
1576  my_free(new_db_file_name.str);
1577 
1578  /* Change db to NULL. */
1579 
1580  mysql_change_db_impl(thd, NULL, 0, thd->variables.collation_server);
1581 
1582  /* The operation succeed. */
1583 
1584  DBUG_RETURN(FALSE);
1585  }
1586  else
1587  {
1588  /* Report an error and free new_db_file_name. */
1589 
1590  my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
1591  my_free(new_db_file_name.str);
1592 
1593  /* The operation failed. */
1594 
1595  DBUG_RETURN(TRUE);
1596  }
1597  }
1598 
1599  /*
1600  NOTE: in mysql_change_db_impl() new_db_file_name is assigned to THD
1601  attributes and will be freed in THD::~THD().
1602  */
1603 
1604  db_default_cl= get_default_db_collation(thd, new_db_file_name.str);
1605 
1606  mysql_change_db_impl(thd, &new_db_file_name, db_access, db_default_cl);
1607 
1608  DBUG_RETURN(FALSE);
1609 }
1610 
1611 
1632 bool mysql_opt_change_db(THD *thd,
1633  const LEX_STRING *new_db_name,
1634  LEX_STRING *saved_db_name,
1635  bool force_switch,
1636  bool *cur_db_changed)
1637 {
1638  *cur_db_changed= !cmp_db_names(thd->db, new_db_name->str);
1639 
1640  if (!*cur_db_changed)
1641  return FALSE;
1642 
1643  backup_current_db_name(thd, saved_db_name);
1644 
1645  return mysql_change_db(thd, new_db_name, force_switch);
1646 }
1647 
1648 
1663 bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
1664 {
1665  int error= 0, change_to_newdb= 0;
1666  char path[FN_REFLEN+16];
1667  uint length;
1668  HA_CREATE_INFO create_info;
1669  MY_DIR *dirp;
1670  TABLE_LIST *table_list;
1671  SELECT_LEX *sl= thd->lex->current_select;
1672  LEX_STRING new_db;
1673  DBUG_ENTER("mysql_upgrade_db");
1674 
1675  if ((old_db->length <= MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
1676  (strncmp(old_db->str,
1677  MYSQL50_TABLE_NAME_PREFIX,
1678  MYSQL50_TABLE_NAME_PREFIX_LENGTH) != 0))
1679  {
1680  my_error(ER_WRONG_USAGE, MYF(0),
1681  "ALTER DATABASE UPGRADE DATA DIRECTORY NAME",
1682  "name");
1683  DBUG_RETURN(1);
1684  }
1685 
1686  /* `#mysql50#<name>` converted to encoded `<name>` */
1687  new_db.str= old_db->str + MYSQL50_TABLE_NAME_PREFIX_LENGTH;
1688  new_db.length= old_db->length - MYSQL50_TABLE_NAME_PREFIX_LENGTH;
1689 
1690  /* Lock the old name, the new name will be locked by mysql_create_db().*/
1691  if (lock_schema_name(thd, old_db->str))
1692  DBUG_RETURN(-1);
1693 
1694  /*
1695  Let's remember if we should do "USE newdb" afterwards.
1696  thd->db will be cleared in mysql_rename_db()
1697  */
1698  if (thd->db && !strcmp(thd->db, old_db->str))
1699  change_to_newdb= 1;
1700 
1701  build_table_filename(path, sizeof(path)-1,
1702  old_db->str, "", MY_DB_OPT_FILE, 0);
1703  if ((load_db_opt(thd, path, &create_info)))
1704  create_info.default_table_charset= thd->variables.collation_server;
1705 
1706  length= build_table_filename(path, sizeof(path)-1, old_db->str, "", "", 0);
1707  if (length && path[length-1] == FN_LIBCHAR)
1708  path[length-1]=0; // remove ending '\'
1709  if ((error= my_access(path,F_OK)))
1710  {
1711  my_error(ER_BAD_DB_ERROR, MYF(0), old_db->str);
1712  goto exit;
1713  }
1714 
1715  /* Step1: Create the new database */
1716  if ((error= mysql_create_db(thd, new_db.str, &create_info, 1)))
1717  goto exit;
1718 
1719  /* Step2: Move tables to the new database */
1720  if ((dirp = my_dir(path,MYF(MY_DONT_SORT))))
1721  {
1722  uint nfiles= (uint) dirp->number_off_files;
1723  for (uint idx=0 ; idx < nfiles && !thd->killed ; idx++)
1724  {
1725  FILEINFO *file= dirp->dir_entry + idx;
1726  char *extension, tname[FN_REFLEN + 1];
1727  LEX_STRING table_str;
1728  DBUG_PRINT("info",("Examining: %s", file->name));
1729 
1730  /* skiping non-FRM files */
1731  if (my_strcasecmp(files_charset_info,
1732  (extension= fn_rext(file->name)), reg_ext))
1733  continue;
1734 
1735  /* A frm file found, add the table info rename list */
1736  *extension= '\0';
1737 
1738  table_str.length= filename_to_tablename(file->name,
1739  tname, sizeof(tname)-1);
1740  table_str.str= (char*) sql_memdup(tname, table_str.length + 1);
1741  Table_ident *old_ident= new Table_ident(thd, *old_db, table_str, 0);
1742  Table_ident *new_ident= new Table_ident(thd, new_db, table_str, 0);
1743  if (!old_ident || !new_ident ||
1744  !sl->add_table_to_list(thd, old_ident, NULL,
1745  TL_OPTION_UPDATING, TL_IGNORE,
1746  MDL_EXCLUSIVE) ||
1747  !sl->add_table_to_list(thd, new_ident, NULL,
1748  TL_OPTION_UPDATING, TL_IGNORE,
1749  MDL_EXCLUSIVE))
1750  {
1751  error= 1;
1752  my_dirend(dirp);
1753  goto exit;
1754  }
1755  }
1756  my_dirend(dirp);
1757  }
1758 
1759  if ((table_list= thd->lex->query_tables) &&
1760  (error= mysql_rename_tables(thd, table_list, 1)))
1761  {
1762  /*
1763  Failed to move all tables from the old database to the new one.
1764  In the best case mysql_rename_tables() moved all tables back to the old
1765  database. In the worst case mysql_rename_tables() moved some tables
1766  to the new database, then failed, then started to move the tables back,
1767  and then failed again. In this situation we have some tables in the
1768  old database and some tables in the new database.
1769  Let's delete the option file, and then the new database directory.
1770  If some tables were left in the new directory, rmdir() will fail.
1771  It garantees we never loose any tables.
1772  */
1773  build_table_filename(path, sizeof(path)-1,
1774  new_db.str,"",MY_DB_OPT_FILE, 0);
1775  mysql_file_delete(key_file_dbopt, path, MYF(MY_WME));
1776  length= build_table_filename(path, sizeof(path)-1, new_db.str, "", "", 0);
1777  if (length && path[length-1] == FN_LIBCHAR)
1778  path[length-1]=0; // remove ending '\'
1779  rmdir(path);
1780  goto exit;
1781  }
1782 
1783 
1784  /*
1785  Step3: move all remaining files to the new db's directory.
1786  Skip db opt file: it's been created by mysql_create_db() in
1787  the new directory, and will be dropped by mysql_rm_db() in the old one.
1788  Trigger TRN and TRG files are be moved as regular files at the moment,
1789  without any special treatment.
1790 
1791  Triggers without explicit database qualifiers in table names work fine:
1792  use d1;
1793  create trigger trg1 before insert on t2 for each row set @a:=1
1794  rename database d1 to d2;
1795 
1796  TODO: Triggers, having the renamed database explicitely written
1797  in the table qualifiers.
1798  1. when the same database is renamed:
1799  create trigger d1.trg1 before insert on d1.t1 for each row set @a:=1;
1800  rename database d1 to d2;
1801  Problem: After database renaming, the trigger's body
1802  still points to the old database d1.
1803  2. when another database is renamed:
1804  create trigger d3.trg1 before insert on d3.t1 for each row
1805  insert into d1.t1 values (...);
1806  rename database d1 to d2;
1807  Problem: After renaming d1 to d2, the trigger's body
1808  in the database d3 still points to database d1.
1809  */
1810 
1811  if ((dirp = my_dir(path,MYF(MY_DONT_SORT))))
1812  {
1813  uint nfiles= (uint) dirp->number_off_files;
1814  for (uint idx=0 ; idx < nfiles ; idx++)
1815  {
1816  FILEINFO *file= dirp->dir_entry + idx;
1817  char oldname[FN_REFLEN + 1], newname[FN_REFLEN + 1];
1818  DBUG_PRINT("info",("Examining: %s", file->name));
1819 
1820  /* skiping . and .. and MY_DB_OPT_FILE */
1821  if ((file->name[0] == '.' &&
1822  (!file->name[1] || (file->name[1] == '.' && !file->name[2]))) ||
1823  !my_strcasecmp(files_charset_info, file->name, MY_DB_OPT_FILE))
1824  continue;
1825 
1826  /* pass empty file name, and file->name as extension to avoid encoding */
1827  build_table_filename(oldname, sizeof(oldname)-1,
1828  old_db->str, "", file->name, 0);
1829  build_table_filename(newname, sizeof(newname)-1,
1830  new_db.str, "", file->name, 0);
1831  mysql_file_rename(key_file_misc, oldname, newname, MYF(MY_WME));
1832  }
1833  my_dirend(dirp);
1834  }
1835 
1836  /*
1837  Step7: drop the old database.
1838  query_cache_invalidate(olddb) is done inside mysql_rm_db(), no need
1839  to execute them again.
1840  mysql_rm_db() also "unuses" if we drop the current database.
1841  */
1842  error= mysql_rm_db(thd, old_db->str, 0, 1);
1843 
1844  /* Step8: logging */
1845  if (mysql_bin_log.is_open())
1846  {
1847  int errcode= query_error_code(thd, TRUE);
1848  Query_log_event qinfo(thd, thd->query(), thd->query_length(),
1849  FALSE, TRUE, TRUE, errcode);
1850  thd->clear_error();
1851  error|= mysql_bin_log.write_event(&qinfo);
1852  }
1853 
1854  /* Step9: Let's do "use newdb" if we renamed the current database */
1855  if (change_to_newdb)
1856  error|= mysql_change_db(thd, & new_db, FALSE);
1857 
1858 exit:
1859  DBUG_RETURN(error);
1860 }
1861 
1862 
1863 
1864 /*
1865  Check if there is directory for the database name.
1866 
1867  SYNOPSIS
1868  check_db_dir_existence()
1869  db_name database name
1870 
1871  RETURN VALUES
1872  FALSE There is directory for the specified database name.
1873  TRUE The directory does not exist.
1874 */
1875 
1876 bool check_db_dir_existence(const char *db_name)
1877 {
1878  char db_dir_path[FN_REFLEN + 1];
1879  uint db_dir_path_len;
1880 
1881  db_dir_path_len= build_table_filename(db_dir_path, sizeof(db_dir_path) - 1,
1882  db_name, "", "", 0);
1883 
1884  if (db_dir_path_len && db_dir_path[db_dir_path_len - 1] == FN_LIBCHAR)
1885  db_dir_path[db_dir_path_len - 1]= 0;
1886 
1887  /* Check access. */
1888 
1889  return my_access(db_dir_path, F_OK);
1890 }