~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/sql_db.cc

  • Committer: Toru Maesaka
  • Date: 2008-07-17 05:59:20 UTC
  • mto: (202.1.1 toru)
  • mto: This revision was merged to the branch mainline in revision 204.
  • Revision ID: dev@torum.net-20080717055920-10okif50x6nh7b1d
forgot to bzr-add new files in the previous push

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
 
17
17
/* create and drop of databases */
18
 
#include "config.h"
19
 
#include <string>
20
 
#include <fstream>
21
 
#include <drizzled/serialize/serialize.h>
22
 
using namespace std;
23
 
#include <drizzled/server_includes.h>
24
 
#include <mysys/mysys_err.h>
25
 
#include <mysys/my_dir.h>
 
18
 
 
19
#include "mysql_priv.h"
 
20
#include <mysys_err.h>
 
21
#include <my_dir.h>
 
22
#include <m_ctype.h>
26
23
#include "log.h"
27
 
#include <drizzled/drizzled_error_messages.h>
28
 
#include <libdrizzle/gettext.h>
29
 
 
30
24
 
31
25
#define MAX_DROP_TABLE_Q_LEN      1024
32
26
 
33
 
const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NULL};
 
27
const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS};
34
28
static TYPELIB deletable_extentions=
35
29
{array_elements(del_exts)-1,"del_exts", del_exts, NULL};
36
30
 
37
31
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
38
 
                                 const char *db, const char *path, uint32_t level, 
39
 
                                 TableList **dropped_tables);
 
32
                                 const char *db, const char *path, uint level, 
 
33
                                 TABLE_LIST **dropped_tables);
40
34
         
41
 
static bool rm_dir_w_symlink(const char *org_path, bool send_error);
 
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);
42
37
static void mysql_change_db_impl(THD *thd,
43
38
                                 LEX_STRING *new_db_name,
44
 
                                 const CHARSET_INFO * const new_db_charset);
 
39
                                 CHARSET_INFO *new_db_charset);
45
40
 
46
41
 
47
42
/* Database lock hash */
54
49
typedef struct my_dblock_st
55
50
{
56
51
  char *name;        /* Database name        */
57
 
  uint32_t name_length;  /* Database length name */
 
52
  uint name_length;  /* Database length name */
58
53
} my_dblock_t;
59
54
 
60
55
 
62
57
  lock_db key.
63
58
*/
64
59
 
65
 
extern "C" unsigned char* lock_db_get_key(my_dblock_t *, size_t *, bool not_used);
 
60
extern "C" uchar* lock_db_get_key(my_dblock_t *, size_t *, my_bool not_used);
66
61
 
67
 
unsigned char* lock_db_get_key(my_dblock_t *ptr, size_t *length,
68
 
                       bool not_used __attribute__((unused)))
 
62
uchar* lock_db_get_key(my_dblock_t *ptr, size_t *length,
 
63
                       my_bool not_used __attribute__((unused)))
69
64
{
70
65
  *length= ptr->name_length;
71
 
  return (unsigned char*) ptr->name;
 
66
  return (uchar*) ptr->name;
72
67
}
73
68
 
74
69
 
80
75
 
81
76
void lock_db_free_element(void *ptr)
82
77
{
83
 
  free(ptr);
 
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:
 
123
  return(error);
84
124
}
85
125
 
86
126
 
88
128
  Delete a database lock entry from hash.
89
129
*/
90
130
 
91
 
void lock_db_delete(const char *name, uint32_t length)
 
131
void lock_db_delete(const char *name, uint length)
92
132
{
93
133
  my_dblock_t *opt;
94
134
  safe_mutex_assert_owner(&LOCK_lock_db);
95
135
  if ((opt= (my_dblock_t *)hash_search(&lock_db_cache,
96
 
                                       (const unsigned char*) name, length)))
97
 
    hash_delete(&lock_db_cache, (unsigned char*) opt);
 
136
                                       (const uchar*) name, length)))
 
137
    hash_delete(&lock_db_cache, (uchar*) opt);
98
138
}
99
139
 
100
140
 
