~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/db.cc

Merged trunk.

Show diffs side-by-side

added added

removed removed

Lines of Context:
38
38
#include <drizzled/replication_services.h>
39
39
#include <drizzled/message/schema.pb.h>
40
40
#include "drizzled/sql_table.h"
41
 
#include "drizzled/plugin/info_schema_table.h"
 
41
#include "drizzled/plugin/storage_engine.h"
42
42
#include "drizzled/global_charset_info.h"
43
43
#include "drizzled/pthread_globals.h"
44
44
#include "drizzled/charset.h"
45
45
 
46
46
#include "drizzled/internal/my_sys.h"
47
47
 
48
 
#define MY_DB_OPT_FILE "db.opt"
49
48
#define MAX_DROP_TABLE_Q_LEN      1024
50
49
 
51
50
using namespace std;
53
52
namespace drizzled
54
53
{
55
54
 
56
 
const string del_exts[]= {".dfe", ".blk", ".arz", ".BAK", ".TMD", ".opt"};
57
 
static set<string> deletable_extentions(del_exts, &del_exts[sizeof(del_exts)/sizeof(del_exts[0])]);
58
 
 
59
 
 
60
 
static long mysql_rm_known_files(Session *session, CachedDirectory &dirp,
 
55
static long mysql_rm_known_files(Session *session,
61
56
                                 const string &db, const char *path,
62
 
                                 TableList **dropped_tables);
 
57
                                 plugin::TableNameList &dropped_tables);
63
58
static void mysql_change_db_impl(Session *session, LEX_STRING *new_db_name);
64
59
 
65
 
/**
66
 
  Return default database collation.
67
 
 
68
 
  @param session     Thread context.
69
 
  @param db_name Database name.
70
 
 
71
 
  @return CHARSET_INFO object. The operation always return valid character
72
 
    set, even if the database does not exist.
73
 
*/
74
 
 
75
 
const CHARSET_INFO *get_default_db_collation(const char *db_name)
76
 
{
77
 
  message::Schema db;
78
 
 
79
 
  get_database_metadata(db_name, db);
80
 
 
81
 
  /* If for some reason the db.opt file lacks a collation,
82
 
     we just return the default */
83
 
 
84
 
  if (db.has_collation())
85
 
  {
86
 
    const string buffer= db.collation();
87
 
    const CHARSET_INFO* cs= get_charset_by_name(buffer.c_str());
88
 
 
89
 
    if (!cs)
90
 
    {
91
 
      errmsg_printf(ERRMSG_LVL_ERROR,
92
 
                    _("Error while loading database options: '%s':"),db_name);
93
 
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UNKNOWN_COLLATION), buffer.c_str());
94
 
 
95
 
      return default_charset_info;
96
 
    }
97
 
 
98
 
    return cs;
99
 
  }
100
 
 
101
 
  return default_charset_info;
102
 
}
103
 
 
104
 
/* path is path to database, not schema file */
105
 
static int write_schema_file(const char *path, const message::Schema &db)
106
 
{
107
 
  char schema_file_tmp[FN_REFLEN];
108
 
  string schema_file(path);
109
 
 
110
 
  snprintf(schema_file_tmp, FN_REFLEN, "%s%c%s.tmpXXXXXX", path, FN_LIBCHAR, MY_DB_OPT_FILE);
111
 
 
112
 
  schema_file.append(1, FN_LIBCHAR);
113
 
  schema_file.append(MY_DB_OPT_FILE);
114
 
 
115
 
  int fd= mkstemp(schema_file_tmp);
116
 
 
117
 
  if (fd==-1)
118
 
    return errno;
119
 
 
120
 
 
121
 
  if (!db.SerializeToFileDescriptor(fd))
122
 
  {
123
 
    close(fd);
124
 
    unlink(schema_file_tmp);
125
 
    return -1;
126
 
  }
127
 
 
128
 
  if (rename(schema_file_tmp, schema_file.c_str()) == -1)
129
 
  {
130
 
    close(fd);
131
 
    return errno;
132
 
  }
133
 
  close(fd);
134
 
 
135
 
  return 0;
136
 
}
137
 
 
138
 
