~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/sql_db.cc

  • Committer: Brian Aker
  • Date: 2008-07-07 16:07:49 UTC
  • mfrom: (80.1.1 food)
  • Revision ID: brian@tangent.org-20080707160749-qj89fnnwufz4xgop
Clean up install, we no longer have system tables.

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
  DBUG_ENTER("lock_db_insert");
 
99
  
 
100
  safe_mutex_assert_owner(&LOCK_lock_db);
 
101
 
 
102
  if (!(opt= (my_dblock_t*) hash_search(&lock_db_cache,
 
103
                                        (uchar*) dbname, length)))
 
104
  { 
 
105
    /* Db is not in the hash, insert it */
 
106
    char *tmp_name;
 
107
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
 
108
                         &opt, (uint) sizeof(*opt), &tmp_name, (uint) length+1,
 
109
                         NullS))
 
110
    {
 
111
      error= 1;
 
112
      goto end;
 
113
    }
 
114
    
 
115
    opt->name= tmp_name;
 
116
    strmov(opt->name, dbname);
 
117
    opt->name_length= length;
 
118
    
 
119
    if ((error= my_hash_insert(&lock_db_cache, (uchar*) opt)))
 
120
      my_free(opt, MYF(0));
 
121
  }
 
122
 
 
123
end:
 
124
  DBUG_RETURN(error);
84
125
}
85
126
 
86
127
 
88
129
  Delete a database lock entry from hash.
89
130
*/
90
131
 
91
 
void lock_db_delete(const char *name, uint32_t length)
 
132
void lock_db_delete(const char *name, uint length)
92
133
{
93
134
  my_dblock_t *opt;
94
135
  safe_mutex_assert_owner(&LOCK_lock_db);
95
136
  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);
 
137
                                       (const uchar*) name, length)))
 
138
    hash_delete(&lock_db_cache, (uchar*) opt);
98
139
}
99
140
 
100
141
 
101
142
/* Database options hash */
102
143
static HASH dboptions;
103
 
static bool dboptions_init= 0;
 
144
static my_bool dboptions_init= 0;
104
145
static rw_lock_t LOCK_dboptions;
105
146
 
106
147
/* Structure for database options */
107
148
typedef struct my_dbopt_st
108
149
{
109
150
  char *name;                   /* Database name                  */
110
 
  uint32_t name_length;         /* Database length name           */
111
 
  const CHARSET_INFO *charset;  /* Database default character set */
 
151
  uint name_length;             /* Database length name           */
 
152
  CHARSET_INFO *charset;        /* Database default character set */
112
153
} my_dbopt_t;
113
154
 
114
155
 
116
157
  Function we use in the creation of our hash to get key.
117
158
*/
118
159
 
119
 
extern "C" unsigned char* dboptions_get_key(my_dbopt_t *opt, size_t *length,
120
 
                                    bool not_used);
 
160
extern "C" uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length,
 
161
                                    my_bool not_used);
121
162
 
122
 
unsigned char* dboptions_get_key(my_dbopt_t *opt, size_t *length,
123
 
                         bool not_used __attribute__((unused)))
 
163
uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length,
 
164
                         my_bool not_used __attribute__((unused)))
124
165
{
125
166
  *length= opt->name_length;
126
 
  return (unsigned char*) opt->name;
 
167
  return (uchar*) opt->name;
127
168
}
128
169
 
129
170
 
131
172
  Helper function to write a query to binlog used by mysql_rm_db()
132
173
*/
133
174
 
134
 
static inline void write_to_binlog(THD *thd, char *query, uint32_t q_len,
135
 
                                   char *db, uint32_t db_len)
 
175
static inline void write_to_binlog(THD *thd, char *query, uint q_len,
 
176
                                   char *db, uint db_len)
136
177
{
137
178
  Query_log_event qinfo(thd, query, q_len, 0, 0);
138
179
  qinfo.error_code= 0;
150
191
 
151
192
void free_dbopt(void *dbopt)
152
193
{
153
 
  free((unsigned char*) dbopt);
 
194
  my_free((uchar*) dbopt, MYF(0));
154
195
}
155
196
 
156
197
 
170
211
 
171
212
bool my_database_names_init(void)
172
213
{
173
 
  bool error= false;
 
214
  bool error= 0;
174
215
  (void) my_rwlock_init(&LOCK_dboptions, NULL);
175
216
  if (!dboptions_init)
176
217
  {
234
275
    1 on error.
235
276
*/
236
277
 
237
 
static bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
 
278
static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
238
279
{
239
280
  my_dbopt_t *opt;
240
 
  uint32_t length;
241
 
  bool error= true;
 
281
  uint length;
 
282
  my_bool error= 1;
242
283
  
243
284
  length= (uint) strlen(dbname);
244
285
  
245
286
  rw_rdlock(&LOCK_dboptions);
246
 
  if ((opt= (my_dbopt_t*) hash_search(&dboptions, (unsigned char*) dbname, length)))
 
287
  if ((opt= (my_dbopt_t*) hash_search(&dboptions, (uchar*) dbname, length)))
247
288
  {
248
289
    create->default_table_charset= opt->charset;
249
 
    error= true;
 
290
    error= 0;
250
291
  }
251
292
  rw_unlock(&LOCK_dboptions);
252
293
  return error;
265
306
    1 on error.
266
307
*/
267
308
 
268
 
static bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
 
309
static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
269
310
{
270
311
  my_dbopt_t *opt;
271
 
  uint32_t length;
272
 
  bool error= false;
 
312
  uint length;
 
313
  my_bool error= 0;
 
314
  DBUG_ENTER("put_dbopt");
273
315
 
274
316
  length= (uint) strlen(dbname);
275
317
  
276
318
  rw_wrlock(&LOCK_dboptions);
277
 
  if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (unsigned char*) dbname, length)))
 
319
  if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (uchar*) dbname, length)))
278
320
  { 
279
321
    /* Options are not in the hash, insert them */
280
322
    char *tmp_name;
281
323
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
282
324
                         &opt, (uint) sizeof(*opt), &tmp_name, (uint) length+1,
283
 
                         NULL))
 
325
                         NullS))
284
326
    {
285
 
      error= true;
 
327
      error= 1;
286
328
      goto end;
287
329
    }
288
330
    
289
331
    opt->name= tmp_name;
290
 
    my_stpcpy(opt->name, dbname);
 
332
    strmov(opt->name, dbname);
291
333
    opt->name_length= length;
292
334
    
293
 
    if ((error= my_hash_insert(&dboptions, (unsigned char*) opt)))
 
335
    if ((error= my_hash_insert(&dboptions, (uchar*) opt)))
294
336
    {
295
 
      free(opt);
 
337
      my_free(opt, MYF(0));
296
338
      goto end;
297
339
    }
298
340
  }
302
344
 
303
345
end:
304
346
  rw_unlock(&LOCK_dboptions);  
