~linuxjedi/drizzle/trunk-bug-667053

« back to all changes in this revision

Viewing changes to sql/sql_db.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

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