int get_database_metadata(const std::string &dbname, message::Schema &schema_message)
139
 
{
140
 
  int rc= 0;
141
 
  char db_opt_path[FN_REFLEN];
142
 
  size_t length;
143
 
 
144
 
  /*
145
 
    Pass an empty file name, and the database options file name as extension
146
 
    to avoid table name to file name encoding.
147
 
  */
148
 
  length= build_table_filename(db_opt_path, sizeof(db_opt_path),
149
 
                               dbname.c_str(), "", false);
150
 
  strcpy(db_opt_path + length, MY_DB_OPT_FILE);
151
 
 
152
 
  int fd= open(db_opt_path, O_RDONLY);
153
 
 
154
 
  if (fd == -1 && errno != ENOENT)
155
 
    rc= errno;
156
 
 
157
 
  /**
158
 
    @note If parsing fails, either someone has done a "mkdir" or has deleted their opt file.
159
 
    So what do we do? We muddle through the adventure by generating 
160
 
    one with a name in it, and the charset set to the default.
161
 
  */
162
 
  if (fd == -1 || not schema_message.ParseFromFileDescriptor(fd))
163
 
  {
164
 
    struct stat directory_stat_buffer;
165
 
 
166
 
    /* Remove the opt file name and see if we can just open up the directory. */
167
 
    db_opt_path[length]= 0;
168
 
    if (lstat(db_opt_path, &directory_stat_buffer))
169
 
    {
170
 
      rc= errno;
171
 
    }
172
 
    else if (not S_ISDIR(directory_stat_buffer.st_mode))
173
 
    {
174
 
      rc= -1;
175
 
    }
176
 
    else
177
 
    {
178
 
      schema_message.set_name(dbname);
179
 
      rc= 0;
180
 
    }
181
 
 
182
 
#if 0 //@todo fill this in with something totally acceptable
183
 
    schema_message.set_collation("utf8_general_ci"); 
184
 
#endif
185
 
  }
186
 
 
187
 
  if (fd != -1)
188
 
    close(fd);
189
 
 
190
 
  return rc;
191
 
}
192
 
 
193
60
/*
194
61
  Create a database
195
62
 
211
78
 
212
79
*/
213
80
 
214
 
bool mysql_create_db(Session *session, const char *db, message::Schema *schema_message, bool is_if_not_exists)
 
81
bool mysql_create_db(Session *session, const message::Schema &schema_message, const bool is_if_not_exists)
215
82
{
216
83
  ReplicationServices &replication_services= ReplicationServices::singleton();
217
 
  long result= 1;
218
 
  int error_erno;
219
84
  bool error= false;
220
85
 
221
 
  /* do not create 'information_schema' db */
222
 
  if (!my_strcasecmp(system_charset_info, db, INFORMATION_SCHEMA_NAME.c_str()))
223
 
  {
224
 
    my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
225
 
    return(-1);
226
 
  }
227
 
 
228
 
  schema_message->set_name(db);
229
 
 
230
86
  /*
231
87
    Do not create database if another thread is holding read lock.
232
88
    Wait for global read lock before acquiring LOCK_create_db.
241
97
  */
242
98
  if (wait_if_global_read_lock(session, 0, 1))
243
99
  {
244
 
    error= true;
245
 
    goto exit2;
 
100
    return false;
246
101
  }
247
102
 
 
103
  assert(schema_message.has_name());
 
104
  assert(schema_message.has_collation());
 
105
 
 
106
  // @todo push this lock down into the engine
248
107
  pthread_mutex_lock(&LOCK_create_db);
249
108
 
250
 
  /* check directory */
251
 
  char   path[FN_REFLEN+16];
252
 
  uint32_t path_len;
253
 
  path_len= build_table_filename(path, sizeof(path), db, "", false);
254
 
  path[path_len-1]= 0;                    // remove last '/' from path
255
 
 
256
 
  if (mkdir(path, 0777) == -1)
 
109
  // Check to see if it exists already.
 
110
  if (plugin::StorageEngine::doesSchemaExist(schema_message.name()))
257
111
  {
258
 
    if (errno == EEXIST)
259
 
    {
260
 
      if (! is_if_not_exists)
261
 
      {
262
 
        my_error(ER_DB_CREATE_EXISTS, MYF(0), path);
263
 
        error= true;
264
 
        goto exit;
265
 
      }
 
112
    if (not is_if_not_exists)
 
113
    {
 
114
      my_error(ER_DB_CREATE_EXISTS, MYF(0), schema_message.name().c_str());
 
115
      error= true;
 
116
    }
 
117
    else
 
118
    {
266
119
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
267
 
                          ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
268
 
                          path);
 
120
                          ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
 
121
                          schema_message.name().c_str());
269
122
      session->my_ok();
270
 
      error= false;
271
 
      goto exit;
272
 
    }
273
 
 
274
 
    my_error(ER_CANT_CREATE_DB, MYF(0), path, errno);
275
 
    error= true;
276
 
    goto exit;
277
 
  }