101
141
/* Database options hash */
102
142
static HASH dboptions;
103
 
static bool dboptions_init= 0;
 
143
static my_bool dboptions_init= 0;
104
144
static rw_lock_t LOCK_dboptions;
105
145
 
106
146
/* Structure for database options */
107
147
typedef struct my_dbopt_st
108
148
{
109
149
  char *name;                   /* Database name                  */
110
 
  uint32_t name_length;         /* Database length name           */
111
 
  const CHARSET_INFO *charset;  /* Database default character set */
 
150
  uint name_length;             /* Database length name           */
 
151
  CHARSET_INFO *charset;        /* Database default character set */
112
152
} my_dbopt_t;
113
153
 
114
154
 
116
156
  Function we use in the creation of our hash to get key.
117
157
*/
118
158
 
119
 
extern "C" unsigned char* dboptions_get_key(my_dbopt_t *opt, size_t *length,
120
 
                                    bool not_used);
 
159
extern "C" uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length,
 
160
                                    my_bool not_used);
121
161
 
122
 
unsigned char* dboptions_get_key(my_dbopt_t *opt, size_t *length,
123
 
                         bool not_used __attribute__((unused)))
 
162
uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length,
 
163
                         my_bool not_used __attribute__((unused)))
124
164
{
125
165
  *length= opt->name_length;
126
 
  return (unsigned char*) opt->name;
 
166
  return (uchar*) opt->name;
127
167
}
128
168
 
129
169
 
131
171
  Helper function to write a query to binlog used by mysql_rm_db()
132
172
*/
133
173
 
134
 
static inline void write_to_binlog(THD *thd, char *query, uint32_t q_len,
135
 
                                   char *db, uint32_t db_len)
 
174
static inline void write_to_binlog(THD *thd, char *query, uint q_len,
 
175
                                   char *db, uint db_len)
136
176
{
137
177
  Query_log_event qinfo(thd, query, q_len, 0, 0);
138
178
  qinfo.error_code= 0;
150
190
 
151
191
void free_dbopt(void *dbopt)
152
192
{
153
 
  free((unsigned char*) dbopt);
 
193
  my_free((uchar*) dbopt, MYF(0));
154
194
}
155
195
 
156
196
 
170
210
 
171
211
bool my_database_names_init(void)
172
212
{
173
 
  bool error= false;
 
213
  bool error= 0;
174
214
  (void) my_rwlock_init(&LOCK_dboptions, NULL);
175
215
  if (!dboptions_init)
176
216
  {
234
274
    1 on error.
235
275
*/
236
276
 
237
 
static bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
 
277
static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
238
278
{
239
279
  my_dbopt_t *opt;
240
 
  uint32_t length;
241
 
  bool error= true;
 
280
  uint length;
 
281
  my_bool error= 1;
242
282
  
243
283
  length= (uint) strlen(dbname);
244
284
  
245
285
  rw_rdlock(&LOCK_dboptions);
246
 
  if ((opt= (my_dbopt_t*) hash_search(&dboptions, (unsigned char*) dbname, length)))
 
286
  if ((opt= (my_dbopt_t*) hash_search(&dboptions, (uchar*) dbname, length)))
247
287
  {
248
288
    create->default_table_charset= opt->charset;
249
 
    error= true;
 
289
    error= 0;
250
290
  }
251
291
  rw_unlock(&LOCK_dboptions);
252
292
  return error;
265
305
    1 on error.
266
306
*/
267
307
 
268
 
static bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
 
308
static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
269
309
{
270
310
  my_dbopt_t *opt;
271
 
  uint32_t length;
272
 
  bool error= false;
 
311
  uint length;
 
312
  my_bool error= 0;
273
313
 
274
314
  length= (uint) strlen(dbname);
275
315
  
276
316
  rw_wrlock(&LOCK_dboptions);
277
 
  if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (unsigned char*) dbname, length)))
 
317
  if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (uchar*) dbname, length)))
278
318
  { 
279
319
    /* Options are not in the hash, insert them */
280
320
    char *tmp_name;
281
321
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
282
322
                         &opt, (uint) sizeof(*opt), &tmp_name, (uint) length+1,
283
 
                         NULL))
 
