~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/sql_db.cc

  • Committer: Monty Taylor
  • Date: 2008-07-05 22:08:52 UTC
  • mto: This revision was merged to the branch mainline in revision 77.
  • Revision ID: monty@inaugust.com-20080705220852-cqd9t6tfkhvlcf73
Removed HAVE_LONG_LONG, as this is now assumed.

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 CSTDINT_H
20
 
#include CINTTYPES_H
21
 
#include <string>
22
 
#include <fstream>
23
 
#include <drizzled/serialize/serialize.h>
24
 
using namespace std;
25
 
#include <drizzled/server_includes.h>
26
 
#include <mysys/mysys_err.h>
27
 
#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>
28
23
#include "log.h"
29
 
#include <drizzled/drizzled_error_messages.h>
30
 
#include <libdrizzle/gettext.h>
31
 
 
32
24
 
33
25
#define MAX_DROP_TABLE_Q_LEN      1024
34
26
 
35
 
const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NULL};
 
27
const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS};
36
28
static TYPELIB deletable_extentions=
37
29
{array_elements(del_exts)-1,"del_exts", del_exts, NULL};
38
30
 
39
31
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
40
 
                                 const char *db, const char *path, uint32_t level, 
41
 
                                 TableList **dropped_tables);
 
32
                                 const char *db, const char *path, uint level, 
 
33
                                 TABLE_LIST **dropped_tables);
42
34
         
43
 
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);
44
37
static void mysql_change_db_impl(THD *thd,
45
38
                                 LEX_STRING *new_db_name,
46
 
                                 const CHARSET_INFO * const new_db_charset);
 
39
                                 CHARSET_INFO *new_db_charset);
47
40
 
48
41
 
49
42
/* Database lock hash */
56
49
typedef struct my_dblock_st
57
50
{
58
51
  char *name;        /* Database name        */
59
 
  uint32_t name_length;  /* Database length name */
 
52
  uint name_length;  /* Database length name */
60
53
} my_dblock_t;
61
54
 
62
55
 
64
57
  lock_db key.
65
58
*/
66
59
 
67
 
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);
68
61
 
69
 
unsigned char* lock_db_get_key(my_dblock_t *ptr, size_t *length,
70
 
                       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)))
71
64
{
72
65
  *length= ptr->name_length;
73
 
  return (unsigned char*) ptr->name;
 
66
  return (uchar*) ptr->name;
74
67
}
75
68
 
76
69
 
82
75
 
83
76
void lock_db_free_element(void *ptr)
84
77
{
85
 
  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);
86
125
}
87
126
 
88
127
 
90
129
  Delete a database lock entry from hash.
91
130
*/
92
131
 
93
 
void lock_db_delete(const char *name, uint32_t length)
 
132
void lock_db_delete(const char *name, uint length)
94
133
{
95
134
  my_dblock_t *opt;
96
135
  safe_mutex_assert_owner(&LOCK_lock_db);
97
136
  if ((opt= (my_dblock_t *)hash_search(&lock_db_cache,
98
 
                                       (const unsigned char*) name, length)))
99
 
    hash_delete(&lock_db_cache, (unsigned char*) opt);
 
137
                                       (const uchar*) name, length)))
 
138
    hash_delete(&lock_db_cache, (uchar*) opt);
100
139
}
101
140
 
102
141
 
103
142
/* Database options hash */
104
143
static HASH dboptions;
105
 
static bool dboptions_init= 0;
 
144
static my_bool dboptions_init= 0;
106
145
static rw_lock_t LOCK_dboptions;
107
146
 
108
147
/* Structure for database options */
109
148
typedef struct my_dbopt_st
110
149
{
111
150
  char *name;                   /* Database name                  */
112
 
  uint32_t name_length;         /* Database length name           */
113
 
  const CHARSET_INFO *charset;  /* Database default character set */
 
151
  uint name_length;             /* Database length name           */
 
152
  CHARSET_INFO *charset;        /* Database default character set */
114
153
} my_dbopt_t;
115
154
 
116
155
 
118
157
  Function we use in the creation of our hash to get key.
119
158
*/
120
159
 
121
 
extern "C" unsigned char* dboptions_get_key(my_dbopt_t *opt, size_t *length,
122
 
                                    bool not_used);
 
160
extern "C" uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length,
 
161
                                    my_bool not_used);
123
162
 
124
 
unsigned char* dboptions_get_key(my_dbopt_t *opt, size_t *length,
125
 
                         bool not_used __attribute__((unused)))
 