278
 
 
279
 
  error_erno= write_schema_file(path, *schema_message);
280
 
  if (error_erno && error_erno != EEXIST)
281
 
  {
282
 
    if (rmdir(path) >= 0)
283
 
    {
284
 
      error= true;
285
 
      goto exit;
286
 
    }
287
 
  }
288
 
  else if (error_erno)
289
 
    error= true;
290
 
 
291
 
  replication_services.rawStatement(session, session->query, session->query_length);
292
 
  session->my_ok(result);
293
 
 
294
 
exit:
 
123
    }
 
124
  }
 
125
  else if (not plugin::StorageEngine::createSchema(schema_message)) // Try to create it 
 
126
  {
 
127
    my_error(ER_CANT_CREATE_DB, MYF(0), schema_message.name().c_str(), errno);
 
128
    error= true;
 
129
  }
 
130
  else // Created !
 
131
  {
 
132
    replication_services.createSchema(session, schema_message);
 
133
    session->my_ok(1);
 
134
  }
 
135
 
295
136
  pthread_mutex_unlock(&LOCK_create_db);
296
137
  start_waiting_global_read_lock(session);
297
 
exit2:
 
138
 
298
139
  return error;
299
140
}
300
141
 
301
142
 
302
143
/* db-name is already validated when we come here */
303
144
 
304
 
bool mysql_alter_db(Session *session, const char *db, message::Schema *schema_message)
 
145
bool mysql_alter_db(Session *session, const message::Schema &schema_message)
305
146
{
306
147
  ReplicationServices &replication_services= ReplicationServices::singleton();
307
 
  long result=1;
308
 
  int error= 0;
309
 
  char   path[FN_REFLEN+16];
310
 
  uint32_t path_len;
311
148
 
312
149
  /*
313
150
    Do not alter database if another thread is holding read lock.
321
158
    has the global read lock and refuses the operation with
322
159
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
323
160
  */
324
 
  if ((error=wait_if_global_read_lock(session,0,1)))
325
 
    goto exit;
326
 
 
327
 
  assert(schema_message);
328
 
 
329
 
  schema_message->set_name(db);
 
161
  if ((wait_if_global_read_lock(session, 0, 1)))
 
162
    return false;
330
163
 
331
164
  pthread_mutex_lock(&LOCK_create_db);
332
165
 
 
166
  if (not plugin::StorageEngine::doesSchemaExist(schema_message.name()))
 
167
  {
 
168
    my_error(ER_SCHEMA_DOES_NOT_EXIST, MYF(0), schema_message.name().c_str());
 
169
    return false;
 
170
  }
 
171
 
333
172
  /* Change options if current database is being altered. */
334
 
  path_len= build_table_filename(path, sizeof(path), db, "", false);
335
 
  path[path_len-1]= 0;                    // Remove last '/' from path
336
 
 
337
 
  error= write_schema_file(path, *schema_message);
338
 
  if (error && error != EEXIST)
339
 
  {
340
 
    /* TODO: find some witty way of getting back an error message */
341
 
    pthread_mutex_unlock(&LOCK_create_db);
342
 
    goto exit;
343
 
  }
344
 
 
345
 
  replication_services.rawStatement(session, session->getQueryString(), session->getQueryLength());
346
 
  session->my_ok(result);
 
173
  bool success= plugin::StorageEngine::alterSchema(schema_message);
 
174
 
 
175
  if (success)
 
176
  {
 
177
    replication_services.rawStatement(session, session->getQueryString());
 
178
    session->my_ok(1);
 
179
  }
 
180
  else
 
181
  {
 
182
    my_error(ER_ALTER_SCHEMA, MYF(0), schema_message.name().c_str());
 
183
  }
347
184
 
348
185
  pthread_mutex_unlock(&LOCK_create_db);
349
186
  start_waiting_global_read_lock(session);
350
 
exit:
351
 
  return error ? true : false;
 
187
 
 
188
  return success;
352
189
}
353
190
 