323
                         NullS))
284
324
    {
285
 
      error= true;
 
325
      error= 1;
286
326
      goto end;
287
327
    }
288
328
    
289
329
    opt->name= tmp_name;
290
 
    my_stpcpy(opt->name, dbname);
 
330
    strmov(opt->name, dbname);
291
331
    opt->name_length= length;
292
332
    
293
 
    if ((error= my_hash_insert(&dboptions, (unsigned char*) opt)))
 
333
    if ((error= my_hash_insert(&dboptions, (uchar*) opt)))
294
334
    {
295
 
      free(opt);
 
335
      my_free(opt, MYF(0));
296
336
      goto end;
297
337
    }
298
338
  }
314
354
{
315
355
  my_dbopt_t *opt;
316
356
  rw_wrlock(&LOCK_dboptions);
317
 
  if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const unsigned char*) path,
 
357
  if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const uchar*) path,
318
358
                                      strlen(path))))
319
 
    hash_delete(&dboptions, (unsigned char*) opt);
 
359
    hash_delete(&dboptions, (uchar*) opt);
320
360
  rw_unlock(&LOCK_dboptions);
321
361
}
322
362
 
332
372
  1     Could not create file or write to it.  Error sent through my_error()
333
373
*/
334
374
 
335
 
static bool write_db_opt(THD *thd, const char *path, const char *name, HA_CREATE_INFO *create)
 
375
static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
336
376
{
337
 
  bool error= true;
338
 
  drizzle::Schema db;
339
 
 
340
 
  assert(name);
 
377
  register File file;
 
378
  char buf[256]; // Should be enough for one option
 
379
  bool error=1;
341
380
 
342
381
  if (!create->default_table_charset)
343
382
    create->default_table_charset= thd->variables.collation_server;
345
384
  if (put_dbopt(path, create))
346
385
    return 1;
347
386
 
348
 
  db.set_name(name);
349
 
  db.set_characterset(create->default_table_charset->csname);
350
 
  db.set_collation(create->default_table_charset->name);
351
 
 
352
 
  fstream output(path, ios::out | ios::trunc | ios::binary);
353
 
  if (!db.SerializeToOstream(&output)) 
354
 
    error= false;
355
 
 
 
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
  }
356
401
  return error;
357
402
}
358
403
 
374
419
 
375
420
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
376
421
{
 
422
  File file;
 
423
  char buf[256];
377
424
  bool error=1;
378
 
  drizzle::Schema db;
379
 
  string buffer;
 
425
  uint nbytes;
380
426
 
381
 
  memset(create, 0, sizeof(*create));
 
427
  bzero((char*) create,sizeof(*create));
382
428
  create->default_table_charset= thd->variables.collation_server;
383
429
 
384
430
  /* Check if options for this database are already in the hash */
385
431
  if (!get_dbopt(path, create))
386
432
    return(0);
387
433
 
388
 
  fstream input(path, ios::in | ios::binary);
389
 
  if (!input)
390
 
    goto err1;
391
 
  else if (!db.ParseFromIstream(&input))
392
 
    goto err1;
393
 
 
394
 
  buffer= db.characterset();
395
 
  if (!(create->default_table_charset= get_charset_by_csname(buffer.c_str(), MY_CS_PRIMARY, MYF(0))))
396
 
  {
397
 
    sql_print_error(_("Error while loading database options: '%s':"),path);
398
 
    sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
399
 
    create->default_table_charset= default_charset_info;
400
 
  }
401
 
 
402
 
  buffer= db.collation();
403
 
  if (!(create->default_table_charset= get_charset_by_name(buffer.c_str(), MYF(0))))
404
 
  {
405
 
    sql_print_error(_("Error while loading database options: '%s':"),path);
406
 
    sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
407
 
    create->default_table_charset= default_charset_info;
408
 
  }
409
 
 
 
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
  }
410
482
  /*
411
483
    Put the loaded value into the hash.
412
484
    Note that another thread could've added the same
416
488
  */
