~drizzle-trunk/drizzle/development

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