163
uchar* dboptions_get_key(my_dbopt_t *opt, size_t *length,
 
164
                         my_bool not_used __attribute__((unused)))
126
165
{
127
166
  *length= opt->name_length;
128
 
  return (unsigned char*) opt->name;
 
167
  return (uchar*) opt->name;
129
168
}
130
169
 
131
170
 
133
172
  Helper function to write a query to binlog used by mysql_rm_db()
134
173
*/
135
174
 
136
 
static inline void write_to_binlog(THD *thd, char *query, uint32_t q_len,
137
 
                                   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)
138
177
{
139
178
  Query_log_event qinfo(thd, query, q_len, 0, 0);
140
179
  qinfo.error_code= 0;
152
191
 
153
192
void free_dbopt(void *dbopt)
154
193
{
155
 
  free((unsigned char*) dbopt);
 
194
  my_free((uchar*) dbopt, MYF(0));
156
195
}
157
196
 
158
197
 
172
211
 
173
212
bool my_database_names_init(void)
174
213
{
175
 
  bool error= false;
 
214
  bool error= 0;
176
215
  (void) my_rwlock_init(&LOCK_dboptions, NULL);
177
216
  if (!dboptions_init)
178
217
  {
236
275
    1 on error.
237
276
*/
238
277
 
239
 
static bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
 
278
static my_bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
240
279
{
241
280
  my_dbopt_t *opt;
242
 
  uint32_t length;
243
 
  bool error= true;
 
281
  uint length;
 
282
  my_bool error= 1;
244
283
  
245
284
  length= (uint) strlen(dbname);
246
285
  
247
286
  rw_rdlock(&LOCK_dboptions);
248
 
  if ((opt= (my_dbopt_t*) hash_search(&dboptions, (unsigned char*) dbname, length)))
 
287
  if ((opt= (my_dbopt_t*) hash_search(&dboptions, (uchar*) dbname, length)))
249
288
  {
250
289
    create->default_table_charset= opt->charset;
251
 
    error= true;
 
290
    error= 0;
252
291
  }
253
292
  rw_unlock(&LOCK_dboptions);
254
293
  return error;
267
306
    1 on error.
268
307
*/
269
308
 
270
 
static bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
 
309
static my_bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
271
310
{
272
311
  my_dbopt_t *opt;
273
 
  uint32_t length;
274
 
  bool error= false;
 
312
  uint length;
 
313
  my_bool error= 0;
 
314
  DBUG_ENTER("put_dbopt");
275
315
 
276
316
  length= (uint) strlen(dbname);
277
317
  
278
318
  rw_wrlock(&LOCK_dboptions);
279
 
  if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (unsigned char*) dbname, length)))
 
319
  if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (uchar*) dbname, length)))
280
320
  { 
281
321
    /* Options are not in the hash, insert them */
282
322
    char *tmp_name;
283
323
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
284
324
                         &opt, (uint) sizeof(*opt), &tmp_name, (uint) length+1,
285
 
                         NULL))
 
325
                         NullS))
286
326
    {
287
 
      error= true;
 
327
      error= 1;
288
328
      goto end;
289
329
    }
290
330
    
291
331
    opt->name= tmp_name;
292
 
    my_stpcpy(opt->name, dbname);
 
332
    strmov(opt->name, dbname);
293
333
    opt->name_length= length;
294
334
    
295
 
    if ((error= my_hash_insert(&dboptions, (unsigned char*) opt)))
 
335
    if ((error= my_hash_insert(&dboptions, (uchar*) opt)))
296
336
    {
297
 
      free(opt);
 
337
      my_free(opt, MYF(0));
298
338
      goto end;
299
339
    }
300
340
  }
304
344
 
305
345
end:
306
346
  rw_unlock(&LOCK_dboptions);  
307
 
  return(error);
 
347
  DBUG_RETURN(error);
308
348
}
309
349
 
310
350
 
316
356
{
317
357
  my_dbopt_t *opt;
318
358
  rw_wrlock(&LOCK_dboptions);
319
 
  if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const unsigned char*) path,
 
359
  if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const uchar*) path,
320
360
                                      strlen(path))))
321
 
    hash_delete(&dboptions, (unsigned char*) opt);
 
361
    hash_delete(&dboptions, (uchar*) opt);
322
362
  rw_unlock(&LOCK_dboptions);
323
363
}
324
364
 