417
489
  error= put_dbopt(path, create);
418
490
 
 
491
  end_io_cache(&cache);
 
492
err2:
 
493
  my_close(file,MYF(0));
419
494
err1:
420
495
  return(error);
421
496
}
477
552
    set, even if the database does not exist.
478
553
*/
479
554
 
480
 
const CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
 
555
CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
481
556
{
482
557
  HA_CREATE_INFO db_info;
483
558
 
522
597
 
523
598
*/
524
599
 
525
 
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent)
 
600
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
 
601
                     bool silent)
526
602
{
527
603
  char   path[FN_REFLEN+16];
528
604
  char   tmp_query[FN_REFLEN+16];
529
605
  long result= 1;
530
606
  int error= 0;
531
607
  struct stat stat_info;
532
 
  uint32_t create_options= create_info ? create_info->options : 0;
533
 
  uint32_t path_len;
 
608
  uint create_options= create_info ? create_info->options : 0;
 
609
  uint path_len;
534
610
 
535
611
  /* do not create 'information_schema' db */
536
612
  if (!my_strcasecmp(system_charset_info, db, INFORMATION_SCHEMA_NAME.str))
557
633
    goto exit2;
558
634
  }
559
635
 
560
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
 
636
  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
561
637
 
562
638
  /* Check directory */
563
639
  path_len= build_table_filename(path, sizeof(path), db, "", "", 0);
571
647
      error= -1;
572
648
      goto exit;
573
649
    }
574
 
    push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
650
    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
575
651
                        ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
576
652
    if (!silent)
577
653
      my_ok(thd);
595
671
 
596
672
  path[path_len-1]= FN_LIBCHAR;
597
673
  strmake(path+path_len, MY_DB_OPT_FILE, sizeof(path)-path_len-1);
598
 
  if (write_db_opt(thd, path, db, create_info))
 
674
  if (write_db_opt(thd, path, create_info))
599
675
  {
600
676
    /*
601
677
      Could not create options file.
617
693
  if (!silent)
618
694
  {
619
695
    char *query;
620
 
    uint32_t query_length;
 
696
    uint query_length;
621
697
 
622
698
    if (!thd->query)                            // Only in replication
623
699
    {
624
700
      query=         tmp_query;
625
701
      query_length= (uint) (strxmov(tmp_query,"create database `",
626
 
                                    db, "`", NULL) - tmp_query);
 
702
                                    db, "`", NullS) - tmp_query);
627
703
    }
628
704
    else
629
705
    {
631
707
      query_length= thd->query_length;
632
708
    }
633
709
 
 
710
    ha_binlog_log_query(thd, 0, LOGCOM_CREATE_DB,
 
711
                        query, query_length,
 
712
                        db, "");
 
713
 
634
714
    if (mysql_bin_log.is_open())
635
715
    {
636
716
      Query_log_event qinfo(thd, query, query_length, 0, 
663
743
  }
664
744
 
665
745
exit:
666
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
 
746
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
667
747
  start_waiting_global_read_lock(thd);
668
748
exit2:
669
749
  return(error);
676
756
{
677
757
  char path[FN_REFLEN+16];
678
758
  long result=1;
679
 
  int error= false;
 
759
  int error= 0;
680
760
 
681
761
  /*
682
762
    Do not alter database if another thread is holding read lock.
693
773
  if ((error=wait_if_global_read_lock(thd,0,1)))
694
774
    goto exit2;
695
775
 
696
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
 
776
  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
697
777
 
698
778
  /* 
699
779
     Recreate db options file: /dbpath/.db.opt
701
781
     "table name to file name" encoding.
702
782
  */
703
783
  build_table_filename(path, sizeof(path), db, "", MY_DB_OPT_FILE, 0);
704
 
  if ((error=write_db_opt(thd, path, db, create_info)))
 
784
  if ((error=write_db_opt(thd, path, create_info)))
705
785
    goto exit;
706
786
 
707
787
  /* Change options if current database is being altered. */
714
794
    thd->variables.collation_database= thd->db_charset;
715
795
  }
