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