305
 
  return(error);
 
347
  DBUG_RETURN(error);
306
348
}
307
349
 
308
350
 
314
356
{
315
357
  my_dbopt_t *opt;
316
358
  rw_wrlock(&LOCK_dboptions);
317
 
  if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const unsigned char*) path,
 
359
  if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const uchar*) path,
318
360
                                      strlen(path))))
319
 
    hash_delete(&dboptions, (unsigned char*) opt);
 
361
    hash_delete(&dboptions, (uchar*) opt);
320
362
  rw_unlock(&LOCK_dboptions);
321
363
}
322
364
 
332
374
  1     Could not create file or write to it.  Error sent through my_error()
333
375
*/
334
376
 
335
 
static bool write_db_opt(THD *thd, const char *path, const char *name, HA_CREATE_INFO *create)
 
377
static bool write_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
336
378
{
337
 
  bool error= true;
338
 
  drizzle::Schema db;
339
 
 
340
 
  assert(name);
 
379
  register File file;
 
380
  char buf[256]; // Should be enough for one option
 
381
  bool error=1;
341
382
 
342
383
  if (!create->default_table_charset)
343
384
    create->default_table_charset= thd->variables.collation_server;
345
386
  if (put_dbopt(path, create))
346
387
    return 1;
347
388
 
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
 
 
 
389
  if ((file=my_create(path, CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
 
390
  {
 
391
    ulong length;
 
392
    length= (ulong) (strxnmov(buf, sizeof(buf)-1, "default-character-set=",
 
393
                              create->default_table_charset->csname,
 
394
                              "\ndefault-collation=",
 
395
                              create->default_table_charset->name,
 
396
                              "\n", NullS) - buf);
 
397
 
 
398
    /* Error is written by my_write */
 
399
    if (!my_write(file,(uchar*) buf, length, MYF(MY_NABP+MY_WME)))
 
400
      error=0;
 
401
    my_close(file,MYF(0));
 
402
  }
356
403
  return error;
357
404
}
358
405
 
374
421
 
375
422
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
376
423
{
 
424
  File file;
 
425
  char buf[256];
 
426
  DBUG_ENTER("load_db_opt");
377
427
  bool error=1;
378
 
  drizzle::Schema db;
379
 
  string buffer;
 
428
  uint nbytes;
380
429
 
381
 
  memset(create, 0, sizeof(*create));
 
430
  bzero((char*) create,sizeof(*create));
382
431
  create->default_table_charset= thd->variables.collation_server;
383
432
 
384
433
  /* Check if options for this database are already in the hash */
385
434
  if (!get_dbopt(path, create))
386
 
    return(0);
387
 
 
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
 
 
 
435
    DBUG_RETURN(0);
 
436
 
 
437
  /* Otherwise, load options from the .opt file */
 
438
  if ((file=my_open(path, O_RDONLY | O_SHARE, MYF(0))) < 0)
 
439
    goto err1;
 
440
 
 
441
  IO_CACHE cache;
 
442
  if (init_io_cache(&cache, file, IO_SIZE, READ_CACHE, 0, 0, MYF(0)))
 
443
    goto err2;
 
444
 
 
445
  while ((int) (nbytes= my_b_gets(&cache, (char*) buf, sizeof(buf))) > 0)
 
446
  {
 
447
    char *pos= buf+nbytes-1;
 
448
    /* Remove end space and control characters */
 
449
    while (pos > buf && !my_isgraph(&my_charset_latin1, pos[-1]))
 
450
      pos--;
 
451
    *pos=0;
 
452
    if ((pos= strchr(buf, '=')))
 
453
    {
 
454
      if (!strncmp(buf,"default-character-set", (pos-buf)))
 
455
      {
 
456
        /*
 
457
           Try character set name, and if it fails
 
458
           try collation name, probably it's an old
 
459
           4.1.0 db.opt file, which didn't have
 
460
           separate default-character-set and
 
461
           default-collation commands.
 
462
        */
 
463
        if (!(create->default_table_charset=
 
464
        get_charset_by_csname(pos+1, MY_CS_PRIMARY, MYF(0))) &&
 
465
            !(create->default_table_charset=
 
466
              get_charset_by_name(pos+1, MYF(0))))
 
467
        {
 
468
          sql_print_error("Error while loading database options: '%s':",path);
 
469
          sql_print_error(ER(ER_UNKNOWN_CHARACTER_SET),pos+1);
 
470
          create->default_table_charset= default_charset_info;
 
471
        }
 
472
      }
 
473
      else if (!strncmp(buf,"default-collation", (pos-buf)))
 
474
      {
 
475
        if (!(create->default_table_charset= get_charset_by_name(pos+1,
 
476
                                                           MYF(0))))
 
477
        {
 
478
          sql_print_error("Error while loading database options: '%s':",path);
 
479
          sql_print_error(ER(ER_UNKNOWN_COLLATION),pos+1);
 
480
          create->default_table_charset= default_charset_info;
 
481
        }
 
482
      }
 
483
    }
 
484
  }
410
485
  /*
411
486
    Put the loaded value into the hash.
412
487
    Note that another thread could've added the same
416
491
  */
417
492
  error= put_dbopt(path, create);
418
493
 
 
494
  end_io_cache(&cache);
 
495
err2:
 
496
  my_close(file,MYF(0));
419
497
err1:
420
 
  return(error);
 
498
  DBUG_RETURN(error);
421
499
}
422
500
 
423
501
 
438
516
    the operation, it is useless usually and should be ignored. The problem
439
517
    is that there are 1) system databases ("mysql") and 2) virtual
440
518
    databases ("information_schema"), which do not contain options file.
441
 
    So, load_db_opt[_by_name]() returns false for these databases, but this
 
519
    So, load_db_opt[_by_name]() returns FALSE for these databases, but this
442
520
    is not an error.
443
521
 
444
522
    load_db_opt[_by_name]() clears db_create_info structure in any case, so
447
525
    db_create_info right after that.
448
526
 
449
527
  RETURN VALUES (read NOTE!)
450
 
    false   Success
451
 
    true    Failed to retrieve options
 
528
    FALSE   Success
 
529
    TRUE    Failed to retrieve options
452
530
*/
453
531
 
454
532
bool load_db_opt_by_name(THD *thd, const char *db_name,
477
555
    set, even if the database does not exist.
478
556
*/
479
557
 
480
 
const CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
 
558
CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
481
559
{
482
560
  HA_CREATE_INFO db_info;
483
561
 
517
595
   (The 'silent' flags turns off 1 and 3.)
518
596
 
519
597
  RETURN VALUES
520
 
  false ok
521
 
  true  Error
 
598
  FALSE ok
 
599
  TRUE  Error
522
600
 
523
601
*/
524
602
 
525
 
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent)
 
603
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
 
604
                     bool silent)
526
605
{
527
606
  char   path[FN_REFLEN+16];
528
607
  char   tmp_query[FN_REFLEN+16];
529
608
  long result= 1;
530
609
  int error= 0;
531
610
  struct stat stat_info;
532
 
  uint32_t create_options= create_info ? create_info->options : 0;
533
 
  uint32_t path_len;
 
611
  uint create_options= create_info ? create_info->options : 0;
 
612
  uint path_len;
 
613
  DBUG_ENTER("mysql_create_db");
534
614
 
535
615
  /* do not create 'information_schema' db */
536
616
  if (!my_strcasecmp(system_charset_info, db, INFORMATION_SCHEMA_NAME.str))
537
617
  {
538
618
    my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
539
 
    return(-1);
 
619
    DBUG_RETURN(-1);
540
620
  }
541
621
 
542
622
  /*
557
637
    goto exit2;
558
638
  }
559
639
 
560
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
 
640
  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
561
641
 
562
642
  /* Check directory */
563
643
  path_len= build_table_filename(path, sizeof(path), db, "", "", 0);
571
651
      error= -1;
572
652
      goto exit;
573
653
    }
574
 
    push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
654
    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
575
655
                        ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
576
656
    if (!silent)
577
657
      my_ok(thd);
595
675
 
596
676
  path[path_len-1]= FN_LIBCHAR;
597
677
  strmake(path+path_len, MY_DB_OPT_FILE, sizeof(path)-path_len-1);
598
 
  if (write_db_opt(thd, path, db, create_info))
 
678
  if (write_db_opt(thd, path, create_info))
599
679
  {
600
680
    /*
601
681
      Could not create options file.
617
697
  if (!silent)
618
698
  {
619
699
    char *query;
620
 
    uint32_t query_length;
 
700
    uint query_length;
621
701
 
622
702
    if (!thd->query)                            // Only in replication
623
703
    {
624
704
      query=         tmp_query;
625
705
      query_length= (uint) (strxmov(tmp_query,"create database `",
626
 
                                    db, "`", NULL) - tmp_query);
 
706
                                    db, "`", NullS) - tmp_query);
627
707
    }
628
708
    else
629
709
    {
631
711
      query_length= thd->query_length;
632
712
    }
633
713
 
 
714
    ha_binlog_log_query(thd, 0, LOGCOM_CREATE_DB,
 
715
                        query, query_length,
 
716
                        db, "");
 
717
 
634
718
    if (mysql_bin_log.is_open())
635
719
    {
636
720
      Query_log_event qinfo(thd, query, query_length, 0, 
637
 
                            /* suppress_use */ true);
 
721
                            /* suppress_use */ TRUE);
