12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
17
/* create and drop of databases */
22
#include <sys/types.h>
18
#include <drizzled/global.h>
23
#include <drizzled/serialize/serialize.h>
25
#include <drizzled/server_includes.h>
26
#include <mysys/mysys_err.h>
27
#include <mysys/my_dir.h>
28
29
#include <drizzled/error.h>
29
30
#include <drizzled/gettext.h>
30
#include <drizzled/my_hash.h>
31
#include <drizzled/internal/m_string.h>
31
#include <mysys/hash.h>
32
32
#include <drizzled/session.h>
33
#include <drizzled/schema.h>
33
#include <drizzled/db.h>
34
34
#include <drizzled/sql_base.h>
35
35
#include <drizzled/lock.h>
36
#include <drizzled/errmsg_print.h>
37
#include <drizzled/transaction_services.h>
38
#include <drizzled/message/schema.pb.h>
39
#include <drizzled/sql_table.h>
40
#include <drizzled/plugin/storage_engine.h>
41
#include <drizzled/plugin/authorization.h>
42
#include <drizzled/global_charset_info.h>
43
#include <drizzled/pthread_globals.h>
44
#include <drizzled/charset.h>
45
#include <drizzled/internal/my_sys.h>
47
#include <boost/thread/mutex.hpp>
49
37
#define MAX_DROP_TABLE_Q_LEN 1024
59
static void change_db_impl(Session &session);
60
static void change_db_impl(Session &session, identifier::Schema &schema_identifier);
39
const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NULL};
40
static TYPELIB deletable_extentions=
41
{array_elements(del_exts)-1,"del_exts", del_exts, NULL};
43
static long mysql_rm_known_files(Session *session, MY_DIR *dirp,
44
const char *db, const char *path,
46
TableList **dropped_tables);
48
static bool rm_dir_w_symlink(const char *org_path, bool send_error);
49
static void mysql_change_db_impl(Session *session,
50
LEX_STRING *new_db_name,
51
const CHARSET_INFO * const new_db_charset);
54
/* Database lock hash */
56
pthread_mutex_t LOCK_lock_db;
57
int creating_database= 0; // how many database locks are made
60
/* Structure for database lock */
61
typedef struct my_dblock_st
63
char *name; /* Database name */
64
uint32_t name_length; /* Database length name */
72
extern "C" unsigned char* lock_db_get_key(my_dblock_t *, size_t *, bool not_used);
74
unsigned char* lock_db_get_key(my_dblock_t *ptr, size_t *length,
75
bool not_used __attribute__((unused)))
77
*length= ptr->name_length;
78
return (unsigned char*) ptr->name;
83
Free lock_db hash element.
86
extern "C" void lock_db_free_element(void *ptr);
88
void lock_db_free_element(void *ptr)
95
Delete a database lock entry from hash.
98
void lock_db_delete(const char *name, uint32_t length)
101
safe_mutex_assert_owner(&LOCK_lock_db);
102
if ((opt= (my_dblock_t *)hash_search(&lock_db_cache,
103
(const unsigned char*) name, length)))
104
hash_delete(&lock_db_cache, (unsigned char*) opt);
108
/* Database options hash */
109
static HASH dboptions;
110
static bool dboptions_init= 0;
111
static pthread_rwlock_t LOCK_dboptions;
113
/* Structure for database options */
114
typedef struct my_dbopt_st
116
char *name; /* Database name */
117
uint32_t name_length; /* Database length name */
118
const CHARSET_INFO *charset; /* Database default character set */
123
Function we use in the creation of our hash to get key.
126
extern "C" unsigned char* dboptions_get_key(my_dbopt_t *opt, size_t *length,
129
unsigned char* dboptions_get_key(my_dbopt_t *opt, size_t *length,
130
bool not_used __attribute__((unused)))
132
*length= opt->name_length;
133
return (unsigned char*) opt->name;
138
Helper function to write a query to binlog used by mysql_rm_db()
141
static inline void write_to_binlog(Session *session, char *query, uint32_t q_len,
142
char *db, uint32_t db_len)
144
Query_log_event qinfo(session, query, q_len, 0, 0);
147
qinfo.db_len= db_len;
148
drizzle_bin_log.write(&qinfo);
153
Function to free dboptions hash element
156
extern "C" void free_dbopt(void *dbopt);
158
void free_dbopt(void *dbopt)
160
free((unsigned char*) dbopt);
165
Initialize database option hash and locked database hash.
171
Must be called before any other database function is called.
178
bool my_database_names_init(void)
181
(void) pthread_rwlock_init(&LOCK_dboptions, NULL);
185
error= hash_init(&dboptions, lower_case_table_names ?
186
&my_charset_bin : system_charset_info,
187
32, 0, 0, (hash_get_key) dboptions_get_key,
189
hash_init(&lock_db_cache, lower_case_table_names ?
190
&my_charset_bin : system_charset_info,
191
32, 0, 0, (hash_get_key) lock_db_get_key,
192
lock_db_free_element,0);
201
Free database option hash and locked databases hash.
204
void my_database_names_free(void)
209
hash_free(&dboptions);
210
(void) pthread_rwlock_destroy(&LOCK_dboptions);
211
hash_free(&lock_db_cache);
217
Cleanup cached options
220
void my_dbopt_cleanup(void)
222
pthread_rwlock_wrlock(&LOCK_dboptions);
223
hash_free(&dboptions);
224
hash_init(&dboptions, lower_case_table_names ?
225
&my_charset_bin : system_charset_info,
226
32, 0, 0, (hash_get_key) dboptions_get_key,
228
pthread_rwlock_unlock(&LOCK_dboptions);
233
Find database options in the hash.
236
Search a database options in the hash, usings its path.
237
Fills "create" on success.
244
static bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
250
length= (uint) strlen(dbname);
252
pthread_rwlock_rdlock(&LOCK_dboptions);
253
if ((opt= (my_dbopt_t*) hash_search(&dboptions, (unsigned char*) dbname, length)))
255
create->default_table_charset= opt->charset;
258
pthread_rwlock_unlock(&LOCK_dboptions);
264
Writes database options into the hash.
267
Inserts database options into the hash, or updates
268
options if they are already in the hash.
275
static bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
281
length= (uint) strlen(dbname);
283
pthread_rwlock_wrlock(&LOCK_dboptions);
284
if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (unsigned char*) dbname, length)))
286
/* Options are not in the hash, insert them */
288
if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
289
&opt, (uint) sizeof(*opt), &tmp_name, (uint) length+1,
297
strcpy(opt->name, dbname);
298
opt->name_length= length;
300
if ((error= my_hash_insert(&dboptions, (unsigned char*) opt)))
307
/* Update / write options in hash */
308
opt->charset= create->default_table_charset;
311
pthread_rwlock_unlock(&LOCK_dboptions);
317
Deletes database options from the hash.
320
void del_dbopt(const char *path)
323
pthread_rwlock_wrlock(&LOCK_dboptions);
324
if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const unsigned char*) path,
326
hash_delete(&dboptions, (unsigned char*) opt);
327
pthread_rwlock_unlock(&LOCK_dboptions);
332
Create database options file:
335
Currently database default charset is only stored there.
339
1 Could not create file or write to it. Error sent through my_error()
342
static bool write_db_opt(Session *session, const char *path, const char *name, HA_CREATE_INFO *create)
349
if (!create->default_table_charset)
350
create->default_table_charset= session->variables.collation_server;
352
if (put_dbopt(path, create))
356
db.set_characterset(create->default_table_charset->csname);
357
db.set_collation(create->default_table_charset->name);
359
fstream output(path, ios::out | ios::trunc | ios::binary);
360
if (!db.SerializeToOstream(&output))
368
Load database options file
371
path Path for option file
372
create Where to store the read options
378
1 No database file or could not open it
382
bool load_db_opt(Session *session, const char *path, HA_CREATE_INFO *create)
388
memset(create, 0, sizeof(*create));
389
create->default_table_charset= session->variables.collation_server;
391
/* Check if options for this database are already in the hash */
392
if (!get_dbopt(path, create))
395
fstream input(path, ios::in | ios::binary);
398
else if (!db.ParseFromIstream(&input))
401
buffer= db.characterset();
402
if (!(create->default_table_charset= get_charset_by_csname(buffer.c_str(), MY_CS_PRIMARY, MYF(0))))
404
sql_print_error(_("Error while loading database options: '%s':"),path);
405
sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
406
create->default_table_charset= default_charset_info;
409
buffer= db.collation();
410
if (!(create->default_table_charset= get_charset_by_name(buffer.c_str(), MYF(0))))
412
sql_print_error(_("Error while loading database options: '%s':"),path);
413
sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
414
create->default_table_charset= default_charset_info;
418
Put the loaded value into the hash.
419
Note that another thread could've added the same
420
entry to the hash after we called get_dbopt(),
421
but it's not an error, as put_dbopt() takes this
422
possibility into account.
424
error= put_dbopt(path, create);
432
Retrieve database options by name. Load database options file or fetch from
436
load_db_opt_by_name()
437
db_name Database name
438
db_create_info Where to store the database options
441
load_db_opt_by_name() is a shortcut for load_db_opt().
444
Although load_db_opt_by_name() (and load_db_opt()) returns status of
445
the operation, it is useless usually and should be ignored. The problem
446
is that there are 1) system databases ("mysql") and 2) virtual
447
databases ("information_schema"), which do not contain options file.
448
So, load_db_opt[_by_name]() returns false for these databases, but this
451
load_db_opt[_by_name]() clears db_create_info structure in any case, so
452
even on failure it contains valid data. So, common use case is just
453
call load_db_opt[_by_name]() without checking return value and use
454
db_create_info right after that.
456
RETURN VALUES (read NOTE!)
458
true Failed to retrieve options
461
bool load_db_opt_by_name(Session *session, const char *db_name,
462
HA_CREATE_INFO *db_create_info)
464
char db_opt_path[FN_REFLEN];
467
Pass an empty file name, and the database options file name as extension
468
to avoid table name to file name encoding.
470
(void) build_table_filename(db_opt_path, sizeof(db_opt_path),
471
db_name, "", MY_DB_OPT_FILE, 0);
473
return load_db_opt(session, db_opt_path, db_create_info);
478
Return default database collation.
480
@param session Thread context.
481
@param db_name Database name.
483
@return CHARSET_INFO object. The operation always return valid character
484
set, even if the database does not exist.
487
const CHARSET_INFO *get_default_db_collation(Session *session, const char *db_name)
489
HA_CREATE_INFO db_info;
491
if (session->db != NULL && strcmp(db_name, session->db) == 0)
492
return session->db_charset;
494
load_db_opt_by_name(session, db_name, &db_info);
497
NOTE: even if load_db_opt_by_name() fails,
498
db_info.default_table_charset contains valid character set
499
(collation_server). We should not fail if load_db_opt_by_name() fails,
500
because it is valid case. If a database has been created just by
501
"mkdir", it does not contain db.opt file, but it is valid database.
504
return db_info.default_table_charset;
67
513
session Thread handler
68
514
db Name of database to create
69
515
Function assumes that this is already validated.
70
516
create_info Database create options (like character set)
517
silent Used by replication when internally creating a database.
518
In this case the entry should not be logged.
73
521
1. Report back to client that command succeeded (my_ok)
74
522
2. Report errors to client
75
523
3. Log event to binary log
524
(The 'silent' flags turns off 1 and 3.)
83
bool create(Session &session, const message::Schema &schema_message, const bool is_if_not_exists)
532
int mysql_create_db(Session *session, char *db, HA_CREATE_INFO *create_info, bool silent)
85
TransactionServices &transaction_services= TransactionServices::singleton();
534
char path[FN_REFLEN+16];
535
char tmp_query[FN_REFLEN+16];
538
struct stat stat_info;
539
uint32_t create_options= create_info ? create_info->options : 0;
542
/* do not create 'information_schema' db */
543
if (!my_strcasecmp(system_charset_info, db, INFORMATION_SCHEMA_NAME.c_str()))
545
my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
89
550
Do not create database if another thread is holding read lock.
90
Wait for global read lock before acquiring session->catalog()->schemaLock().
551
Wait for global read lock before acquiring LOCK_drizzle_create_db.
91
552
After wait_if_global_read_lock() we have protection against another
92
global read lock. If we would acquire session->catalog()->schemaLock() first,
553
global read lock. If we would acquire LOCK_drizzle_create_db first,
93
554
another thread could step in and get the global read lock before we
94
555
reach wait_if_global_read_lock(). If this thread tries the same as we
95
(admin a db), it would then go and wait on session->catalog()->schemaLock()...
556
(admin a db), it would then go and wait on LOCK_drizzle_create_db...
96
557
Furthermore wait_if_global_read_lock() checks if the current thread
97
558
has the global read lock and refuses the operation with
98
559
ER_CANT_UPDATE_WITH_READLOCK if applicable.
100
if (session.wait_if_global_read_lock(false, true))
105
assert(schema_message.has_name());
106
assert(schema_message.has_collation());
108
// @todo push this lock down into the engine
110
boost::mutex::scoped_lock scopedLock(session.catalog().schemaLock());
112
// Check to see if it exists already.
113
identifier::Schema schema_identifier(schema_message.name());
114
if (plugin::StorageEngine::doesSchemaExist(schema_identifier))
116
if (not is_if_not_exists)
118
my_error(ER_DB_CREATE_EXISTS, schema_identifier);
123
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
124
ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
125
schema_message.name().c_str());
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
transaction_services.createSchema(session, schema_message);
140
session.startWaitingGlobalReadLock();
561
if (wait_if_global_read_lock(session, 0, 1))
567
pthread_mutex_lock(&LOCK_drizzle_create_db);
569
/* Check directory */
570
path_len= build_table_filename(path, sizeof(path), db, "", "", 0);
571
path[path_len-1]= 0; // Remove last '/' from path
573
if (!stat(path,&stat_info))
575
if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
577
my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
581
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
582
ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
592
my_error(EE_STAT, MYF(0), path, errno);
595
if (my_mkdir(path,0777,MYF(0)) < 0)
597
my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno);
603
path[path_len-1]= FN_LIBCHAR;
604
strncpy(path+path_len, MY_DB_OPT_FILE, sizeof(path)-path_len-1);
605
if (write_db_opt(session, path, db, create_info))
608
Could not create options file.
609
Restore things to beginning.
612
if (rmdir(path) >= 0)
618
We come here when we managed to create the database, but not the option
619
file. In this case it's best to just continue as if nothing has
620
happened. (This is a very unlikely senario)
627
uint32_t query_length;
629
if (!session->query) // Only in replication
632
query_length= sprintf(tmp_query, "create database `%s`", db);
636
query= session->query;
637
query_length= session->query_length;
640
if (drizzle_bin_log.is_open())
642
Query_log_event qinfo(session, query, query_length, 0,
643
/* suppress_use */ true);
646
Write should use the database being created as the "current
647
database" and not the threads current database, which is the
648
default. If we do not change the "current database" to the
649
database being created, the CREATE statement will not be
650
replicated when using --binlog-do-db to select databases to be
653
An example (--binlog-do-db=sisyfos):
655
CREATE DATABASE bob; # Not replicated
656
USE bob; # 'bob' is the current database
657
CREATE DATABASE sisyfos; # Not replicated since 'bob' is
659
USE sisyfos; # Will give error on slave since
660
# database does not exist.
663
qinfo.db_len = strlen(db);
665
/* These DDL methods and logging protected with LOCK_drizzle_create_db */
666
drizzle_bin_log.write(&qinfo);
668
my_ok(session, result);
672
pthread_mutex_unlock(&LOCK_drizzle_create_db);
673
start_waiting_global_read_lock(session);
146
679
/* db-name is already validated when we come here */
148
bool alter(Session &session,
149
const message::Schema &schema_message,
150
const message::Schema &original_schema)
681
bool mysql_alter_db(Session *session, const char *db, HA_CREATE_INFO *create_info)
152
TransactionServices &transaction_services= TransactionServices::singleton();
683
char path[FN_REFLEN+16];
155
688
Do not alter database if another thread is holding read lock.
156
Wait for global read lock before acquiring session->catalog()->schemaLock().
689
Wait for global read lock before acquiring LOCK_drizzle_create_db.
157
690
After wait_if_global_read_lock() we have protection against another
158
global read lock. If we would acquire session->catalog()->schemaLock() first,
691
global read lock. If we would acquire LOCK_drizzle_create_db first,
159
692
another thread could step in and get the global read lock before we
160
693
reach wait_if_global_read_lock(). If this thread tries the same as we
161
(admin a db), it would then go and wait on session->catalog()->schemaLock()...
694
(admin a db), it would then go and wait on LOCK_drizzle_create_db...
162
695
Furthermore wait_if_global_read_lock() checks if the current thread
163
696
has the global read lock and refuses the operation with
164
697
ER_CANT_UPDATE_WITH_READLOCK if applicable.
166
if ((session.wait_if_global_read_lock(false, true)))
171
boost::mutex::scoped_lock scopedLock(session.catalog().schemaLock());
173
identifier::Schema schema_idenifier(schema_message.name());
174
if (not plugin::StorageEngine::doesSchemaExist(schema_idenifier))
176
my_error(ER_SCHEMA_DOES_NOT_EXIST, schema_idenifier);
180
/* Change options if current database is being altered. */
181
success= plugin::StorageEngine::alterSchema(schema_message);
185
transaction_services.alterSchema(session, original_schema, schema_message);
190
my_error(ER_ALTER_SCHEMA, schema_idenifier);
193
session.startWaitingGlobalReadLock();
699
if ((error=wait_if_global_read_lock(session,0,1)))
702
pthread_mutex_lock(&LOCK_drizzle_create_db);
705
Recreate db options file: /dbpath/.db.opt
706
We pass MY_DB_OPT_FILE as "extension" to avoid
707
"table name to file name" encoding.
709
build_table_filename(path, sizeof(path), db, "", MY_DB_OPT_FILE, 0);
710
if ((error=write_db_opt(session, path, db, create_info)))
713
/* Change options if current database is being altered. */
715
if (session->db && !strcmp(session->db,db))
717
session->db_charset= create_info->default_table_charset ?
718
create_info->default_table_charset :
719
session->variables.collation_server;
720
session->variables.collation_database= session->db_charset;
723
if (drizzle_bin_log.is_open())
725
Query_log_event qinfo(session, session->query, session->query_length, 0,
726
/* suppress_use */ true);
729
Write should use the database being created as the "current
730
database" and not the threads current database, which is the
734
qinfo.db_len = strlen(db);
736
session->clear_error();
737
/* These DDL methods and logging protected with LOCK_drizzle_create_db */
738
drizzle_bin_log.write(&qinfo);
740
my_ok(session, result);
743
pthread_mutex_unlock(&LOCK_drizzle_create_db);
744
start_waiting_global_read_lock(session);
216
bool drop(Session &session, identifier::Schema &schema_identifier, const bool if_exists)
767
bool mysql_rm_db(Session *session,char *db,bool if_exists, bool silent)
771
char path[FN_REFLEN+16];
774
TableList* dropped_tables= 0;
776
if (db && (strcmp(db, "information_schema") == 0))
778
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
221
783
Do not drop database if another thread is holding read lock.
222
Wait for global read lock before acquiring session->catalog()->schemaLock().
784
Wait for global read lock before acquiring LOCK_drizzle_create_db.
223
785
After wait_if_global_read_lock() we have protection against another
224
global read lock. If we would acquire session->catalog()->schemaLock() first,
786
global read lock. If we would acquire LOCK_drizzle_create_db first,
225
787
another thread could step in and get the global read lock before we
226
788
reach wait_if_global_read_lock(). If this thread tries the same as we
227
(admin a db), it would then go and wait on session->catalog()->schemaLock()...
789
(admin a db), it would then go and wait on LOCK_drizzle_create_db...
228
790
Furthermore wait_if_global_read_lock() checks if the current thread
229
791
has the global read lock and refuses the operation with
230
792
ER_CANT_UPDATE_WITH_READLOCK if applicable.
232
if (session.wait_if_global_read_lock(false, true))
239
boost::mutex::scoped_lock scopedLock(session.catalog().schemaLock());
240
message::schema::shared_ptr message= plugin::StorageEngine::getSchemaDefinition(schema_identifier);
242
/* See if the schema exists */
248
schema_identifier.getSQLPath(path);
250
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
251
ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS),
257
my_error(ER_DB_DROP_EXISTS, schema_identifier);
263
error= plugin::StorageEngine::dropSchema(session, schema_identifier, *message);
794
if (wait_if_global_read_lock(session, 0, 1))
800
pthread_mutex_lock(&LOCK_drizzle_create_db);
802
length= build_table_filename(path, sizeof(path), db, "", "", 0);
803
strcpy(path+length, MY_DB_OPT_FILE); // Append db option file name
804
del_dbopt(path); // Remove dboption hash entry
805
path[length]= '\0'; // Remove file name
807
/* See if the directory exists */
808
if (!(dirp= my_dir(path,MYF(MY_DONT_SORT))))
813
my_error(ER_DB_DROP_EXISTS, MYF(0), db);
817
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
818
ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
822
pthread_mutex_lock(&LOCK_open);
823
remove_db_from_cache(db);
824
pthread_mutex_unlock(&LOCK_open);
828
if ((deleted= mysql_rm_known_files(session, dirp, db, path, 0,
829
&dropped_tables)) >= 0)
831
ha_drop_database(path);
835
if (!silent && deleted>=0)
838
uint32_t query_length;
841
/* The client used the old obsolete mysql_drop_db() call */
843
query_length= sprintf(path, "drop database `%s`", db);
847
query= session->query;
848
query_length= session->query_length;
850
if (drizzle_bin_log.is_open())
852
Query_log_event qinfo(session, query, query_length, 0,
853
/* suppress_use */ true);
855
Write should use the database being created as the "current
856
database" and not the threads current database, which is the
860
qinfo.db_len = strlen(db);
862
session->clear_error();
863
/* These DDL methods and logging protected with LOCK_drizzle_create_db */
864
drizzle_bin_log.write(&qinfo);
866
session->clear_error();
867
session->server_status|= SERVER_STATUS_DB_DROPPED;
868
my_ok(session, (uint32_t) deleted);
869
session->server_status&= ~SERVER_STATUS_DB_DROPPED;
871
else if (drizzle_bin_log.is_open())
873
char *query, *query_pos, *query_end, *query_data_start;
877
if (!(query= (char*) session->alloc(MAX_DROP_TABLE_Q_LEN)))
878
goto exit; /* not much else we can do */
879
query_pos= query_data_start= strcpy(query,"drop table ")+11;
880
query_end= query + MAX_DROP_TABLE_Q_LEN;
883
for (tbl= dropped_tables; tbl; tbl= tbl->next_local)
885
uint32_t tbl_name_len;
887
/* 3 for the quotes and the comma*/
888
tbl_name_len= strlen(tbl->table_name) + 3;
889
if (query_pos + tbl_name_len + 1 >= query_end)
891
/* These DDL methods and logging protected with LOCK_drizzle_create_db */
892
write_to_binlog(session, query, query_pos -1 - query, db, db_len);
893
query_pos= query_data_start;
897
query_pos= strcpy(query_pos,tbl->table_name) + (tbl_name_len-3);
902
if (query_pos != query_data_start)
904
/* These DDL methods and logging protected with LOCK_drizzle_create_db */
905
write_to_binlog(session, query, query_pos -1 - query, db, db_len);
269
911
If this database was the client's selected database, we silently
270
912
change the client's selected database to nothing (to have an empty
271
913
SELECT DATABASE() in the future). For this we free() session->db and set
274
if (not error and schema_identifier.compare(*session.schema()))
275
change_db_impl(session);
277
session.startWaitingGlobalReadLock();
916
if (session->db && !strcmp(session->db, db))
917
mysql_change_db_impl(session, NULL, session->variables.collation_server);
918
pthread_mutex_unlock(&LOCK_drizzle_create_db);
919
start_waiting_global_read_lock(session);
925
Removes files with known extensions plus.
926
session MUST be set when calling this function!
929
static long mysql_rm_known_files(Session *session, MY_DIR *dirp, const char *db,
930
const char *org_path, uint32_t level,
931
TableList **dropped_tables)
934
uint32_t found_other_files=0;
935
char filePath[FN_REFLEN];
936
TableList *tot_list=0, **tot_list_next;
938
tot_list_next= &tot_list;
940
for (uint32_t idx=0 ;
941
idx < (uint) dirp->number_off_files && !session->killed ;
944
FILEINFO *file=dirp->dir_entry+idx;
947
/* skiping . and .. */
948
if (file->name[0] == '.' && (!file->name[1] ||
949
(file->name[1] == '.' && !file->name[2])))
952
if (!(extension= strrchr(file->name, '.')))
953
extension= strchr(file->name, '\0');
954
if (find_type(extension, &deletable_extentions,1+2) <= 0)
959
strange checking for magic extensions that are then deleted if
960
not reg_ext (i.e. .frm).
962
and (previously) we'd err out on drop database if files not matching
963
engine ha_known_exts() or deletable_extensions were present.
965
presumably this was to avoid deleting other user data... except if that
966
data happened to be in files ending in .BAK, .opt or .TMD. *fun*
968
find_type(extension, ha_known_exts(),1+2);
971
/* just for safety we use files_charset_info */
972
if (db && !my_strcasecmp(files_charset_info,
975
uint32_t db_len= strlen(db);
977
/* Drop the table nicely */
978
*extension= 0; // Remove extension
979
TableList *table_list=(TableList*)
980
session->calloc(sizeof(*table_list) +
982
MYSQL50_TABLE_NAME_PREFIX_LENGTH +
983
strlen(file->name) + 1);
987
table_list->db= (char*) (table_list+1);
988
table_list->table_name= strcpy(table_list->db, db) + db_len + 1;
989
filename_to_tablename(file->name, table_list->table_name,
990
MYSQL50_TABLE_NAME_PREFIX_LENGTH +
991
strlen(file->name) + 1);
992
table_list->alias= table_list->table_name; // If lower_case_table_names=2
993
table_list->internal_tmp_table= is_prefix(file->name, TMP_FILE_PREFIX);
995
(*tot_list_next)= table_list;
996
tot_list_next= &table_list->next_local;
1001
sprintf(filePath, "%s/%s", org_path, file->name);
1002
if (my_delete_with_symlink(filePath,MYF(MY_WME)))
1008
if (session->killed ||
1009
(tot_list && mysql_rm_table_part2(session, tot_list, 1, 0, 1)))
1015
*dropped_tables= tot_list;
1018
If the directory is a symbolic link, remove the link first, then
1019
remove the directory the symbolic link pointed at
1021
if (found_other_files)
1023
my_error(ER_DB_DROP_RMDIR, MYF(0), org_path, EEXIST);
1028
/* Don't give errors if we can't delete 'RAID' directory */
1029
if (rm_dir_w_symlink(org_path, level == 0))
1042
Remove directory with symlink
1046
org_path path of derictory
1047
send_error send errors
1053
static bool rm_dir_w_symlink(const char *org_path, bool send_error)
1055
char tmp_path[FN_REFLEN], *pos;
1056
char *path= tmp_path;
1057
unpack_filename(tmp_path, org_path);
1058
#ifdef HAVE_READLINK
1060
char tmp2_path[FN_REFLEN];
1062
/* Remove end FN_LIBCHAR as this causes problem on Linux in readlink */
1063
pos= strchr(path, '\0');
1064
if (pos > path && pos[-1] == FN_LIBCHAR)
1067
if ((error= my_readlink(tmp2_path, path, MYF(MY_WME))) < 0)
1071
if (my_delete(path, MYF(send_error ? MY_WME : 0)))
1075
/* Delete directory symbolic link pointed at */
1079
/* Remove last FN_LIBCHAR to not cause a problem on OS/2 */
1080
pos= strchr(path, '\0');
1082
if (pos > path && pos[-1] == FN_LIBCHAR)
1084
if (rmdir(path) < 0 && send_error)
1086
my_error(ER_DB_DROP_RMDIR, MYF(0), path, errno);
1094
@brief Internal implementation: switch current database to a valid one.
1096
@param session Thread context.
1097
@param new_db_name Name of the database to switch to. The function will
1098
take ownership of the name (the caller must not free
1099
the allocated memory). If the name is NULL, we're
1100
going to switch to NULL db.
1101
@param new_db_charset Character set of the new database.
1104
static void mysql_change_db_impl(Session *session,
1105
LEX_STRING *new_db_name,
1106
const CHARSET_INFO * const new_db_charset)
1108
/* 1. Change current database in Session. */
1110
if (new_db_name == NULL)
1113
Session::set_db() does all the job -- it frees previous database name and
1117
session->set_db(NULL, 0);
1119
else if (my_strcasecmp(system_charset_info, new_db_name->str,
1120
INFORMATION_SCHEMA_NAME.c_str()) == 0)
1123
Here we must use Session::set_db(), because we want to copy
1124
INFORMATION_SCHEMA_NAME constant.
1127
session->set_db(INFORMATION_SCHEMA_NAME.c_str(),
1128
INFORMATION_SCHEMA_NAME.length());
1133
Here we already have a copy of database name to be used in Session. So,
1134
we just call Session::reset_db(). Since Session::reset_db() does not releases
1135
the previous database name, we should do it explicitly.
1141
session->reset_db(new_db_name->str, new_db_name->length);
1144
/* 3. Update db-charset environment variables. */
1146
session->db_charset= new_db_charset;
1147
session->variables.collation_database= new_db_charset;
1153
Backup the current database name before switch.
1155
@param[in] session thread handle
1156
@param[in, out] saved_db_name IN: "str" points to a buffer where to store
1157
the old database name, "length" contains the
1159
OUT: if the current (default) database is
1160
not NULL, its name is copied to the
1161
buffer pointed at by "str"
1162
and "length" is updated accordingly.
1163
Otherwise "str" is set to NULL and
1164
"length" is set to 0.
1167
static void backup_current_db_name(Session *session,
1168
LEX_STRING *saved_db_name)
1172
/* No current (default) database selected. */
1174
saved_db_name->str= NULL;
1175
saved_db_name->length= 0;
1179
strncpy(saved_db_name->str, session->db, saved_db_name->length - 1);
1180
saved_db_name->length= session->db_length;
1186
Return true if db1_name is equal to db2_name, false otherwise.
1188
The function allows to compare database names according to the MySQL
1189
rules. The database names db1 and db2 are equal if:
1190
- db1 is NULL and db2 is NULL;
1192
- db1 is not-NULL, db2 is not-NULL, db1 is equal (ignoring case) to
1193
db2 in system character set (UTF8).
1197
cmp_db_names(const char *db1_name,
1198
const char *db2_name)
1201
/* db1 is NULL and db2 is NULL */
1202
(!db1_name && !db2_name) ||
1204
/* db1 is not-NULL, db2 is not-NULL, db1 == db2. */
1205
(db1_name && db2_name && my_strcasecmp(system_charset_info, db1_name, db2_name) == 0);
283
1210
@brief Change the current database and its attributes unconditionally.
341
1268
@retval true Error
344
bool change(Session &session, identifier::Schema &schema_identifier)
1271
bool mysql_change_db(Session *session, const LEX_STRING *new_db_name, bool force_switch)
347
if (not plugin::Authorization::isAuthorized(*session.user(), schema_identifier))
349
/* Error message is set in isAuthorized */
353
if (not check(session, schema_identifier))
355
my_error(ER_WRONG_DB_NAME, schema_identifier);
360
if (not plugin::StorageEngine::doesSchemaExist(schema_identifier))
362
my_error(ER_BAD_DB_ERROR, schema_identifier);
364
/* The operation failed. */
369
change_db_impl(session, schema_identifier);
1273
LEX_STRING new_db_file_name;
1274
const CHARSET_INFO *db_default_cl;
1276
if (new_db_name == NULL ||
1277
new_db_name->length == 0)
1282
This can happen only if we're switching the current database back
1283
after loading stored program. The thing is that loading of stored
1284
program can happen when there is no current database.
1286
TODO: actually, new_db_name and new_db_name->str seem to be always
1287
non-NULL. In case of stored program, new_db_name->str == "" and
1288
new_db_name->length == 0.
1291
mysql_change_db_impl(session, NULL, session->variables.collation_server);
1297
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
1303
if (my_strcasecmp(system_charset_info, new_db_name->str,
1304
INFORMATION_SCHEMA_NAME.c_str()) == 0)
1306
/* Switch the current database to INFORMATION_SCHEMA. */
1307
/* const_cast<> is safe here: mysql_change_db_impl does a copy */
1308
LEX_STRING is_name= { const_cast<char *>(INFORMATION_SCHEMA_NAME.c_str()),
1309
INFORMATION_SCHEMA_NAME.length() };
1310
mysql_change_db_impl(session, &is_name, system_charset_info);
1316
Now we need to make a copy because check_db_name requires a
1317
non-constant argument. Actually, it takes database file name.
1319
TODO: fix check_db_name().
1322
new_db_file_name.length= new_db_name->length;
1323
new_db_file_name.str= (char *)malloc(new_db_name->length + 1);
1324
if (new_db_file_name.str == NULL)
1325
return(true); /* the error is set */
1326
memcpy(new_db_file_name.str, new_db_name->str, new_db_name->length);
1327
new_db_file_name.str[new_db_name->length]= 0;
1331
NOTE: if check_db_name() fails, we should throw an error in any case,
1332
even if we are called from sp_head::execute().
1334
It's next to impossible however to get this error when we are called
1335
from sp_head::execute(). But let's switch the current database to NULL
1336
in this case to be sure.
1339
if (check_db_name(&new_db_file_name))
1341
my_error(ER_WRONG_DB_NAME, MYF(0), new_db_file_name.str);
1342
free(new_db_file_name.str);
1345
mysql_change_db_impl(session, NULL, session->variables.collation_server);
1350
if (check_db_dir_existence(new_db_file_name.str))
1354
/* Throw a warning and free new_db_file_name. */
1356
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1357
ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
1358
new_db_file_name.str);
1360
free(new_db_file_name.str);
1362
/* Change db to NULL. */
1364
mysql_change_db_impl(session, NULL, session->variables.collation_server);
1366
/* The operation succeed. */
1372
/* Report an error and free new_db_file_name. */
1374
my_error(ER_BAD_DB_ERROR, MYF(0), new_db_file_name.str);
1375
free(new_db_file_name.str);
1377
/* The operation failed. */
1384
NOTE: in mysql_change_db_impl() new_db_file_name is assigned to Session
1385
attributes and will be freed in Session::~Session().
1388
db_default_cl= get_default_db_collation(session, new_db_file_name.str);
1390
mysql_change_db_impl(session, &new_db_file_name, db_default_cl);
375
@brief Internal implementation: switch current database to a valid one.
1397
Change the current database and its attributes if needed.
377
@param session Thread context.
378
@param new_db_name Name of the database to switch to. The function will
379
take ownership of the name (the caller must not free
380
the allocated memory). If the name is NULL, we're
381
going to switch to NULL db.
382
@param new_db_charset Character set of the new database.
1399
@param session thread handle
1400
@param new_db_name database name
1401
@param[in, out] saved_db_name IN: "str" points to a buffer where to store
1402
the old database name, "length" contains the
1404
OUT: if the current (default) database is
1405
not NULL, its name is copied to the
1406
buffer pointed at by "str"
1407
and "length" is updated accordingly.
1408
Otherwise "str" is set to NULL and
1409
"length" is set to 0.
1410
@param force_switch @see mysql_change_db()
1411
@param[out] cur_db_changed out-flag to indicate whether the current
1412
database has been changed (valid only if
1413
the function suceeded)
385
static void change_db_impl(Session &session, identifier::Schema &schema_identifier)
387
/* 1. Change current database in Session. */
390
if (new_db_name == NULL)
393
Session::set_db() does all the job -- it frees previous database name and
397
session->set_db(NULL, 0);
403
Here we already have a copy of database name to be used in Session. So,
404
we just call Session::reset_db(). Since Session::reset_db() does not releases
405
the previous database name, we should do it explicitly.
408
session.set_db(schema_identifier.getSchemaName());
412
static void change_db_impl(Session &session)
414
session.set_db(string());
1416
bool mysql_opt_change_db(Session *session,
1417
const LEX_STRING *new_db_name,
1418
LEX_STRING *saved_db_name,
1420
bool *cur_db_changed)
1422
*cur_db_changed= !cmp_db_names(session->db, new_db_name->str);
1424
if (!*cur_db_changed)
1427
backup_current_db_name(session, saved_db_name);
1429
return mysql_change_db(session, new_db_name, force_switch);
418
Check if database name is valid
422
org_name Name of database and length
1434
Check if there is directory for the database name.
1437
check_db_dir_existence()
1438
db_name database name
1441
false There is directory for the specified database name.
1442
true The directory does not exist.
429
bool check(Session &session, identifier::Schema &schema_identifier)
1445
bool check_db_dir_existence(const char *db_name)
431
if (not plugin::Authorization::isAuthorized(*session.user(), schema_identifier))
436
return schema_identifier.isValid();
1447
char db_dir_path[FN_REFLEN];
1448
uint32_t db_dir_path_len;
1450
db_dir_path_len= build_table_filename(db_dir_path, sizeof(db_dir_path),
1451
db_name, "", "", 0);
1453
if (db_dir_path_len && db_dir_path[db_dir_path_len - 1] == FN_LIBCHAR)
1454
db_dir_path[db_dir_path_len - 1]= 0;
1458
return my_access(db_dir_path, F_OK);
439
} /* namespace schema */
441
} /* namespace drizzled */