354
191
 
369
206
    ERROR Error
370
207
*/
371
208
 
372
 
bool mysql_rm_db(Session *session, char *db, bool if_exists)
 
209
bool mysql_rm_db(Session *session, const std::string &schema_name, const bool if_exists)
373
210
{
374
211
  long deleted=0;
375
212
  int error= false;
376
213
  char  path[FN_REFLEN+16];
377
214
  uint32_t length;
378
 
  TableList *dropped_tables= NULL;
379
 
 
380
 
  if (db && (strcmp(db, "information_schema") == 0))
381
 
  {
382
 
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
383
 
    return true;
384
 
  }
 
215
  plugin::TableNameList dropped_tables;
 
216
  message::Schema schema_proto;
385
217
 
386
218
  /*
387
219
    Do not drop database if another thread is holding read lock.
402
234
 
403
235
  pthread_mutex_lock(&LOCK_create_db);
404
236
 
 
237
 
405
238
  length= build_table_filename(path, sizeof(path),
406
 
                               db, "", false);
407
 
  strcpy(path+length, MY_DB_OPT_FILE);         // Append db option file name
408
 
  unlink(path);
 
239
                               schema_name.c_str(), "", false);
409
240
  path[length]= '\0';                           // Remove file name
410
241
 
411
 
  /* See if the directory exists */
412
 
  CachedDirectory dirp(path);
413
 
  if (dirp.fail())
 
242
  /* See if the schema exists */
 
243
  if (not plugin::StorageEngine::doesSchemaExist(schema_name))
414
244
  {
415
 
    if (!if_exists)
 
245
    if (if_exists)
 
246
    {
 
247
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
248
                          ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS),
 
249
                          path);
 
250
    }
 
251
    else
416
252
    {
417
253
      error= -1;
418
254
      my_error(ER_DB_DROP_EXISTS, MYF(0), path);
419
255
      goto exit;
420
256
    }
421
 
    else
422
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
423
 
                          ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS),
424
 
                          path);
425
257
  }
426
258
  else
427
259
  {
428
260
    pthread_mutex_lock(&LOCK_open); /* After deleting database, remove all cache entries related to schema */
429
 
    remove_db_from_cache(db);
 
261
    remove_db_from_cache(schema_name);
430
262
    pthread_mutex_unlock(&LOCK_open);
431
263
 
432
264
 
433
265
    error= -1;
434
 
    deleted= mysql_rm_known_files(session, dirp, db,
435
 
                                  path, &dropped_tables);
 
266
    deleted= mysql_rm_known_files(session, schema_name,
 
267
                                  path, dropped_tables);
436
268
    if (deleted >= 0)
437
269
    {
438
 
      plugin::StorageEngine::dropDatabase(path);
439
 
      error = 0;
 
270
      error= 0;
440
271
    }
441
272
  }