638
722
 
639
723
      /*
640
724
        Write should use the database being created as the "current
663
747
  }
664
748
 
665
749
exit:
666
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
 
750
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
667
751
  start_waiting_global_read_lock(thd);
668
752
exit2:
669
 
  return(error);
 
753
  DBUG_RETURN(error);
670
754
}
671
755
 
672
756
 
676
760
{
677
761
  char path[FN_REFLEN+16];
678
762
  long result=1;
679
 
  int error= false;
 
763
  int error= 0;
 
764
  DBUG_ENTER("mysql_alter_db");
680
765
 
681
766
  /*
682
767
    Do not alter database if another thread is holding read lock.
693
778
  if ((error=wait_if_global_read_lock(thd,0,1)))
694
779
    goto exit2;
695
780
 
696
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
 
781
  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
697
782
 
698
783
  /* 
699
784
     Recreate db options file: /dbpath/.db.opt
701
786
     "table name to file name" encoding.
702
787
  */
703
788
  build_table_filename(path, sizeof(path), db, "", MY_DB_OPT_FILE, 0);
704
 
  if ((error=write_db_opt(thd, path, db, create_info)))
 
789
  if ((error=write_db_opt(thd, path, create_info)))
705
790
    goto exit;
706
791
 
707
792
  /* Change options if current database is being altered. */
714
799
    thd->variables.collation_database= thd->db_charset;
715
800
  }
716
801
 
 
802
  ha_binlog_log_query(thd, 0, LOGCOM_ALTER_DB,
 
803
                      thd->query, thd->query_length,
 
804
                      db, "");
 
805
 
717
806
  if (mysql_bin_log.is_open())
718
807
  {
719
808
    Query_log_event qinfo(thd, thd->query, thd->query_length, 0,
720
 
                          /* suppress_use */ true);
 
809
                          /* suppress_use */ TRUE);
721
810
 
722
811
    /*
723
812
      Write should use the database being created as the "current
734
823
  my_ok(thd, result);
735
824
 
736
825
exit:
737
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
 
826
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
738
827
  start_waiting_global_read_lock(thd);
739
828
exit2:
740
 
  return(error);
 
829
  DBUG_RETURN(error);
741
830
}
742
831
 
743
832
 
754
843
    silent              Don't generate errors
755
844
 
756
845
  RETURN
757
 
    false ok (Database dropped)
 
846
    FALSE ok (Database dropped)
758
847
    ERROR Error
759
848
*/
760
849
 
761
850
bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
762
851
{
763
852
  long deleted=0;
764
 
  int error= false;
 
853
  int error= 0;
765
854
  char  path[FN_REFLEN+16];
766
855
  MY_DIR *dirp;
767
 
  uint32_t length;
768
 
  TableList* dropped_tables= 0;
 
856
  uint length;
 
857
  TABLE_LIST* dropped_tables= 0;
 
858
  DBUG_ENTER("mysql_rm_db");
769
859
 
770
860
  if (db && (strcmp(db, "information_schema") == 0))
771
861
  {
772
862
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
773
 
    return(true);
 
863
    DBUG_RETURN(TRUE);
774
864
  }
775
865
 
776
866
  /*
791
881
    goto exit2;
792
882
  }
793
883
 
794
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
 
884
  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
795
885
 
796
886
  /*
797
887
    This statement will be replicated as a statement, even when using
801
891
  thd->clear_current_stmt_binlog_row_based();
802
892
 
803
893
  length= build_table_filename(path, sizeof(path), db, "", "", 0);
804
 
  my_stpcpy(path+length, MY_DB_OPT_FILE);               // Append db option file name
 
894
  strmov(path+length, MY_DB_OPT_FILE);          // Append db option file name
805
895
  del_dbopt(path);                              // Remove dboption hash entry
806
896
  path[length]= '\0';                           // Remove file name
807
897
 
815
905
      goto exit;
816
906
    }
817
907
    else
818
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
908
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
819
909
                          ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
820
910
  }
821
911
  else
836
926
  if (!silent && deleted>=0)
837
927
  {
838
928
    const char *query;
839
 
    uint32_t query_length;
 
929
    ulong query_length;
840
930
    if (!thd->query)
841
931
    {
842
932
      /* The client used the old obsolete mysql_drop_db() call */
843
933
      query= path;
844
934
      query_length= (uint) (strxmov(path, "drop database `", db, "`",
845
 
                                     NULL) - path);
 
935
                                     NullS) - path);