334
374
  1     Could not create file or write to it.  Error sent through my_error()
335
375
*/
336
376
 
337
 
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)
338
378
{
339
 
  bool error= true;
340
 
  drizzle::Schema db;
341
 
 
342
 
  assert(name);
 
379
  register File file;
 
380
  char buf[256]; // Should be enough for one option
 
381
  bool error=1;
343
382
 
344
383
  if (!create->default_table_charset)
345
384
    create->default_table_charset= thd->variables.collation_server;
347
386
  if (put_dbopt(path, create))
348
387
    return 1;
349
388
 
350
 
  db.set_name(name);
351
 
  db.set_characterset(create->default_table_charset->csname);
352
 
  db.set_collation(create->default_table_charset->name);
353
 
 
354
 
  fstream output(path, ios::out | ios::trunc | ios::binary);
355
 
  if (!db.SerializeToOstream(&output)) 
356
 
    error= false;
357
 
 
 
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
  }
358
403
  return error;
359
404
}
360
405
 
376
421
 
377
422
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
378
423
{
 
424
  File file;
 
425
  char buf[256];
 
426
  DBUG_ENTER("load_db_opt");
379
427
  bool error=1;
380
 
  drizzle::Schema db;
381
 
  string buffer;
 
428
  uint nbytes;
382
429
 
383
 
  memset(create, 0, sizeof(*create));
 
430
  bzero((char*) create,sizeof(*create));
384
431
  create->default_table_charset= thd->variables.collation_server;
385
432
 
386
433
  /* Check if options for this database are already in the hash */
387
434
  if (!get_dbopt(path, create))
388
 
    return(0);
389
 
 
390
 
  fstream input(path, ios::in | ios::binary);
391
 
  if (!input)
392
 
    goto err1;
393
 
  else if (!db.ParseFromIstream(&input))
394
 
    goto err1;
395
 
 
396
 
  buffer= db.characterset();
397
 
  if (!(create->default_table_charset= get_charset_by_csname(buffer.c_str(), MY_CS_PRIMARY, MYF(0))))
398
 
  {
399
 
    sql_print_error(_("Error while loading database options: '%s':"),path);
400
 
    sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
401
 
    create->default_table_charset= default_charset_info;
402
 
  }
403
 
 
404
 
  buffer= db.collation();
405
 
  if (!(create->default_table_charset= get_charset_by_name(buffer.c_str(), MYF(0))))
406
 
  {
407
 
    sql_print_error(_("Error while loading database options: '%s':"),path);
408
 
    sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
409
 
    create->default_table_charset= default_charset_info;
410
 
  }
411
 
 
 
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
  }
412
485
  /*
413
486
    Put the loaded value into the hash.
414
487
    Note that another thread could've added the same
418
491
  */
419
492
  error= put_dbopt(path, create);
420
493
 
 
494
  end_io_cache(&cache);
 
495
err2:
 
496
  my_close(file,MYF(0));
421
497
err1:
422
 
  return(error);
 
498
  DBUG_RETURN(error);
423
499
}
424
500
 
425
501
 
440
516
    the operation, it is useless usually and should be ignored. The problem
441
517
    is that there are 1) system databases ("mysql") and 2) virtual
442
518
    databases ("information_schema"), which do not contain options file.
443
 
    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
444
520
    is not an error.
445
521
 
446
522
    load_db_opt[_by_name]() clears db_create_info structure in any case, so
449
525
    db_create_info right after that.
450
526
 
451
527
  RETURN VALUES (read NOTE!)
452
 
    false   Success
453
 
    true    Failed to retrieve options
 
528
    FALSE   Success
 
529
    TRUE    Failed to retrieve options
454
530
*/
455
531
 
