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])]);
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);
66
Return default database collation.
68
@param session Thread context.
69
@param db_name Database name.
71
@return CHARSET_INFO object. The operation always return valid character
72
set, even if the database does not exist.
75
const CHARSET_INFO *get_default_db_collation(const char *db_name)
79
get_database_metadata(db_name, db);
81
/* If for some reason the db.opt file lacks a collation,
82
we just return the default */
84
if (db.has_collation())
86
const string buffer= db.collation();
87
const CHARSET_INFO* cs= get_charset_by_name(buffer.c_str());
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());
95
return default_charset_info;
101
return default_charset_info;
104
/* path is path to database, not schema file */
105
static int write_schema_file(const char *path, const message::Schema &db)
107
char schema_file_tmp[FN_REFLEN];
108
string schema_file(path);
110
snprintf(schema_file_tmp, FN_REFLEN, "%s%c%s.tmpXXXXXX", path, FN_LIBCHAR, MY_DB_OPT_FILE);
112
schema_file.append(1, FN_LIBCHAR);
113
schema_file.append(MY_DB_OPT_FILE);
115
int fd= mkstemp(schema_file_tmp);
121
if (!db.SerializeToFileDescriptor(fd))
124
unlink(schema_file_tmp);
128
if (rename(schema_file_tmp, schema_file.c_str()) == -1)
138
int get_database_metadata(const std::string &dbname, message::Schema &schema_message)
141
char db_opt_path[FN_REFLEN];
145
Pass an empty file name, and the database options file name as extension
146
to avoid table name to file name encoding.
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);
152
int fd= open(db_opt_path, O_RDONLY);
154
if (fd == -1 && errno != ENOENT)
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.
162
if (fd == -1 || not schema_message.ParseFromFileDescriptor(fd))
164
struct stat directory_stat_buffer;
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))
172
else if (not S_ISDIR(directory_stat_buffer.st_mode))
178
schema_message.set_name(dbname);
182
#if 0 //@todo fill this in with something totally acceptable
183
schema_message.set_collation("utf8_general_ci");
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)
216
83
ReplicationServices &replication_services= ReplicationServices::singleton();
219
84
bool error= false;
221
/* do not create 'information_schema' db */
222
if (!my_strcasecmp(system_charset_info, db, INFORMATION_SCHEMA_NAME.c_str()))
224
my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
228
schema_message->set_name(db);
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.
242
98
if (wait_if_global_read_lock(session, 0, 1))
103
assert(schema_message.has_name());
104
assert(schema_message.has_collation());
106
// @todo push this lock down into the engine
248
107
pthread_mutex_lock(&LOCK_create_db);
250
/* check directory */
251
char path[FN_REFLEN+16];
253
path_len= build_table_filename(path, sizeof(path), db, "", false);
254
path[path_len-1]= 0; // remove last '/' from path
256
if (mkdir(path, 0777) == -1)
109
// Check to see if it exists already.
110
if (plugin::StorageEngine::doesSchemaExist(schema_message.name()))
260
if (! is_if_not_exists)
262
my_error(ER_DB_CREATE_EXISTS, MYF(0), path);
112
if (not is_if_not_exists)
114
my_error(ER_DB_CREATE_EXISTS, MYF(0), schema_message.name().c_str());
266
119
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
267
ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
120
ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
121
schema_message.name().c_str());
269
122
session->my_ok();
274
my_error(ER_CANT_CREATE_DB, MYF(0), path, errno);
279
error_erno= write_schema_file(path, *schema_message);
280
if (error_erno && error_erno != EEXIST)
282
if (rmdir(path) >= 0)
291
replication_services.rawStatement(session, session->query, session->query_length);
292
session->my_ok(result);
125
else if (not plugin::StorageEngine::createSchema(schema_message)) // Try to create it
127
my_error(ER_CANT_CREATE_DB, MYF(0), schema_message.name().c_str(), errno);
132
replication_services.createSchema(session, schema_message);
295
136
pthread_mutex_unlock(&LOCK_create_db);
296
137
start_waiting_global_read_lock(session);
302
143
/* db-name is already validated when we come here */
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)
306
147
ReplicationServices &replication_services= ReplicationServices::singleton();
309
char path[FN_REFLEN+16];
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.
324
if ((error=wait_if_global_read_lock(session,0,1)))
327
assert(schema_message);
329
schema_message->set_name(db);
161
if ((wait_if_global_read_lock(session, 0, 1)))
331
164
pthread_mutex_lock(&LOCK_create_db);
166
if (not plugin::StorageEngine::doesSchemaExist(schema_message.name()))
168
my_error(ER_SCHEMA_DOES_NOT_EXIST, MYF(0), schema_message.name().c_str());
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
337
error= write_schema_file(path, *schema_message);
338
if (error && error != EEXIST)
340
/* TODO: find some witty way of getting back an error message */
341
pthread_mutex_unlock(&LOCK_create_db);
345
replication_services.rawStatement(session, session->getQueryString(), session->getQueryLength());
346
session->my_ok(result);
173
bool success= plugin::StorageEngine::alterSchema(schema_message);
177
replication_services.rawStatement(session, session->getQueryString());
182
my_error(ER_ALTER_SCHEMA, MYF(0), schema_message.name().c_str());
348
185
pthread_mutex_unlock(&LOCK_create_db);
349
186
start_waiting_global_read_lock(session);
351
return error ? true : false;
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)
375
212
int error= false;
376
213
char path[FN_REFLEN+16];
378
TableList *dropped_tables= NULL;
380
if (db && (strcmp(db, "information_schema") == 0))
382
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
215
plugin::TableNameList dropped_tables;
216
message::Schema schema_proto;
387
219
Do not drop database if another thread is holding read lock.
403
235
pthread_mutex_lock(&LOCK_create_db);
405
238
length= build_table_filename(path, sizeof(path),
407
strcpy(path+length, MY_DB_OPT_FILE); // Append db option file name
239
schema_name.c_str(), "", false);
409
240
path[length]= '\0'; // Remove file name
411
/* See if the directory exists */
412
CachedDirectory dirp(path);
242
/* See if the schema exists */
243
if (not plugin::StorageEngine::doesSchemaExist(schema_name))
247
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
248
ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS),
418
254
my_error(ER_DB_DROP_EXISTS, MYF(0), path);
422
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
423
ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS),
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);
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)
438
plugin::StorageEngine::dropDatabase(path);
442
273
if (deleted >= 0)
445
uint32_t query_length;
447
assert(session->query);
449
query= session->query;
450
query_length= session->query_length;
275
assert(! session->query.empty());
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);
461
286
char *query, *query_pos, *query_end, *query_data_start;
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;
293
db_len= schema_name.length();
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();
474
300
uint32_t tbl_name_len;
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)
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;
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++ = ',';
655
478
session MUST be set when calling this function!
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)
486
CachedDirectory dirp(org_path);
666
char filePath[FN_REFLEN];
667
491
TableList *tot_list= NULL, **tot_list_next;
669
493
tot_list_next= &tot_list;
671
for (CachedDirectory::Entries::const_iterator iter= dirp.getEntries().begin();
672
iter != dirp.getEntries().end() && !session->killed;
495
plugin::StorageEngine::getTableNames(db, dropped_tables);
497
for (plugin::TableNameList::iterator it= dropped_tables.begin();
498
it != dropped_tables.end();
675
string filename((*iter)->filename);
677
/* skiping . and .. */
678
if (filename[0] == '.' && (!filename[1] ||
679
(filename[1] == '.' && !filename[2])))
682
string extension("");
683
size_t ext_pos= filename.rfind('.');
684
if (ext_pos != string::npos)
686
extension= filename.substr(ext_pos);
688
if (deletable_extentions.find(extension) == deletable_extentions.end())
693
strange checking for magic extensions that are then deleted if
694
not reg_ext (i.e. .frm).
696
and (previously) we'd err out on drop database if files not matching
697
engine ha_known_exts() or deletable_extensions were present.
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*
704
/* just for safety we use files_charset_info */
705
if (!my_strcasecmp(files_charset_info, extension.c_str(), ".dfe"))
707
size_t db_len= db.size();
709
/* Drop the table nicely */
710
filename.erase(ext_pos);
711
TableList *table_list=(TableList*)
712
session->calloc(sizeof(*table_list) +
714
filename.size() + 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(),
725
strlen(TMP_FILE_PREFIX)) == 0);
727
(*tot_list_next)= table_list;
728
tot_list_next= &table_list->next_local;
733
sprintf(filePath, "%s/%s", org_path, filename.c_str());
734
if (internal::my_delete_with_symlink(filePath,MYF(MY_WME)))
501
size_t db_len= db.size();
503
/* Drop the table nicely */
504
TableList *table_list=(TableList*)
505
session->calloc(sizeof(*table_list) +
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,
516
table_list->alias= table_list->table_name; // If lower_case_table_names=2
517
table_list->internal_tmp_table= (strncmp((*it).c_str(),
519
strlen(TMP_FILE_PREFIX)) == 0);
521
(*tot_list_next)= table_list;
522
tot_list_next= &table_list->next_local;
740
525
if (session->killed)
820
602
@retval true Error
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)
825
607
LEX_STRING new_db_file_name;
826
608
const CHARSET_INFO *db_default_cl;
829
assert(new_db_name->length);
831
if (my_strcasecmp(system_charset_info, new_db_name->str,
832
INFORMATION_SCHEMA_NAME.c_str()) == 0)
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);
610
assert(not new_db_name.empty());
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().
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;
868
638
my_error(ER_WRONG_DB_NAME, MYF(0), new_db_file_name.str);
869
639
free(new_db_file_name.str);
872
mysql_change_db_impl(session, NULL);
877
if (check_db_dir_existence(new_db_file_name.str))
644
if (not plugin::StorageEngine::doesSchemaExist(new_db_file_name.str))
881
/* Throw a warning and free new_db_file_name. */
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);
887
free(new_db_file_name.str);
889
/* Change db to NULL. */
891
mysql_change_db_impl(session, NULL);
893
/* The operation succeed. */
899
/* Report an error and free new_db_file_name. */
901
my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
902
free(new_db_file_name.str);
904
/* The operation failed. */
646
/* Report an error and free new_db_file_name. */
648
my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
649
free(new_db_file_name.str);
651
/* The operation failed. */
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);
912
658
mysql_change_db_impl(session, &new_db_file_name);
913
659
free(new_db_file_name.str);
919
Check if there is directory for the database name.
922
check_db_dir_existence()
923
db_name database name
926
false There is directory for the specified database name.
927
true The directory does not exist.
930
bool check_db_dir_existence(const char *db_name)
932
char db_dir_path[FN_REFLEN];
933
uint32_t db_dir_path_len;
935
db_dir_path_len= build_table_filename(db_dir_path, sizeof(db_dir_path),
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;
943
return access(db_dir_path, F_OK);
947
665
@brief Internal implementation: switch current database to a valid one.