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