456
532
bool load_db_opt_by_name(THD *thd, const char *db_name,
479
555
    set, even if the database does not exist.
480
556
*/
481
557
 
482
 
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)
483
559
{
484
560
  HA_CREATE_INFO db_info;
485
561
 
519
595
   (The 'silent' flags turns off 1 and 3.)
520
596
 
521
597
  RETURN VALUES
522
 
  false ok
523
 
  true  Error
 
598
  FALSE ok
 
599
  TRUE  Error
524
600
 
525
601
*/
526
602
 
527
 
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)
528
605
{
529
606
  char   path[FN_REFLEN+16];
530
607
  char   tmp_query[FN_REFLEN+16];
531
608
  long result= 1;
532
609
  int error= 0;
533
610
  struct stat stat_info;
534
 
  uint32_t create_options= create_info ? create_info->options : 0;
535
 
  uint32_t path_len;
 
611
  uint create_options= create_info ? create_info->options : 0;
 
612
  uint path_len;
 
613
  DBUG_ENTER("mysql_create_db");
536
614
 
537
615
  /* do not create 'information_schema' db */
538
616
  if (!my_strcasecmp(system_charset_info, db, INFORMATION_SCHEMA_NAME.str))
539
617
  {
540
618
    my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
541
 
    return(-1);
 
619
    DBUG_RETURN(-1);
542
620
  }
543
621
 
544
622
  /*
559
637
    goto exit2;
560
638
  }
561
639
 
562
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
 
640
  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
563
641
 
564
642
  /* Check directory */
565
643
  path_len= build_table_filename(path, sizeof(path), db, "", "", 0);
573
651
      error= -1;
574
652
      goto exit;
575
653
    }
576
 
    push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
654
    push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
577
655
                        ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
578
656
    if (!silent)
579
657
      my_ok(thd);
597
675
 
598
676
  path[path_len-1]= FN_LIBCHAR;
599
677
  strmake(path+path_len, MY_DB_OPT_FILE, sizeof(path)-path_len-1);
600
 
  if (write_db_opt(thd, path, db, create_info))
 
678
  if (write_db_opt(thd, path, create_info))
601
679
  {
602
680
    /*
603
681
      Could not create options file.
619
697
  if (!silent)
620
698
  {
621
699
    char *query;
622
 
    uint32_t query_length;
 
700
    uint query_length;
623
701
 
624
702
    if (!thd->query)                            // Only in replication
625
703
    {
626
704
      query=         tmp_query;
627
705
      query_length= (uint) (strxmov(tmp_query,"create database `",
628
 
                                    db, "`", NULL) - tmp_query);
 
706
                                    db, "`", NullS) - tmp_query);
629
707
    }
630
708
    else
631
709
    {
633
711
      query_length= thd->query_length;
634
712
    }
635
713
 
 
714
    ha_binlog_log_query(thd, 0, LOGCOM_CREATE_DB,
 
715
                        query, query_length,
 
716
                        db, "");
 
717
 
636
718
    if (mysql_bin_log.is_open())
637
719
    {
638
720
      Query_log_event qinfo(thd, query, query_length, 0, 
639
 
                            /* suppress_use */ true);
 
721
                            /* suppress_use */ TRUE);
640
722
 
641
723
      /*
642
724
        Write should use the database being created as the "current
665
747
  }
666
748
 
667
749
exit:
668
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
 
750
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
669
751
  start_waiting_global_read_lock(thd);
670
752
exit2:
671
 
  return(error);
 
753
  DBUG_RETURN(error);
672
754
}
673
755
 
674
756
 
678
760
{
679
761
  char path[FN_REFLEN+16];
680
762
  long result=1;
681
 
  int error= false;
 
763
  int error= 0;
 
764
  DBUG_ENTER("mysql_alter_db");
682
765
 
683
766
  /*
684
767
    Do not alter database if another thread is holding read lock.
695
778
  if ((error=wait_if_global_read_lock(thd,0,1)))
696
779
    goto exit2;
697
780
 
698
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
 
781
  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
699
782
 
700
783
  /* 
701
784
     Recreate db options file: /dbpath/.db.opt
703
786
     "table name to file name" encoding.
704
787
  */
705
788
  build_table_filename(path, sizeof(path), db, "", MY_DB_OPT_FILE, 0);
706
 
  if ((error=write_db_opt(thd, path, db, create_info)))
 
789
  if ((error=write_db_opt(thd, path, create_info)))
707
790
    goto exit;
708
791
 
709
792
  /* Change options if current database is being altered. */
716
799
    thd->variables.collation_database= thd->db_charset;
717
800
  }
718
801
 
 
802
  ha_binlog_log_query(thd, 0, LOGCOM_ALTER_DB,
 
803
                      thd->query, thd->query_length,
 
804
                      db, "");
 
805
 
719
806
  if (mysql_bin_log.is_open())
720
807
  {
721
808
    Query_log_event qinfo(thd, thd->query, thd->query_length, 0,
722
 
                          /* suppress_use */ true);
 
809
                          /* suppress_use */ TRUE);
723
810
 
