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