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"
46
46
#include "drizzled/internal/my_sys.h"
48
#define MY_DB_OPT_FILE "db.opt"
49
48
#define MAX_DROP_TABLE_Q_LEN 1024
51
50
using namespace std;
62
61
TableList **dropped_tables);
63
62
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)
85
bool mysql_create_db(Session *session, const message::Schema &schema_message, bool is_if_not_exists)
216
87
ReplicationServices &replication_services= ReplicationServices::singleton();
219
88
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
91
Do not create database if another thread is holding read lock.
232
92
Wait for global read lock before acquiring LOCK_create_db.
242
102
if (wait_if_global_read_lock(session, 0, 1))
107
assert(schema_message.has_name());
108
assert(schema_message.has_collation());
110
// @todo push this lock down into the engine
248
111
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)
113
// Check to see if it exists already.
114
if (plugin::StorageEngine::doesSchemaExist(schema_message.name()))
260
if (! is_if_not_exists)
262
my_error(ER_DB_CREATE_EXISTS, MYF(0), path);
116
if (not is_if_not_exists)
118
my_error(ER_DB_CREATE_EXISTS, MYF(0), schema_message.name().c_str());
266
123
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
267
ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
124
ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
125
schema_message.name().c_str());
269
126
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);
129
else if (not plugin::StorageEngine::createSchema(schema_message)) // Try to create it
131
my_error(ER_CANT_CREATE_DB, MYF(0), schema_message.name().c_str(), errno);
136
replication_services.rawStatement(session, session->query);
295
140
pthread_mutex_unlock(&LOCK_create_db);
296
141
start_waiting_global_read_lock(session);
302
147
/* db-name is already validated when we come here */
304
bool mysql_alter_db(Session *session, const char *db, message::Schema *schema_message)
149
bool mysql_alter_db(Session *session, const message::Schema &schema_message)
306
151
ReplicationServices &replication_services= ReplicationServices::singleton();
309
char path[FN_REFLEN+16];
313
154
Do not alter database if another thread is holding read lock.
321
162
has the global read lock and refuses the operation with
322
163
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);
165
if ((wait_if_global_read_lock(session, 0, 1)))
331
168
pthread_mutex_lock(&LOCK_create_db);
170
if (not plugin::StorageEngine::doesSchemaExist(schema_message.name()))
172
my_error(ER_SCHEMA_DOES_NOT_EXIST, MYF(0), schema_message.name().c_str());
333
176
/* 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);
177
bool success= plugin::StorageEngine::alterSchema(schema_message);
181
replication_services.rawStatement(session, session->getQueryString());
186
my_error(ER_ALTER_SCHEMA, MYF(0), schema_message.name().c_str());
348
189
pthread_mutex_unlock(&LOCK_create_db);
349
190
start_waiting_global_read_lock(session);
351
return error ? true : false;
820
647
@retval true Error
823
bool mysql_change_db(Session *session, const LEX_STRING *new_db_name, bool force_switch)
650
bool mysql_change_db(Session *session, const std::string &new_db_name, bool force_switch)
825
652
LEX_STRING new_db_file_name;
826
653
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);
655
assert(not new_db_name.empty());
843
658
Now we need to make a copy because check_db_name requires a
844
659
non-constant argument. Actually, it takes database file name.
846
661
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);
664
new_db_file_name.length= new_db_name.length();
665
new_db_file_name.str= (char *)malloc(new_db_name.length() + 1);
851
666
if (new_db_file_name.str == NULL)
852
667
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;
668
memcpy(new_db_file_name.str, new_db_name.c_str(), new_db_name.length());
669
new_db_file_name.str[new_db_name.length()]= 0;
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
734
@brief Internal implementation: switch current database to a valid one.