724
811
    /*
725
812
      Write should use the database being created as the "current
736
823
  my_ok(thd, result);
737
824
 
738
825
exit:
739
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
 
826
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
740
827
  start_waiting_global_read_lock(thd);
741
828
exit2:
742
 
  return(error);
 
829
  DBUG_RETURN(error);
743
830
}
744
831
 
745
832
 
756
843
    silent              Don't generate errors
757
844
 
758
845
  RETURN
759
 
    false ok (Database dropped)
 
846
    FALSE ok (Database dropped)
760
847
    ERROR Error
761
848
*/
762
849
 
763
850
bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
764
851
{
765
852
  long deleted=0;
766
 
  int error= false;
 
853
  int error= 0;
767
854
  char  path[FN_REFLEN+16];
768
855
  MY_DIR *dirp;
769
 
  uint32_t length;
770
 
  TableList* dropped_tables= 0;
 
856
  uint length;
 
857
  TABLE_LIST* dropped_tables= 0;
 
858
  DBUG_ENTER("mysql_rm_db");
771
859
 
772
860
  if (db && (strcmp(db, "information_schema") == 0))
773
861
  {
774
862
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
775
 
    return(true);
 
863
    DBUG_RETURN(TRUE);
776
864
  }
777
865
 
778
866
  /*
793
881
    goto exit2;
794
882
  }
795
883
 
796
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
 
884
  VOID(pthread_mutex_lock(&LOCK_mysql_create_db));
797
885
 
798
886
  /*
799
887
    This statement will be replicated as a statement, even when using
803
891
  thd->clear_current_stmt_binlog_row_based();
804
892
 
805
893
  length= build_table_filename(path, sizeof(path), db, "", "", 0);
806
 
  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
807
895
  del_dbopt(path);                              // Remove dboption hash entry
808
896
  path[length]= '\0';                           // Remove file name
809
897
 
817
905
      goto exit;
818
906
    }
819
907
    else
820
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
908
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
821
909
                          ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
822
910
  }
823
911
  else
838
926
  if (!silent && deleted>=0)
839
927
  {
840
928
    const char *query;
841
 
    uint32_t query_length;
 
929
    ulong query_length;
842
930
    if (!thd->query)
843
931
    {
844
932
      /* The client used the old obsolete mysql_drop_db() call */
845
933
      query= path;
846
934
      query_length= (uint) (strxmov(path, "drop database `", db, "`",
847
 
                                     NULL) - path);
 
935
                                     NullS) - path);
848
936
    }
849
937
    else
850
938
    {
854
942
    if (mysql_bin_log.is_open())
855
943
    {
856
944
      Query_log_event qinfo(thd, query, query_length, 0, 
857
 
                            /* suppress_use */ true);
 
945
                            /* suppress_use */ TRUE);
858
946
      /*
859
947
        Write should use the database being created as the "current
860
948
        database" and not the threads current database, which is the
869
957
    }
870
958
    thd->clear_error();
871
959
    thd->server_status|= SERVER_STATUS_DB_DROPPED;
872
 
    my_ok(thd, (uint32_t) deleted);
 
960
    my_ok(thd, (ulong) deleted);
873
961
    thd->server_status&= ~SERVER_STATUS_DB_DROPPED;
874
962
  }
875
963
  else if (mysql_bin_log.is_open())
876
964
  {
877
965
    char *query, *query_pos, *query_end, *query_data_start;
878
 
    TableList *tbl;
879
 
    uint32_t db_len;
 
966
    TABLE_LIST *tbl;
 
967
    uint db_len;
880
968
 
881
969
    if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN)))
882
970
      goto exit; /* not much else we can do */
883
 
    query_pos= query_data_start= my_stpcpy(query,"drop table ");
 
971
    query_pos= query_data_start= strmov(query,"drop table ");
884
972
    query_end= query + MAX_DROP_TABLE_Q_LEN;
885
973
    db_len= strlen(db);
886
974
 
887
975
    for (tbl= dropped_tables; tbl; tbl= tbl->next_local)
888
976
    {
889
 
      uint32_t tbl_name_len;
 
977
      uint tbl_name_len;
890
978
 
891
979
      /* 3 for the quotes and the comma*/
892
980
      tbl_name_len= strlen(tbl->table_name) + 3;
898
986
      }
899
987
 
900
988
      *query_pos++ = '`';
901
 
      query_pos= my_stpcpy(query_pos,tbl->table_name);
 
989
      query_pos= strmov(query_pos,tbl->table_name);
902
990
      *query_pos++ = '`';
903
991
      *query_pos++ = ',';
904
992
    }