846
936
    }
847
937
    else
848
938
    {
852
942
    if (mysql_bin_log.is_open())
853
943
    {
854
944
      Query_log_event qinfo(thd, query, query_length, 0, 
855
 
                            /* suppress_use */ true);
 
945
                            /* suppress_use */ TRUE);
856
946
      /*
857
947
        Write should use the database being created as the "current
858
948
        database" and not the threads current database, which is the
867
957
    }
868
958
    thd->clear_error();
869
959
    thd->server_status|= SERVER_STATUS_DB_DROPPED;
870
 
    my_ok(thd, (uint32_t) deleted);
 
960
    my_ok(thd, (ulong) deleted);
871
961
    thd->server_status&= ~SERVER_STATUS_DB_DROPPED;
872
962
  }
873
963
  else if (mysql_bin_log.is_open())
874
964
  {
875
965
    char *query, *query_pos, *query_end, *query_data_start;
876
 
    TableList *tbl;
877
 
    uint32_t db_len;
 
966
    TABLE_LIST *tbl;
 
967
    uint db_len;
878
968
 
879
969
    if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN)))
880
970
      goto exit; /* not much else we can do */
881
 
    query_pos= query_data_start= my_stpcpy(query,"drop table ");
 
971
    query_pos= query_data_start= strmov(query,"drop table ");
882
972
    query_end= query + MAX_DROP_TABLE_Q_LEN;
883
973
    db_len= strlen(db);
884
974
 
885
975
    for (tbl= dropped_tables; tbl; tbl= tbl->next_local)
886
976
    {
887
 
      uint32_t tbl_name_len;
 
977
      uint tbl_name_len;
888
978
 
889
979
      /* 3 for the quotes and the comma*/
890
980
      tbl_name_len= strlen(tbl->table_name) + 3;
896
986
      }
897
987
 
898
988
      *query_pos++ = '`';
899
 
      query_pos= my_stpcpy(query_pos,tbl->table_name);
 
989
      query_pos= strmov(query_pos,tbl->table_name);
900
990
      *query_pos++ = '`';
901
991
      *query_pos++ = ',';
902
992
    }
917
1007
  */
918
1008
  if (thd->db && !strcmp(thd->db, db))
919
1009
    mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
920
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
 
1010
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
921
1011
  start_waiting_global_read_lock(thd);
922
1012
exit2:
923
 
  return(error);
 
1013
  DBUG_RETURN(error);
924
1014
}
925
1015
 
926
1016
/*
927
 
  Removes files with known extensions plus.
 
1017
  Removes files with known extensions plus all found subdirectories that
 
1018
  are 2 hex digits (raid directories).
928
1019
  thd MUST be set when calling this function!
929
1020
*/
930
1021
 
931
1022
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)
 
1023
                                 const char *org_path, uint level,
 
1024
                                 TABLE_LIST **dropped_tables)
934
1025
{
935
1026
  long deleted=0;
936
 
  uint32_t found_other_files=0;
 
1027
  ulong found_other_files=0;
937
1028
  char filePath[FN_REFLEN];
938
 
  TableList *tot_list=0, **tot_list_next;
 
1029
  TABLE_LIST *tot_list=0, **tot_list_next;
 
1030
  List<String> raid_dirs;
 
1031
  DBUG_ENTER("mysql_rm_known_files");
 
1032
  DBUG_PRINT("enter",("path: %s", org_path));
939
1033
 
940
1034
  tot_list_next= &tot_list;
941
1035
 
942
 
  for (uint32_t idx=0 ;
 
1036
  for (uint idx=0 ;
943
1037
       idx < (uint) dirp->number_off_files && !thd->killed ;
944
1038
       idx++)
945
1039
  {
946
1040
    FILEINFO *file=dirp->dir_entry+idx;
947
1041
    char *extension;
 
1042
    DBUG_PRINT("info",("Examining: %s", file->name));
948
1043
 
949
1044
    /* skiping . and .. */
950
1045
    if (file->name[0] == '.' && (!file->name[1] ||
951
1046
       (file->name[1] == '.' &&  !file->name[2])))
952
1047
      continue;
953
1048
 
 
1049
    /* Check if file is a raid directory */
 
1050
    if ((my_isdigit(system_charset_info, file->name[0]) ||
 
1051
         (file->name[0] >= 'a' && file->name[0] <= 'f')) &&
 
1052
        (my_isdigit(system_charset_info, file->name[1]) ||
 
1053
         (file->name[1] >= 'a' && file->name[1] <= 'f')) &&
 
1054
        !file->name[2] && !level)
 
1055
    {
 
1056
      char newpath[FN_REFLEN], *copy_of_path;
 
1057
      MY_DIR *new_dirp;
 
1058
      String *dir;
 
1059
      uint length;
 
1060
 
 
1061
      strxmov(newpath,org_path,"/",file->name,NullS);
 
1062
      length= unpack_filename(newpath,newpath);
 
1063
      if ((new_dirp = my_dir(newpath,MYF(MY_DONT_SORT))))
 
1064
      {
 
1065
        DBUG_PRINT("my",("New subdir found: %s", newpath));
 
1066
        if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1,0)) < 0)
 
1067
          goto err;
 
1068
        if (!(copy_of_path= (char*) thd->memdup(newpath, length+1)) ||
 
1069
            !(dir= new (thd->mem_root) String(copy_of_path, length,
 
1070
                                               &my_charset_bin)) ||
 
1071
            raid_dirs.push_back(dir))
 
1072
          goto err;
 
1073
        continue;
 
1074
      }
 
1075
      found_other_files++;
 
1076
      continue;
 
1077
    }
 
1078
    else if (file->name[0] == 'a' && file->name[1] == 'r' &&
 
1079
             file->name[2] == 'c' && file->name[3] == '\0')
 
1080
    {
 
1081
      /* .frm archive */
 
1082
      char newpath[FN_REFLEN];
 
1083
      MY_DIR *new_dirp;
 
1084
      strxmov(newpath, org_path, "/", "arc", NullS);
 
1085
      (void) unpack_filename(newpath, newpath);
 
1086
      if ((new_dirp = my_dir(newpath, MYF(MY_DONT_SORT))))
 
1087
      {
 
1088
        DBUG_PRINT("my",("Archive subdir found: %s", newpath));
 
1089
        if ((mysql_rm_arc_files(thd, new_dirp, newpath)) < 0)
 
1090
          goto err;
 
1091
        continue;
 
1092
      }
 
1093
      found_other_files++;
 
1094
      continue;
 
1095
    }
954
1096
    if (!(extension= strrchr(file->name, '.')))
955
 
      extension= strchr(file->name, '\0');
 
1097
      extension= strend(file->name);
956
1098
    if (find_type(extension, &deletable_extentions,1+2) <= 0)