716
796
 
 
797
  ha_binlog_log_query(thd, 0, LOGCOM_ALTER_DB,
 
798
                      thd->query, thd->query_length,
 
799
                      db, "");
 
800
 
717
801
  if (mysql_bin_log.is_open())
718
802
  {
719
803
    Query_log_event qinfo(thd, thd->query, thd->query_length, 0,
734
818
  my_ok(thd, result);
735
819
 
736
820
exit:
737
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
 
821
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
738
822
  start_waiting_global_read_lock(thd);
739
823
exit2:
740
824
  return(error);
761
845
bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
762
846
{
763
847
  long deleted=0;
764
 
  int error= false;
 
848
  int error= 0;
765
849
  char  path[FN_REFLEN+16];
766
850
  MY_DIR *dirp;
767
 
  uint32_t length;
768
 
  TableList* dropped_tables= 0;
 
851
  uint length;
 
852
  TABLE_LIST* dropped_tables= 0;
769
853
 
770
854
  if (db && (strcmp(db, "information_schema") == 0))
771
855
  {
791
875
    goto exit2;
792
876
  }
793
877
 
794
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
 
878
  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
795
879
 
796
880
  /*
797
881
    This statement will be replicated as a statement, even when using
801
885
  thd->clear_current_stmt_binlog_row_based();
802
886
 
803
887
  length= build_table_filename(path, sizeof(path), db, "", "", 0);
804
 
  my_stpcpy(path+length, MY_DB_OPT_FILE);               // Append db option file name
 
888
  strmov(path+length, MY_DB_OPT_FILE);          // Append db option file name
805
889
  del_dbopt(path);                              // Remove dboption hash entry
806
890
  path[length]= '\0';                           // Remove file name
807
891
 
815
899
      goto exit;
816
900
    }
817
901
    else
818
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
902
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
819
903
                          ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
820
904
  }
821
905
  else
836
920
  if (!silent && deleted>=0)
837
921
  {
838
922
    const char *query;
839
 
    uint32_t query_length;
 
923
    ulong query_length;
840
924
    if (!thd->query)
841
925
    {
842
926
      /* The client used the old obsolete mysql_drop_db() call */
843
927
      query= path;
844
928
      query_length= (uint) (strxmov(path, "drop database `", db, "`",
845
 
                                     NULL) - path);
 
929
                                     NullS) - path);
846
930
    }
847
931
    else
848
932
    {
867
951
    }
868
952
    thd->clear_error();
869
953
    thd->server_status|= SERVER_STATUS_DB_DROPPED;
870
 
    my_ok(thd, (uint32_t) deleted);
 
954
    my_ok(thd, (ulong) deleted);
871
955
    thd->server_status&= ~SERVER_STATUS_DB_DROPPED;
872
956
  }
873
957
  else if (mysql_bin_log.is_open())
874
958
  {
875
959
    char *query, *query_pos, *query_end, *query_data_start;
876
 
    TableList *tbl;
877
 
    uint32_t db_len;
 
960
    TABLE_LIST *tbl;
 
961
    uint db_len;
878
962
 
879
963
    if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN)))
880
964
      goto exit; /* not much else we can do */
881
 
    query_pos= query_data_start= my_stpcpy(query,"drop table ");
 
965
    query_pos= query_data_start= strmov(query,"drop table ");
882
966
    query_end= query + MAX_DROP_TABLE_Q_LEN;
883
967
    db_len= strlen(db);
884
968
 
885
969
    for (tbl= dropped_tables; tbl; tbl= tbl->next_local)
886
970
    {
887
 
      uint32_t tbl_name_len;
 
971
      uint tbl_name_len;
888
972
 
889
973
      /* 3 for the quotes and the comma*/
890
974
      tbl_name_len= strlen(tbl->table_name) + 3;
896
980
      }
897
981
 
898
982
      *query_pos++ = '`';
899
 
      query_pos= my_stpcpy(query_pos,tbl->table_name);
 
983
      query_pos= strmov(query_pos,tbl->table_name);
900
984
      *query_pos++ = '`';
901
985
      *query_pos++ = ',';