919
1007
  */
920
1008
  if (thd->db && !strcmp(thd->db, db))
921
1009
    mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
922
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
 
1010
  VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
923
1011
  start_waiting_global_read_lock(thd);
924
1012
exit2:
925
 
  return(error);
 
1013
  DBUG_RETURN(error);
926
1014
}
927
1015
 
928
1016
/*
929
 
  Removes files with known extensions plus.
 
1017
  Removes files with known extensions plus all found subdirectories that
 
1018
  are 2 hex digits (raid directories).
930
1019
  thd MUST be set when calling this function!
931
1020
*/
932
1021
 
933
1022
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
934
 
                                 const char *org_path, uint32_t level,
935
 
                                 TableList **dropped_tables)
 
1023
                                 const char *org_path, uint level,
 
1024
                                 TABLE_LIST **dropped_tables)
936
1025
{
937
1026
  long deleted=0;
938
 
  uint32_t found_other_files=0;
 
1027
  ulong found_other_files=0;
939
1028
  char filePath[FN_REFLEN];
940
 
  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));
941
1033
 
942
1034
  tot_list_next= &tot_list;
943
1035
 
944
 
  for (uint32_t idx=0 ;
 
1036
  for (uint idx=0 ;
945
1037
       idx < (uint) dirp->number_off_files && !thd->killed ;
946
1038
       idx++)
947
1039
  {
948
1040
    FILEINFO *file=dirp->dir_entry+idx;
949
1041
    char *extension;
 
1042
    DBUG_PRINT("info",("Examining: %s", file->name));
950
1043
 
951
1044
    /* skiping . and .. */
952
1045
    if (file->name[0] == '.' && (!file->name[1] ||
953
1046
       (file->name[1] == '.' &&  !file->name[2])))
954
1047
      continue;
955
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
    }
956
1096
    if (!(extension= strrchr(file->name, '.')))
957
 
      extension= strchr(file->name, '\0');
 
1097
      extension= strend(file->name);
958
1098
    if (find_type(extension, &deletable_extentions,1+2) <= 0)
959
1099
    {
960
1100
      if (find_type(extension, ha_known_exts(),1+2) <= 0)
967
1107
    {
968
1108
      /* Drop the table nicely */
969
1109
      *extension= 0;                    // Remove extension
970
 
      TableList *table_list=(TableList*)
 
1110
      TABLE_LIST *table_list=(TABLE_LIST*)
971
1111
                              thd->calloc(sizeof(*table_list) + 
972
1112
                                          strlen(db) + 1 +
973
1113
                                          MYSQL50_TABLE_NAME_PREFIX_LENGTH + 
976
1116
      if (!table_list)
977
1117
        goto err;
978
1118
      table_list->db= (char*) (table_list+1);
979
 
      table_list->table_name= my_stpcpy(table_list->db, db) + 1;
980
 
      filename_to_tablename(file->name, table_list->table_name,
981
 
                            MYSQL50_TABLE_NAME_PREFIX_LENGTH +
982
 
                            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));
983
1123
      table_list->alias= table_list->table_name;        // If lower_case_table_names=2
984
1124
      table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix);
985
1125
      /* Link into list */
989
1129
    }
990
1130
    else
991
1131
    {
992
 
      strxmov(filePath, org_path, "/", file->name, NULL);
 
1132
      strxmov(filePath, org_path, "/", file->name, NullS);
993
1133
      if (my_delete_with_symlink(filePath,MYF(MY_WME)))
994
1134
      {
995
1135
        goto err;
1000
1140
      (tot_list && mysql_rm_table_part2(thd, tot_list, 1, 0, 1, 1)))
1001
1141
    goto err;
1002
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
  }
1003
1151
  my_dirend(dirp);  
1004
1152
  
1005
1153
  if (dropped_tables)
1012
1160
  if (found_other_files)
1013
1161
  {
1014
1162
    my_error(ER_DB_DROP_RMDIR, MYF(0), org_path, EEXIST);
1015
 
    return(-1);
 
1163
    DBUG_RETURN(-1);
1016
1164
  }
1017
1165
  else
1018
1166
  {
1019
1167
    /* Don't give errors if we can't delete 'RAID' directory */
1020
1168
    if (rm_dir_w_symlink(org_path, level == 0))
1021
 
      return(-1);
 
1169
      DBUG_RETURN(-1);
1022
1170
  }
1023
1171
 
1024
 
  return(deleted);
 
1172
  DBUG_RETURN(deleted);
1025
1173
 
1026
1174
err:
1027
1175
  my_dirend(dirp);
1028
 
  return(-1);
 
1176
  DBUG_RETURN(-1);
1029
1177
}
1030
1178
 