442
273
  if (deleted >= 0)
443
274
  {
444
 
    const char *query;
445
 
    uint32_t query_length;
446
 
 
447
 
    assert(session->query);
448
 
 
449
 
    query= session->query;
450
 
    query_length= session->query_length;
 
275
    assert(! session->query.empty());
451
276
 
452
277
    ReplicationServices &replication_services= ReplicationServices::singleton();
453
 
    replication_services.rawStatement(session, session->getQueryString(), session->getQueryLength());
 
278
    replication_services.dropSchema(session, schema_name);
454
279
    session->clear_error();
455
280
    session->server_status|= SERVER_STATUS_DB_DROPPED;
456
281
    session->my_ok((uint32_t) deleted);
459
284
  else
460
285
  {
461
286
    char *query, *query_pos, *query_end, *query_data_start;
462
 
    TableList *tbl;
463
287
    uint32_t db_len;
464
288
 
465
289
    if (!(query= (char*) session->alloc(MAX_DROP_TABLE_Q_LEN)))
466
290
      goto exit; /* not much else we can do */
467
291
    query_pos= query_data_start= strcpy(query,"drop table ")+11;
468
292
    query_end= query + MAX_DROP_TABLE_Q_LEN;
469
 
    db_len= strlen(db);
 
293
    db_len= schema_name.length();
470
294
 
471
295
    ReplicationServices &replication_services= ReplicationServices::singleton();
472
 
    for (tbl= dropped_tables; tbl; tbl= tbl->next_local)
 
296
    for (plugin::TableNameList::iterator it= dropped_tables.begin();
 
297
         it != dropped_tables.end();
 
298
         it++)
473
299
    {
474
300
      uint32_t tbl_name_len;
475
301
 
476
302
      /* 3 for the quotes and the comma*/
477
 
      tbl_name_len= strlen(tbl->table_name) + 3;
 
303
      tbl_name_len= (*it).length() + 3;
478
304
      if (query_pos + tbl_name_len + 1 >= query_end)
479
305
      {
480
306
        /* These DDL methods and logging protected with LOCK_create_db */
481
 
        replication_services.rawStatement(session, query, (size_t) (query_pos -1 - query));
 
307
        replication_services.rawStatement(session, query);
482
308
        query_pos= query_data_start;
483
309
      }
484
310
 
485
311
      *query_pos++ = '`';
486
 
      query_pos= strcpy(query_pos,tbl->table_name) + (tbl_name_len-3);
 
312
      query_pos= strcpy(query_pos, (*it).c_str()) + (tbl_name_len-3);
487
313
      *query_pos++ = '`';
488
314
      *query_pos++ = ',';
489
315
    }
491
317
    if (query_pos != query_data_start)
492
318
    {
493
319
      /* These DDL methods and logging protected with LOCK_create_db */
494
 
      replication_services.rawStatement(session, query, (size_t) (query_pos -1 - query));
 
320
      replication_services.rawStatement(session, query);
495
321
    }
496
322
  }
497
323
 
502
328
    SELECT DATABASE() in the future). For this we free() session->db and set
503
329
    it to 0.
504
330
  */
505
 
  if (! session->db.empty() && session->db.compare(db) == 0)
 
331
  if (not session->db.empty() && session->db.compare(schema_name) == 0)
506
332
    mysql_change_db_impl(session, NULL);
507
333
  pthread_mutex_unlock(&LOCK_create_db);
508
334
  start_waiting_global_read_lock(session);
 
335
 
509
336
  return error;
510
337
}
511
338
 
583
410
      }
584
411
    }
585
412
 
586
 
    TableIdentifier identifier(db, table->table_name, table->internal_tmp_table ? INTERNAL_TMP_TABLE : NO_TMP_TABLE);
 
413
    TableIdentifier identifier(db, table->table_name);
587
414
 
588
 
    if ((table_type == NULL
589
 
          && (plugin::StorageEngine::getTableDefinition(*session,
590
 
                                                        identifier) != EEXIST)))
 