957
1099
    {
958
1100
      if (find_type(extension, ha_known_exts(),1+2) <= 0)
965
1107
    {
966
1108
      /* Drop the table nicely */
967
1109
      *extension= 0;                    // Remove extension
968
 
      TableList *table_list=(TableList*)
 
1110
      TABLE_LIST *table_list=(TABLE_LIST*)
969
1111
                              thd->calloc(sizeof(*table_list) + 
970
1112
                                          strlen(db) + 1 +
971
1113
                                          MYSQL50_TABLE_NAME_PREFIX_LENGTH + 
974
1116
      if (!table_list)
975
1117
        goto err;
976
1118
      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);
 
1119
      table_list->table_name= strmov(table_list->db, db) + 1;
 
1120
      VOID(filename_to_tablename(file->name, table_list->table_name,
 
1121
                                 MYSQL50_TABLE_NAME_PREFIX_LENGTH +
 
1122
                                 strlen(file->name) + 1));
981
1123
      table_list->alias= table_list->table_name;        // If lower_case_table_names=2
982
1124
      table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix);
983
1125
      /* Link into list */
987
1129
    }
988
1130
    else
989
1131
    {
990
 
      strxmov(filePath, org_path, "/", file->name, NULL);
 
1132
      strxmov(filePath, org_path, "/", file->name, NullS);
991
1133
      if (my_delete_with_symlink(filePath,MYF(MY_WME)))
992
1134
      {
993
1135
        goto err;
998
1140
      (tot_list && mysql_rm_table_part2(thd, tot_list, 1, 0, 1, 1)))
999
1141
    goto err;
1000
1142
 
 
1143
  /* Remove RAID directories */
 
1144
  {
 
1145
    List_iterator<String> it(raid_dirs);
 
1146
    String *dir;
 
1147
    while ((dir= it++))
 
1148
      if (rmdir(dir->c_ptr()) < 0)
 
1149
        found_other_files++;
 
1150
  }
1001
1151
  my_dirend(dirp);  
1002
1152
  
1003
1153
  if (dropped_tables)
1010
1160
  if (found_other_files)
1011
1161
  {
1012
1162
    my_error(ER_DB_DROP_RMDIR, MYF(0), org_path, EEXIST);
1013
 
    return(-1);
 
1163
    DBUG_RETURN(-1);
1014
1164
  }
1015
1165
  else
1016
1166
  {
1017
1167
    /* Don't give errors if we can't delete 'RAID' directory */
1018
1168
    if (rm_dir_w_symlink(org_path, level == 0))
1019
 
      return(-1);
 
1169
      DBUG_RETURN(-1);
1020
1170
  }
1021
1171
 
1022
 
  return(deleted);
 
1172
  DBUG_RETURN(deleted);
1023
1173
 
1024
1174
err:
1025
1175
  my_dirend(dirp);
1026
 
  return(-1);
 
1176
  DBUG_RETURN(-1);
1027
1177
}
1028
1178
 
1029
1179
 
1039
1189
    1 ERROR
1040
1190
*/
1041
1191
 
1042
 
static bool rm_dir_w_symlink(const char *org_path, bool send_error)
 
1192
static my_bool rm_dir_w_symlink(const char *org_path, my_bool send_error)
1043
1193
{
1044
1194
  char tmp_path[FN_REFLEN], *pos;
1045
1195
  char *path= tmp_path;
 
1196
  DBUG_ENTER("rm_dir_w_symlink");
1046
1197
  unpack_filename(tmp_path, org_path);
1047
1198
#ifdef HAVE_READLINK
1048
1199
  int error;
1049
1200
  char tmp2_path[FN_REFLEN];
1050
1201
 
1051
1202
  /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
1052
 
  pos= strchr(path, '\0');
 
1203
  pos= strend(path);
1053
1204
  if (pos > path && pos[-1] == FN_LIBCHAR)
1054
1205
    *--pos=0;
1055
1206
 
1056
1207
  if ((error= my_readlink(tmp2_path, path, MYF(MY_WME))) < 0)
1057
 
    return(1);
 
1208
    DBUG_RETURN(1);
1058
1209
  if (!error)
1059
1210
  {
1060
1211
    if (my_delete(path, MYF(send_error ? MY_WME : 0)))
1061
1212
    {
1062
 
      return(send_error);
 
1213
      DBUG_RETURN(send_error);
1063
1214
    }
1064
1215
    /* Delete directory symbolic link pointed at */
1065
1216
    path= tmp2_path;
1066
1217
  }
1067
1218
#endif
1068
1219
  /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
1069
 
  pos= strchr(path, '\0');
 
1220
  pos= strend(path);
1070
1221
 
1071
1222
  if (pos > path && pos[-1] == FN_LIBCHAR)
1072
1223
    *--pos=0;
1073
1224
  if (rmdir(path) < 0 && send_error)
1074
1225
  {
1075
1226
    my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
1076
 
    return(1);
1077
 
  }
1078
 
  return(0);
 
1227
    DBUG_RETURN(1);
 
1228
  }
 
1229
  DBUG_RETURN(0);
 
1230
}
 
1231
 
 
1232
 
 
1233
/*
 
1234
  Remove .frm archives from directory
 
1235
 
 
1236
  SYNOPSIS
 
1237
    thd       thread handler
 
1238
    dirp      list of files in archive directory
 
1239
    db        data base name
 
1240
    org_path  path of archive directory
 
1241
 
 
1242
  RETURN
 
1243
    > 0 number of removed files
 
1244
    -1  error
 
1245
*/
 
1246
static long mysql_rm_arc_files(THD *thd, MY_DIR *dirp,
 
1247
                                 const char *org_path)
 