1031
1179
 
1041
1189
    1 ERROR
1042
1190
*/
1043
1191
 
1044
 
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)
1045
1193
{
1046
1194
  char tmp_path[FN_REFLEN], *pos;
1047
1195
  char *path= tmp_path;
 
1196
  DBUG_ENTER("rm_dir_w_symlink");
1048
1197
  unpack_filename(tmp_path, org_path);
1049
1198
#ifdef HAVE_READLINK
1050
1199
  int error;
1051
1200
  char tmp2_path[FN_REFLEN];
1052
1201
 
1053
1202
  /* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
1054
 
  pos= strchr(path, '\0');
 
1203
  pos= strend(path);
1055
1204
  if (pos > path && pos[-1] == FN_LIBCHAR)
1056
1205
    *--pos=0;
1057
1206
 
1058
1207
  if ((error= my_readlink(tmp2_path, path, MYF(MY_WME))) < 0)
1059
 
    return(1);
 
1208
    DBUG_RETURN(1);
1060
1209
  if (!error)
1061
1210
  {
1062
1211
    if (my_delete(path, MYF(send_error ? MY_WME : 0)))
1063
1212
    {
1064
 
      return(send_error);
 
1213
      DBUG_RETURN(send_error);
1065
1214
    }
1066
1215
    /* Delete directory symbolic link pointed at */
1067
1216
    path= tmp2_path;
1068
1217
  }
1069
1218
#endif
1070
1219
  /* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
1071
 
  pos= strchr(path, '\0');
 
1220
  pos= strend(path);
1072
1221
 
1073
1222
  if (pos > path && pos[-1] == FN_LIBCHAR)
1074
1223
    *--pos=0;
1075
1224
  if (rmdir(path) < 0 && send_error)
1076
1225
  {
1077
1226
    my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
1078
 
    return(1);
1079
 
  }
1080
 
  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);
1081
1307
}
1082
1308
 
1083
1309
 
1094
1320
 
1095
1321
static void mysql_change_db_impl(THD *thd,
1096
1322
                                 LEX_STRING *new_db_name,
1097
 
                                 const CHARSET_INFO * const new_db_charset)
 
1323
                                 CHARSET_INFO *new_db_charset)
1098
1324
{
1099
1325
  /* 1. Change current database in THD. */
1100
1326
 
1124
1350
      the previous database name, we should do it explicitly.
1125
1351
    */
1126
1352
 
1127
 
    if (thd->db)
1128
 
      free(thd->db);
 
1353
    x_free(thd->db);
1129
1354
 
1130
1355
    thd->reset_db(new_db_name->str, new_db_name->length);
1131
1356
  }
1172
1397
 
1173
1398
 
1174
1399
/**
1175
 
  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.
1176
1401
 
1177
1402
  The function allows to compare database names according to the MySQL
1178
1403
  rules. The database names db1 and db2 are equal if:
1200
1425
 
1201
1426
  @param thd          thread handle
1202
1427
  @param new_db_name  database name
1203
 
  @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
1204
1429
 
1205
1430
                        - new_db_name is NULL or empty;
1206
1431
 
1211
1436
 
1212
1437
                        - OR new database does not exist;
1213
1438
 
1214
 
                      if force_switch is true, then
 
1439
                      if force_switch is TRUE, then
1215
1440
 
1216
1441
                        - if new_db_name is NULL or empty, the current
1217
1442
                          database will be NULL, @@collation_database will
1253
1478
  the stack address was long gone.
1254
1479
 
1255
1480
  @return Operation status
1256
 
    @retval false Success
1257
 
    @retval true  Error
 
1481
    @retval FALSE Success
 
1482
    @retval TRUE  Error
1258
1483
*/
1259
1484
 
1260
1485
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
1261
1486
{
1262
1487
  LEX_STRING new_db_file_name;
1263
 
  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));
1264
1492
 
1265
1493
  if (new_db_name == NULL ||
1266
1494
      new_db_name->length == 0)
1279
1507
 
1280
1508
      mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
1281
1509
 
1282
 
      return(false);
 
1510
      DBUG_RETURN(FALSE);