415
    if (table_type == NULL && not plugin::StorageEngine::doesTableExist(*session, identifier))
591
416
    {
592
417
      // Table was not found on disk and table can't be created from engine
593
418
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
596
421
    }
597
422
    else
598
423
    {
599
 
      error= plugin::StorageEngine::dropTable(*session,
600
 
                                              identifier,
601
 
                                              false);
 
424
      error= plugin::StorageEngine::dropTable(*session, identifier);
602
425
 
603
426
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE))
604
427
      {
631
454
  error= 0;
632
455
  if (wrong_tables.length())
633
456
  {
634
 
    if (!foreign_key_error)
 
457
    if (not foreign_key_error)
635
458
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
636
459
                      wrong_tables.c_ptr());
637
460
    else
655
478
  session MUST be set when calling this function!
656
479
*/
657
480
 
658
 
static long mysql_rm_known_files(Session *session, CachedDirectory &dirp,
 
481
static long mysql_rm_known_files(Session *session,
659
482
                                 const string &db,
660
483
                                 const char *org_path,
661
 
                                 TableList **dropped_tables)
 
484
                                 plugin::TableNameList &dropped_tables)
662
485
{
663
 
 
 
486
  CachedDirectory dirp(org_path);
 
487
  if (dirp.fail())
 
488
    return 0;
664
489
 
665
490
  long deleted= 0;
666
 
  char filePath[FN_REFLEN];
667
491
  TableList *tot_list= NULL, **tot_list_next;
668
492
 
669
493
  tot_list_next= &tot_list;
670
494
 
671
 
  for (CachedDirectory::Entries::const_iterator iter= dirp.getEntries().begin();
672
 
       iter != dirp.getEntries().end() && !session->killed;
673
 
       ++iter)
 
495
  plugin::StorageEngine::getTableNames(db, dropped_tables);
 
496
 
 
497
  for (plugin::TableNameList::iterator it= dropped_tables.begin();
 
498
       it != dropped_tables.end();
 
499
       it++)
674
500
  {
675
 
    string filename((*iter)->filename);
676
 
 
677
 
    /* skiping . and .. */
678
 
    if (filename[0] == '.' && (!filename[1] ||
679
 
       (filename[1] == '.' &&  !filename[2])))
680
 
      continue;
681
 
 
682
 
    string extension("");
683
 
    size_t ext_pos= filename.rfind('.');
684
 
    if (ext_pos != string::npos)
685
 
    {
686
 
      extension= filename.substr(ext_pos);
687
 
    }
688
 
    if (deletable_extentions.find(extension) == deletable_extentions.end())
689
 
    {
690
 
      /*
691
 
        ass ass ass.
692
 
 
693
 
        strange checking for magic extensions that are then deleted if
694
 
        not reg_ext (i.e. .frm).
695
 
 
696
 
        and (previously) we'd err out on drop database if files not matching
697
 
        engine ha_known_exts() or deletable_extensions were present.
698
 
 
699
 
        presumably this was to avoid deleting other user data... except if that
700
 
        data happened to be in files ending in .BAK, .opt or .TMD. *fun*
701
 
       */
702
 
      continue;
703
 
    }
704
 
    /* just for safety we use files_charset_info */
705
 
    if (!my_strcasecmp(files_charset_info, extension.c_str(), ".dfe"))
706
 
    {
707
 
      size_t db_len= db.size();
708
 
 
709
 
      /* Drop the table nicely */
710
 
      filename.erase(ext_pos);
711
 
      TableList *table_list=(TableList*)
712
 
                             session->calloc(sizeof(*table_list) +
713
 
                                             db_len + 1 +
714
 
                                             filename.size() + 1);
715
 
 
716
 
      if (!table_list)
717
 
        return -1;
718
 
      table_list->db= (char*) (table_list+1);
719
 
      table_list->table_name= strcpy(table_list->db, db.c_str()) + db_len + 1;
720
 
      filename_to_tablename(filename.c_str(), table_list->table_name,
721
 
                            filename.size() + 1);
722
 
      table_list->alias= table_list->table_name;  // If lower_case_table_names=2
723
 
      table_list->internal_tmp_table= (strncmp(filename.c_str(),
724
 
                                               TMP_FILE_PREFIX,
725
 
                                               strlen(TMP_FILE_PREFIX)) == 0);
726
 
      /* Link into list */
727
 
      (*tot_list_next)= table_list;
728
 
      tot_list_next= &table_list->next_local;
729
 
      deleted++;
730
 
    }
731
 
    else
732
 
    {
733
 
      sprintf(filePath, "%s/%s", org_path, filename.c_str());
734
 
      if (internal::my_delete_with_symlink(filePath,MYF(MY_WME)))
735
 
      {
736
 
        return -1;
737
 
      }
738
 
    }
 
501
    size_t db_len= db.size();
 
502
 
 
503
    /* Drop the table nicely */
 
504
    TableList *table_list=(TableList*)
 
505
      session->calloc(sizeof(*table_list) +
 
506
                      db_len + 1 +
 
507
                      (*it).length() + 1);
 
508
 
 
509
    if (not table_list)
 
510
      return -1;
 
511
 
 
512
    table_list->db= (char*) (table_list+1);
 
513
    table_list->table_name= strcpy(table_list->db, db.c_str()) + db_len + 1;
 
514
    filename_to_tablename((*it).c_str(), table_list->table_name,
 
515
                          (*it).size() + 1);
 
516
    table_list->alias= table_list->table_name;  // If lower_case_table_names=2
 
517
    table_list->internal_tmp_table= (strncmp((*it).c_str(),
 
518
                                             TMP_FILE_PREFIX,
 
519
                                             strlen(TMP_FILE_PREFIX)) == 0);
 
520
    /* Link into list */
 
521
    (*tot_list_next)= table_list;
 
522
    tot_list_next= &table_list->next_local;
 
523
    deleted++;
739
524
  }
740
525
  if (session->killed)
741
526
    return -1;
746
531
      return -1;
747
532
  }
748
533
 
749
 
  if (dropped_tables)
750
 
    *dropped_tables= tot_list;
751
 
 
752
 
  if (rmdir(org_path))
 
534
  if (not plugin::StorageEngine::dropSchema(db))
753
535
  {
754
 
    my_error(ER_DB_DROP_RMDIR, MYF(0), org_path, errno);
 
536
    my_error(ER_DROP_SCHEMA, MYF(0), db.c_str());
755
537
    return -1;
756
538
  }
757
539
 
820
602
    @retval true  Error
821
603
*/
822
604
 
823
 
bool mysql_change_db(Session *session, const LEX_STRING *new_db_name, bool force_switch)
 
605
bool mysql_change_db(Session *session, const std::string &new_db_name)
824
606
{
825
607
  LEX_STRING new_db_file_name;
826
608
  const CHARSET_INFO *db_default_cl;
827
609
 
828
 
  assert(new_db_name);
829
 
  assert(new_db_name->length);
830
 
 
831
 
  if (my_strcasecmp(system_charset_info, new_db_name->str,
832
 
                    INFORMATION_SCHEMA_NAME.c_str()) == 0)
833
 
  {
834
 
    /* Switch the current database to INFORMATION_SCHEMA. */
835
 
    /* const_cast<> is safe here: mysql_change_db_impl does a copy */
836
 
    LEX_STRING is_name= { const_cast<char *>(INFORMATION_SCHEMA_NAME.c_str()),
837
 
                          INFORMATION_SCHEMA_NAME.length() };
838
 
    mysql_change_db_impl(session, &is_name);
839
 
 
840
 
    return false;
841
 
  }
 
610
  assert(not new_db_name.empty());
 
611
 
842
612
  /*
843
613
    Now we need to make a copy because check_db_name requires a
844
614
    non-constant argument. Actually, it takes database file name.
846
616
    TODO: fix check_db_name().
847
617
  */
848
618
 
849
 
  new_db_file_name.length= new_db_name->length;
850
 
  new_db_file_name.str= (char *)malloc(new_db_name->length + 1);
 
619
  new_db_file_name.length= new_db_name.length();
 
620
  new_db_file_name.str= (char *)malloc(new_db_name.length() + 1);
851
621
  if (new_db_file_name.str == NULL)
852
622
    return true;                             /* the error is set */
853
 
  memcpy(new_db_file_name.str, new_db_name->str, new_db_name->length);
854
 
  new_db_file_name.str[new_db_name->length]= 0;
 
623
  memcpy(new_db_file_name.str, new_db_name.c_str(), new_db_name.length());
 
624
  new_db_file_name.str[new_db_name.length()]= 0;
855
625
 
856
626
 
857
627
  /*
868
638
    my_error(ER_WRONG_DB_NAME, MYF(0), new_db_file_name.str);
869
639
    free(new_db_file_name.str);
870
640
 
871
 
    if (force_switch)
872
 
      mysql_change_db_impl(session, NULL);
873
 
 
874
641
    return true;
875
642
  }
876
643
 
877
 
  if (check_db_dir_existence(new_db_file_name.str))
 
644
  if (not plugin::StorageEngine::doesSchemaExist(new_db_file_name.str))
878
645
  {
879
 
    if (force_switch)
880
 
    {
881
 
      /* Throw a warning and free new_db_file_name. */
882
 
 
883
 
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
884
 
                          ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
885
 
                          new_db_file_name.str);
886
 
 
887
 
      free(new_db_file_name.str);
888
 
 
889
 
      /* Change db to NULL. */
890
 
 
891
 
      mysql_change_db_impl(session, NULL);
892
 
 
893
 
      /* The operation succeed. */
894
 
 
895
 
      return false;
896
 
    }