1248
{
 
1249
  long deleted= 0;
 
1250
  ulong found_other_files= 0;
 
1251
  char filePath[FN_REFLEN];
 
1252
  DBUG_ENTER("mysql_rm_arc_files");
 
1253
  DBUG_PRINT("enter", ("path: %s", org_path));
 
1254
 
 
1255
  for (uint idx=0 ;
 
1256
       idx < (uint) dirp->number_off_files && !thd->killed ;
 
1257
       idx++)
 
1258
  {
 
1259
    FILEINFO *file=dirp->dir_entry+idx;
 
1260
    char *extension, *revision;
 
1261
    DBUG_PRINT("info",("Examining: %s", file->name));
 
1262
 
 
1263
    /* skiping . and .. */
 
1264
    if (file->name[0] == '.' && (!file->name[1] ||
 
1265
       (file->name[1] == '.' &&  !file->name[2])))
 
1266
      continue;
 
1267
 
 
1268
    extension= fn_ext(file->name);
 
1269
    if (extension[0] != '.' ||
 
1270
        extension[1] != 'f' || extension[2] != 'r' ||
 
1271
        extension[3] != 'm' || extension[4] != '-')
 
1272
    {
 
1273
      found_other_files++;
 
1274
      continue;
 
1275
    }
 
1276
    revision= extension+5;
 
1277
    while (*revision && my_isdigit(system_charset_info, *revision))
 
1278
      revision++;
 
1279
    if (*revision)
 
1280
    {
 
1281
      found_other_files++;
 
1282
      continue;
 
1283
    }
 
1284
    strxmov(filePath, org_path, "/", file->name, NullS);
 
1285
    if (my_delete_with_symlink(filePath,MYF(MY_WME)))
 
1286
    {
 
1287
      goto err;
 
1288
    }
 
1289
  }
 
1290
  if (thd->killed)
 
1291
    goto err;
 
1292
 
 
1293
  my_dirend(dirp);
 
1294
 
 
1295
  /*
 
1296
    If the directory is a symbolic link, remove the link first, then
 
1297
    remove the directory the symbolic link pointed at
 
1298
  */
 
1299
  if (!found_other_files &&
 
1300
      rm_dir_w_symlink(org_path, 0))
 
1301
    DBUG_RETURN(-1);
 
1302
  DBUG_RETURN(deleted);
 
1303
 
 
1304
err:
 
1305
  my_dirend(dirp);
 
1306
  DBUG_RETURN(-1);
1079
1307
}
1080
1308
 
1081
1309
 
1092
1320
 
1093
1321
static void mysql_change_db_impl(THD *thd,
1094
1322
                                 LEX_STRING *new_db_name,
1095
 
                                 const CHARSET_INFO * const new_db_charset)
 
1323
                                 CHARSET_INFO *new_db_charset)
1096
1324
{
1097
1325
  /* 1. Change current database in THD. */
1098
1326
 
1122
1350
      the previous database name, we should do it explicitly.
1123
1351
    */
1124
1352
 
1125
 
    if (thd->db)
1126
 
      free(thd->db);
 
1353
    x_free(thd->db);
1127
1354
 
1128
1355
    thd->reset_db(new_db_name->str, new_db_name->length);
1129
1356
  }
1170
1397
 
1171
1398
 
1172
1399
/**
1173
 
  Return true if db1_name is equal to db2_name, false otherwise.
 
1400
  Return TRUE if db1_name is equal to db2_name, FALSE otherwise.
1174
1401
 
1175
1402
  The function allows to compare database names according to the MySQL
1176
1403
  rules. The database names db1 and db2 are equal if:
1198
1425
 
1199
1426
  @param thd          thread handle
1200
1427
  @param new_db_name  database name
1201
 
  @param force_switch if force_switch is false, then the operation will fail if
 
1428
  @param force_switch if force_switch is FALSE, then the operation will fail if
1202
1429
 
1203
1430
                        - new_db_name is NULL or empty;
1204
1431
 
1209
1436
 
1210
1437
                        - OR new database does not exist;
1211
1438
 
1212
 
                      if force_switch is true, then
 
1439
                      if force_switch is TRUE, then
1213
1440
 
1214
1441
                        - if new_db_name is NULL or empty, the current
1215
1442
                          database will be NULL, @@collation_database will
1251
1478
  the stack address was long gone.
1252
1479
 
1253
1480
  @return Operation status
1254
 
    @retval false Success
1255
 
    @retval true  Error
 
1481
    @retval FALSE Success
 
1482
    @retval TRUE  Error
1256
1483
*/
1257
1484
 
1258
1485
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
1259
1486
{
1260
1487
  LEX_STRING new_db_file_name;
1261
 
  const CHARSET_INFO *db_default_cl;
 
1488
  CHARSET_INFO *db_default_cl;
 
1489
 
 
1490
  DBUG_ENTER("mysql_change_db");
 
1491
  DBUG_PRINT("enter",("name: '%s'", new_db_name->str));
1262
1492
 
1263
1493
  if (new_db_name == NULL ||
1264
1494
      new_db_name->length == 0)
1277
1507
 
1278
1508
      mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
1279
1509
 
1280
 
      return(false);
 
1510
      DBUG_RETURN(FALSE);
1281
1511
    }
1282
1512
    else
1283
1513
    {
1284
1514
      my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1285
1515
 
1286
 
      return(true);
 
1516
      DBUG_RETURN(TRUE);
1287
1517
    }
1288
1518
  }
1289
1519
 
1294
1524
 
1295
1525
    mysql_change_db_impl(thd, &INFORMATION_SCHEMA_NAME, system_charset_info);
1296
1526
 
1297
 
    return(false);
 
1527
    DBUG_RETURN(FALSE);
1298
1528
  }
1299
1529
 
1300
1530
  /*
1309
1539
  new_db_file_name.length= new_db_name->length;
1310
1540
 
1311
1541
  if (new_db_file_name.str == NULL)
1312
 
    return(true);                             /* the error is set */
 
1542
    DBUG_RETURN(TRUE);                             /* the error is set */
1313
1543
 
1314
1544
  /*
1315
1545
    NOTE: if check_db_name() fails, we should throw an error in any case,
1323
1553
  if (check_db_name(&new_db_file_name))
1324
1554
  {
1325
1555
    my_error(ER_WRONG_DB_NAME, MYF(0), new_db_file_name.str);
1326
 
    free(new_db_file_name.str);
 
1556
    my_free(new_db_file_name.str, MYF(0));
1327
1557
 
1328
1558
    if (force_switch)
1329
1559
      mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
1330
1560
 
1331
 
    return(true);
 
1561
    DBUG_RETURN(TRUE);
1332
1562
  }
1333
1563
 
 
1564
  DBUG_PRINT("info",("Use database: %s", new_db_file_name.str));
 
1565
 
 
1566
 
1334
1567
  if (check_db_dir_existence(new_db_file_name.str))
1335
1568
  {
1336
1569
    if (force_switch)
1337
1570
    {
1338
1571
      /* Throw a warning and free new_db_file_name. */
1339
1572
 
1340
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1573
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1341
1574
                          ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
1342
1575
                          new_db_file_name.str);
1343
1576
 
1344
 
      free(new_db_file_name.str);
 
1577
      my_free(new_db_file_name.str, MYF(0));
1345
1578
 
1346
1579
      /* Change db to NULL. */
1347
1580
 
1349
1582
 
1350
1583
      /* The operation succeed. */
1351
1584
 
1352
 
      return(false);
 
1585
      DBUG_RETURN(FALSE);
1353
1586
    }
1354
1587
    else
1355
1588
    {
1356
1589
      /* Report an error and free new_db_file_name. */
1357
1590
 
1358
1591
      my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
1359
 
      free(new_db_file_name.str);
 
1592
      my_free(new_db_file_name.str, MYF(0));
1360
1593
 
1361
1594
      /* The operation failed. */
1362
1595
 
1363
 
      return(true);
 
1596
      DBUG_RETURN(TRUE);
1364
1597
    }
1365
1598
  }
1366
1599
 
1373
1606
 