1283
1511
    }
1284
1512
    else
1285
1513
    {
1286
1514
      my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1287
1515
 
1288
 
      return(true);
 
1516
      DBUG_RETURN(TRUE);
1289
1517
    }
1290
1518
  }
1291
1519
 
1296
1524
 
1297
1525
    mysql_change_db_impl(thd, &INFORMATION_SCHEMA_NAME, system_charset_info);
1298
1526
 
1299
 
    return(false);
 
1527
    DBUG_RETURN(FALSE);
1300
1528
  }
1301
1529
 
1302
1530
  /*
1311
1539
  new_db_file_name.length= new_db_name->length;
1312
1540
 
1313
1541
  if (new_db_file_name.str == NULL)
1314
 
    return(true);                             /* the error is set */
 
1542
    DBUG_RETURN(TRUE);                             /* the error is set */
1315
1543
 
1316
1544
  /*
1317
1545
    NOTE: if check_db_name() fails, we should throw an error in any case,
1325
1553
  if (check_db_name(&new_db_file_name))
1326
1554
  {
1327
1555
    my_error(ER_WRONG_DB_NAME, MYF(0), new_db_file_name.str);
1328
 
    free(new_db_file_name.str);
 
1556
    my_free(new_db_file_name.str, MYF(0));
1329
1557
 
1330
1558
    if (force_switch)
1331
1559
      mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
1332
1560
 
1333
 
    return(true);
 
1561
    DBUG_RETURN(TRUE);
1334
1562
  }
1335
1563
 
 
1564
  DBUG_PRINT("info",("Use database: %s", new_db_file_name.str));
 
1565
 
 
1566
 
1336
1567
  if (check_db_dir_existence(new_db_file_name.str))
1337
1568
  {
1338
1569
    if (force_switch)
1339
1570
    {
1340
1571
      /* Throw a warning and free new_db_file_name. */
1341
1572
 
1342
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1573
      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1343
1574
                          ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
1344
1575
                          new_db_file_name.str);
1345
1576
 
1346
 
      free(new_db_file_name.str);
 
1577
      my_free(new_db_file_name.str, MYF(0));
1347
1578
 
1348
1579
      /* Change db to NULL. */
1349
1580
 
1351
1582
 
1352
1583
      /* The operation succeed. */
1353
1584
 
1354
 
      return(false);
 
1585
      DBUG_RETURN(FALSE);
1355
1586
    }
1356
1587
    else
1357
1588
    {
1358
1589
      /* Report an error and free new_db_file_name. */
1359
1590
 
1360
1591
      my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
1361
 
      free(new_db_file_name.str);
 
1592
      my_free(new_db_file_name.str, MYF(0));
1362
1593
 
1363
1594
      /* The operation failed. */
1364
1595
 
1365
 
      return(true);
 
1596
      DBUG_RETURN(TRUE);
1366
1597
    }
1367
1598
  }
1368
1599
 
1375
1606
 
1376
1607
  mysql_change_db_impl(thd, &new_db_file_name, db_default_cl);
1377
1608
 
1378
 
  return(false);
 
1609
  DBUG_RETURN(FALSE);
1379
1610
}
1380
1611
 
1381
1612
 
1408
1639
  *cur_db_changed= !cmp_db_names(thd->db, new_db_name->str);
1409
1640
 
1410
1641
  if (!*cur_db_changed)
1411
 
    return false;
 
1642
    return FALSE;
1412
1643
 
1413
1644
  backup_current_db_name(thd, saved_db_name);
1414
1645
 
1416
1647
}
1417
1648
 
1418
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
 
1419
1897
/*
1420
1898
  Check if there is directory for the database name.
1421
1899
 
1424
1902
    db_name   database name
1425
1903
 
1426
1904
  RETURN VALUES
1427
 
    false   There is directory for the specified database name.
1428
 
    true    The directory does not exist.
 
1905
    FALSE   There is directory for the specified database name.
 
1906
    TRUE    The directory does not exist.
1429
1907
*/
1430
1908
 
1431
1909
bool check_db_dir_existence(const char *db_name)
1432
1910
{
1433
1911
  char db_dir_path[FN_REFLEN];
1434
 
  uint32_t db_dir_path_len;
 
1912
  uint db_dir_path_len;
1435
1913
 
1436
1914
  db_dir_path_len= build_table_filename(db_dir_path, sizeof(db_dir_path),
1437
1915
                                        db_name, "", "", 0);