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