1374
1607
  mysql_change_db_impl(thd, &new_db_file_name, db_default_cl);
1375
1608
 
1376
 
  return(false);
 
1609
  DBUG_RETURN(FALSE);
1377
1610
}
1378
1611
 
1379
1612
 
1406
1639
  *cur_db_changed= !cmp_db_names(thd->db, new_db_name->str);
1407
1640
 
1408
1641
  if (!*cur_db_changed)
1409
 
    return false;
 
1642
    return FALSE;
1410
1643
 
1411
1644
  backup_current_db_name(thd, saved_db_name);
1412
1645
 
1414
1647
}
1415
1648
 
1416
1649
 
 
1650
static int
 
1651
lock_databases(THD *thd, const char *db1, uint length1,
 
1652
                         const char *db2, uint length2)
 
1653
{
 
1654
  pthread_mutex_lock(&LOCK_lock_db);
 
1655
  while (!thd->killed &&
 
1656
         (hash_search(&lock_db_cache,(uchar*) db1, length1) ||
 
1657
          hash_search(&lock_db_cache,(uchar*) db2, length2)))
 
1658
  {
 
1659
    wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
 
1660
    pthread_mutex_lock(&LOCK_lock_db);
 
1661
  }
 
1662
 
 
1663
  if (thd->killed)
 
1664
  {
 
1665
    pthread_mutex_unlock(&LOCK_lock_db);
 
1666
    return 1;
 
1667
  }
 
1668
 
 
1669
  lock_db_insert(db1, length1);
 
1670
  lock_db_insert(db2, length2);
 
1671
  creating_database++;
 
1672
 
 
1673
  /*
 
1674
    Wait if a concurent thread is creating a table at the same time.
 
1675
    The assumption here is that it will not take too long until
 
1676
    there is a point in time when a table is not created.
 
1677
  */
 
1678
 
 
1679
  while (!thd->killed && creating_table)
 
1680
  {
 
1681
    wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
 
1682
    pthread_mutex_lock(&LOCK_lock_db);
 
1683
  }
 
1684
 
 
1685
  if (thd->killed)
 
1686
  {
 
1687
    lock_db_delete(db1, length1);
 
1688
    lock_db_delete(db2, length2);
 
1689
    creating_database--;
 
1690
    pthread_mutex_unlock(&LOCK_lock_db);
 
1691
    pthread_cond_signal(&COND_refresh);
 
1692
    return(1);
 
1693
  }
 
1694
 
 
1695
  /*
 
1696
    We can unlock now as the hash will protect against anyone creating a table
 
1697
    in the databases we are using
 
1698
  */
 
1699
  pthread_mutex_unlock(&LOCK_lock_db);
 
1700
  return 0;
 
1701
}
 
1702
 
 
1703
 
 
1704
/**
 
1705
  Upgrade a 5.0 database.
 
1706
  This function is invoked whenever an ALTER DATABASE UPGRADE query is executed:
 
1707
    ALTER DATABASE 'olddb' UPGRADE DATA DIRECTORY NAME.
 
1708
 
 
1709
  If we have managed to rename (move) tables to the new database
 
1710
  but something failed on a later step, then we store the
 
1711
  RENAME DATABASE event in the log. mysql_rename_db() is atomic in
 
1712
  the sense that it will rename all or none of the tables.
 
1713
 
 
1714
  @param thd Current thread
 
1715
  @param old_db 5.0 database name, in #mysql50#name format
 
1716
  @return 0 on success, 1 on error
 
1717
*/
 
1718
bool mysql_upgrade_db(THD *thd, LEX_STRING *old_db)
 