897
 
    else
898
 
    {
899
 
      /* Report an error and free new_db_file_name. */
900
 
 
901
 
      my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
902
 
      free(new_db_file_name.str);
903
 
 
904
 
      /* The operation failed. */
905
 
 
906
 
      return true;
907
 
    }
 
646
    /* Report an error and free new_db_file_name. */
 
647
 
 
648
    my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
 
649
    free(new_db_file_name.str);
 
650
 
 
651
    /* The operation failed. */
 
652
 
 
653
    return true;
908
654
  }
909
655
 
910
 
  db_default_cl= get_default_db_collation(new_db_file_name.str);
 
656
  db_default_cl= plugin::StorageEngine::getSchemaCollation(new_db_file_name.str);
911
657
 
912
658
  mysql_change_db_impl(session, &new_db_file_name);
913
659
  free(new_db_file_name.str);
915
661
  return false;
916
662
}
917
663
 
918
 
/*
919
 
  Check if there is directory for the database name.
920
 
 
921
 
  SYNOPSIS
922
 
    check_db_dir_existence()
923
 
    db_name   database name
924
 
 
925
 
  RETURN VALUES
926
 
    false   There is directory for the specified database name.
927
 
    true    The directory does not exist.
928
 
*/
929
 
 
930
 
bool check_db_dir_existence(const char *db_name)
931
 
{
932
 
  char db_dir_path[FN_REFLEN];
933
 
  uint32_t db_dir_path_len;
934
 
 
935
 
  db_dir_path_len= build_table_filename(db_dir_path, sizeof(db_dir_path),
936
 
                                        db_name, "", false);
937
 
 
938
 
  if (db_dir_path_len && db_dir_path[db_dir_path_len - 1] == FN_LIBCHAR)
939
 
    db_dir_path[db_dir_path_len - 1]= 0;
940
 
 
941
 
  /* Check access. */
942
 
 
943
 
  return access(db_dir_path, F_OK);
944
 
}
945
 
 
946
664
/**
947
665
  @brief Internal implementation: switch current database to a valid one.
948
666