902
986
    }
917
1001
  */
918
1002
  if (thd->db && !strcmp(thd->db, db))
919
1003
    mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
920
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
 
1004
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
921
1005
  start_waiting_global_read_lock(thd);
922
1006
exit2:
923
1007
  return(error);
924
1008
}
925
1009
 
926
1010
/*
927
 
  Removes files with known extensions plus.
 
1011
  Removes files with known extensions plus all found subdirectories that
 
1012
  are 2 hex digits (raid directories).
928
1013
  thd MUST be set when calling this function!
929
1014
*/
930
1015
 
931
1016
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
932
 
                                 const char *org_path, uint32_t level,
933
 
                                 TableList **dropped_tables)
 
1017
                                 const char *org_path, uint level,
 
1018
                                 TABLE_LIST **dropped_tables)
934
1019
{
935
1020
  long deleted=0;
936
 
  uint32_t found_other_files=0;
 
1021
  ulong found_other_files=0;
937
1022
  char filePath[FN_REFLEN];
938
 
  TableList *tot_list=0, **tot_list_next;
 
1023
  TABLE_LIST *tot_list=0, **tot_list_next;
 
1024
  List<String> raid_dirs;
939
1025
 
940
1026
  tot_list_next= &tot_list;
941
1027
 
942
 
  for (uint32_t idx=0 ;
 
1028
  for (uint idx=0 ;
943
1029
       idx < (uint) dirp->number_off_files && !thd->killed ;
944
1030
       idx++)
945
1031
  {
951
1037
       (file->name[1] == '.' &&  !file->name[2])))
952
1038
      continue;
953
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
    }
954
1085
    if (!(extension= strrchr(file->name, '.')))
955
 
      extension= strchr(file->name, '\0');
 
1086
      extension= strend(file->name);
956
1087
    if (find_type(extension, &deletable_extentions,1+2) <= 0)
957
1088
    {
958
1089
      if (find_type(extension, ha_known_exts(),1+2) <= 0)
965
1096
    {
966
1097
      /* Drop the table nicely */
967
1098
      *extension= 0;                    // Remove extension
968
 
      TableList *table_list=(TableList*)
 
1099
      TABLE_LIST *table_list=(TABLE_LIST*)
969
1100
                              thd->calloc(sizeof(*table_list) + 
970
1101
                                          strlen(db) + 1 +
971
1102
                                          MYSQL50_TABLE_NAME_PREFIX_LENGTH + 
974
1105
      if (!table_list)
975
1106
        goto err;
976
1107
      table_list->db= (char*) (table_list+1);
977
 
      table_list->table_name= my_stpcpy(table_list->db, db) + 1;
978
 
      filename_to_tablename(file->name, table_list->table_name,
979
 
                            MYSQL50_TABLE_NAME_PREFIX_LENGTH +
980
 
                            strlen(file->name) + 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));
981
1112
      table_list->alias= table_list->table_name;        // If lower_case_table_names=2
982
1113
      table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix);
983
1114
      /* Link into list */
987
1118
    }
988
1119
    else
989
1120
    {
990
 
      strxmov(filePath, org_path, "/", file->name, NULL);
 
1121
      strxmov(filePath, org_path, "/", file->name, NullS);
991
1122
      if (my_delete_with_symlink(filePath,MYF(MY_WME)))
992
1123
      {
993
1124
        goto err;
998
1129
      (tot_list && mysql_rm_table_part2(thd, tot_list, 1, 0, 1, 1)))
999
1130
    goto err;
1000
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
  }
1001
1140
  my_dirend(dirp);  
1002
1141
  
1003
1142
  if (dropped_tables)
1039
1178
    1 ERROR
1040
1179
*/
1041
1180
 
1042
 
static bool rm_dir_w_symlink(const char *org_path, bool send_error)
 