1719
{
 
1720
  int error= 0, change_to_newdb= 0;
 
1721
  char path[FN_REFLEN+16];
 
1722
  uint length;
 
1723
  HA_CREATE_INFO create_info;
 
1724
  MY_DIR *dirp;
 
1725
  TABLE_LIST *table_list;
 
1726
  SELECT_LEX *sl= thd->lex->current_select;
 
1727
  LEX_STRING new_db;
 
1728
  DBUG_ENTER("mysql_upgrade_db");
 
1729
 
 
1730
  if ((old_db->length <= MYSQL50_TABLE_NAME_PREFIX_LENGTH) ||
 
1731
      (strncmp(old_db->str,
 
1732
              MYSQL50_TABLE_NAME_PREFIX,
 
1733
              MYSQL50_TABLE_NAME_PREFIX_LENGTH) != 0))
 
1734
  {
 
1735
    my_error(ER_WRONG_USAGE, MYF(0),
 
1736
             "ALTER DATABASE UPGRADE DATA DIRECTORY NAME",
 
1737
             "name");
 
1738
    DBUG_RETURN(1);
 
1739
  }
 
1740
 
 
1741
  /* `#mysql50#<name>` converted to encoded `<name>` */
 
1742
  new_db.str= old_db->str + MYSQL50_TABLE_NAME_PREFIX_LENGTH;
 
1743
  new_db.length= old_db->length - MYSQL50_TABLE_NAME_PREFIX_LENGTH;
 
1744
 
 
1745
  if (lock_databases(thd, old_db->str, old_db->length,
 
1746
                          new_db.str, new_db.length))
 
1747
    DBUG_RETURN(1);
 
1748
 
 
1749
  /*
 
1750
    Let's remember if we should do "USE newdb" afterwards.
 
1751
    thd->db will be cleared in mysql_rename_db()
 
1752
  */
 
1753
  if (thd->db && !strcmp(thd->db, old_db->str))
 
1754
    change_to_newdb= 1;
 
1755
 
 
1756
  build_table_filename(path, sizeof(path)-1,
 
1757
                       old_db->str, "", MY_DB_OPT_FILE, 0);
 
1758
  if ((load_db_opt(thd, path, &create_info)))
 
1759
    create_info.default_table_charset= thd->variables.collation_server;
 
1760
 
 
1761
  length= build_table_filename(path, sizeof(path)-1, old_db->str, "", "", 0);
 
1762
  if (length && path[length-1] == FN_LIBCHAR)
 
1763
    path[length-1]=0;                            // remove ending '\'
 
1764
  if ((error= my_access(path,F_OK)))
 
1765
  {
 
1766
    my_error(ER_BAD_DB_ERROR, MYF(0), old_db->str);
 
1767
    goto exit;
 
1768
  }
 
1769
 
 
1770
  /* Step1: Create the new database */
 
1771
  if ((error= mysql_create_db(thd, new_db.str, &create_info, 1)))
 
1772
    goto exit;
 
1773
 
 
1774
  /* Step2: Move tables to the new database */
 
1775
  if ((dirp = my_dir(path,MYF(MY_DONT_SORT))))
 
1776
  {
 
1777
    uint nfiles= (uint) dirp->number_off_files;
 
1778
    for (uint idx=0 ; idx < nfiles && !thd->killed ; idx++)
 
1779
    {
 
1780
      FILEINFO *file= dirp->dir_entry + idx;
 
1781
      char *extension, tname[FN_REFLEN];
 
1782
      LEX_STRING table_str;
 
1783
      DBUG_PRINT("info",("Examining: %s", file->name));
 
1784
 
 
1785
      /* skiping non-FRM files */
 
1786
      if (my_strcasecmp(files_charset_info,
 
1787
                        (extension= fn_rext(file->name)), reg_ext))
 
1788
        continue;
 
1789
 
 
1790
      /* A frm file found, add the table info rename list */
 
1791
      *extension= '\0';
 
1792
 
 
1793
      table_str.length= filename_to_tablename(file->name,
 
1794
                                              tname, sizeof(tname)-1);
 
1795
      table_str.str= (char*) sql_memdup(tname, table_str.length + 1);
 
1796
      Table_ident *old_ident= new Table_ident(thd, *old_db, table_str, 0);
 
1797
      Table_ident *new_ident= new Table_ident(thd, new_db, table_str, 0);
 
1798
      if (!old_ident || !new_ident ||
 
1799
          !sl->add_table_to_list(thd, old_ident, NULL,
 
1800
                                 TL_OPTION_UPDATING, TL_IGNORE) ||
 
1801
          !sl->add_table_to_list(thd, new_ident, NULL,
 
1802
                                 TL_OPTION_UPDATING, TL_IGNORE))
 
1803
      {
 
1804
        error= 1;
 
1805
        my_dirend(dirp);
 
1806
        goto exit;
 
1807
      }
 
1808
    }
 
1809
    my_dirend(dirp);  
 
1810
  }
 
1811
 
 
1812
  if ((table_list= thd->lex->query_tables) &&
 
1813
      (error= mysql_rename_tables(thd, table_list, 1)))
 
1814
  {
 
1815
    /*
 
1816
      Failed to move all tables from the old database to the new one.
 
1817
      In the best case mysql_rename_tables() moved all tables back to the old
 
1818
      database. In the worst case mysql_rename_tables() moved some tables
 
1819
      to the new database, then failed, then started to move the tables back,
 
1820
      and then failed again. In this situation we have some tables in the
 
1821
      old database and some tables in the new database.
 
1822
      Let's delete the option file, and then the new database directory.
 
1823
      If some tables were left in the new directory, rmdir() will fail.
 
1824
      It garantees we never loose any tables.
 
1825
    */
 
1826
    build_table_filename(path, sizeof(path)-1,
 
1827
                         new_db.str,"",MY_DB_OPT_FILE, 0);
 
1828
    my_delete(path, MYF(MY_WME));
 
1829
    length= build_table_filename(path, sizeof(path)-1, new_db.str, "", "", 0);
 
1830
    if (length && path[length-1] == FN_LIBCHAR)
 
1831
      path[length-1]=0;                            // remove ending '\'
 
1832
    rmdir(path);
 
1833
    goto exit;
 
1834
  }
 
1835
 
 
1836
 
 
1837
  if ((dirp = my_dir(path,MYF(MY_DONT_SORT))))
 
1838
  {
 
1839
    uint nfiles= (uint) dirp->number_off_files;
 
1840
    for (uint idx=0 ; idx < nfiles ; idx++)
 
1841
    {
 
1842
      FILEINFO *file= dirp->dir_entry + idx;
 
1843
      char oldname[FN_REFLEN], newname[FN_REFLEN];
 
1844
      DBUG_PRINT("info",("Examining: %s", file->name));
 
1845
 
 
1846
      /* skiping . and .. and MY_DB_OPT_FILE */
 
1847
      if ((file->name[0] == '.' &&
 
1848
           (!file->name[1] || (file->name[1] == '.' && !file->name[2]))) ||
 
1849
          !my_strcasecmp(files_charset_info, file->name, MY_DB_OPT_FILE))
 
1850
        continue;
 
1851
 
 
1852
      /* pass empty file name, and file->name as extension to avoid encoding */
 
1853
      build_table_filename(oldname, sizeof(oldname)-1,
 
1854
                           old_db->str, "", file->name, 0);
 
1855
      build_table_filename(newname, sizeof(newname)-1,
 
1856
                           new_db.str, "", file->name, 0);
 
1857
      my_rename(oldname, newname, MYF(MY_WME));
 
1858
    }
 
1859
    my_dirend(dirp);
 
1860
  }
 
1861
 
 
1862
  /*
 
1863
    Step7: drop the old database.
 
1864
    remove_db_from_cache(olddb) and query_cache_invalidate(olddb)
 
1865
    are done inside mysql_rm_db(), no needs to execute them again.
 
1866
    mysql_rm_db() also "unuses" if we drop the current database.
 
1867
  */
 
1868
  error= mysql_rm_db(thd, old_db->str, 0, 1);
 
1869
 
 
1870
  /* Step8: logging */
 
1871
  if (mysql_bin_log.is_open())
 
1872
  {
 
1873
    Query_log_event qinfo(thd, thd->query, thd->query_length, 0, TRUE);
 
1874
    thd->clear_error();
 
1875
    mysql_bin_log.write(&qinfo);
 
1876
  }
 
1877
 
 
1878
  /* Step9: Let's do "use newdb" if we renamed the current database */
 
1879
  if (change_to_newdb)
 
1880
    error|= mysql_change_db(thd, & new_db, FALSE);
 
1881
 
 
1882
exit:
 
1883
  pthread_mutex_lock(&LOCK_lock_db);
 
1884
  /* Remove the databases from db lock cache */
 
1885
  lock_db_delete(old_db->str, old_db->length);
 
1886
  lock_db_delete(new_db.str, new_db.length);
 
1887
  creating_database--;
 
1888
  /* Signal waiting CREATE TABLE's to continue */
 
1889
  pthread_cond_signal(&COND_refresh);
 
1890
  pthread_mutex_unlock(&LOCK_lock_db);
 
1891
 
 
1892
  DBUG_RETURN(error);
 
1893
}
 
1894
 
 
1895
 
 
1896
 
1417
1897
/*
1418
1898
  Check if there is directory for the database name.
1419
1899
 
1422
1902
    db_name   database name
1423
1903
 
1424
1904
  RETURN VALUES
1425
 
    false   There is directory for the specified database name.
1426
 
    true    The directory does not exist.
 
1905
    FALSE   There is directory for the specified database name.
 
1906
    TRUE    The directory does not exist.
1427
1907
*/
1428
1908
 
1429
1909
bool check_db_dir_existence(const char *db_name)
1430
1910
{
1431
1911
  char db_dir_path[FN_REFLEN];
1432
 
  uint32_t db_dir_path_len;
 
1912
  uint db_dir_path_len;
1433
1913
 
1434
1914
  db_dir_path_len= build_table_filename(db_dir_path, sizeof(db_dir_path),
1435
1915
                                        db_name, "", "", 0);