1181
static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error)
1043
1182
{
1044
1183
  char tmp_path[FN_REFLEN], *pos;
1045
1184
  char *path= tmp_path;
1049
1188
  char tmp2_path[FN_REFLEN];
1050
1189
 
1051
1190
  /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
1052
 
  pos= strchr(path, '\0');
 
1191
  pos= strend(path);
1053
1192
  if (pos > path && pos[-1] == FN_LIBCHAR)
1054
1193
    *--pos=0;
1055
1194
 
1066
1205
  }
1067
1206
#endif
1068
1207
  /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
1069
 
  pos= strchr(path, '\0');
 
1208
  pos= strend(path);
1070
1209
 
1071
1210
  if (pos > path && pos[-1] == FN_LIBCHAR)
1072
1211
    *--pos=0;
1079
1218
}
1080
1219
 
1081
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))
 
1286
    return(-1);
 
1287
  return(deleted);
 
1288
 
 
1289
err:
 
1290
  my_dirend(dirp);
 
1291
  return(-1);
 
1292
}
 
1293
 
 
1294
 
1082
1295
/**
1083
1296
  @brief Internal implementation: switch current database to a valid one.
1084
1297
 
1092
1305
 
1093
1306
static void mysql_change_db_impl(THD *thd,
1094
1307
                                 LEX_STRING *new_db_name,
1095
 
                                 const CHARSET_INFO * const new_db_charset)
 
1308
                                 CHARSET_INFO *new_db_charset)
1096
1309
{
1097
1310
  /* 1. Change current database in THD. */
1098
1311
 
1122
1335
      the previous database name, we should do it explicitly.
1123
1336
    */
1124
1337
 
1125
 
    if (thd->db)
1126
 
      free(thd->db);
 
1338
    x_free(thd->db);
1127
1339
 
1128
1340
    thd->reset_db(new_db_name->str, new_db_name->length);
1129
1341
  }
1258
1470
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
1259
1471
{
1260
1472
  LEX_STRING new_db_file_name;
1261
 
  const CHARSET_INFO *db_default_cl;
 
1473
  CHARSET_INFO *db_default_cl;
1262
1474
 
1263
1475
  if (new_db_name == NULL ||
1264
1476
      new_db_name->length == 0)
1323
1535
  if (check_db_name(&new_db_file_name))
1324
1536
  {
1325
1537
    my_error(ER_WRONG_DB_NAME, MYF(0), new_db_file_name.str);
1326
 
    free(new_db_file_name.str);
 
1538
    my_free(new_db_file_name.str, MYF(0));
1327
1539
 
1328
1540
    if (force_switch)
1329
1541
      mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
1337
1549
    {
1338
1550
      /* Throw a warning and free new_db_file_name. */
1339
1551
 
1340
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1552
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1341
1553
                          ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
1342
1554
                          new_db_file_name.str);
1343
1555
 
1344
 
      free(new_db_file_name.str);
 
1556
      my_free(new_db_file_name.str, MYF(0));
1345
1557
 
1346
1558
      /* Change db to NULL. */
1347
1559
 
1356
1568
      /* Report an error and free new_db_file_name. */
1357
1569
 
1358
1570
      my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
1359
 
      free(new_db_file_name.str);
 
1571
      my_free(new_db_file_name.str, MYF(0));
1360
1572
 
1361
1573
      /* The operation failed. */
1362
1574
 
1414
1626
}
1415
1627
 
1416
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");
 
1716
    return(1);
 
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))
 
1725
    return(1);
 
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
  {
 
1849
    Query_log_event qinfo(thd, thd->query, thd->query_length, 0, true);
 
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)
 
1856
    error|= mysql_change_db(thd, & new_db, false);
 
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
 
 
1868
  return(error);
 
1869
}
 
1870
 
 
1871
 
 
1872
 
1417
1873
/*
1418
1874
  Check if there is directory for the database name.
1419
1875
 
1429
1885
bool check_db_dir_existence(const char *db_name)
1430
1886
{
1431
1887
  char db_dir_path[FN_REFLEN];
1432
 
  uint32_t db_dir_path_len;
 
1888
  uint db_dir_path_len;
1433
1889
 
1434
1890
  db_dir_path_len= build_table_filename(db_dir_path, sizeof(db_dir_path),
1435
1891
                                        db_name, "", "", 0);