~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/db.cc

  • Committer: Brian Aker
  • Date: 2009-02-12 22:45:08 UTC
  • Revision ID: brian@tangent.org-20090212224508-mrd9jwgn1zjdpqdk
Minor refactoring (we will need to disconnect the code from the include
file).

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
 
17
17
/* create and drop of databases */
18
 
#include "config.h"
 
18
#include <drizzled/global.h>
 
19
#include CSTDINT_H
 
20
#include CINTTYPES_H
19
21
#include <string>
20
22
#include <fstream>
21
23
#include <drizzled/serialize/serialize.h>
23
25
#include <drizzled/server_includes.h>
24
26
#include <mysys/mysys_err.h>
25
27
#include <mysys/my_dir.h>
26
 
#include "log.h"
27
 
#include <drizzled/drizzled_error_messages.h>
28
 
#include <libdrizzle/gettext.h>
29
 
 
30
 
 
 
28
#include <drizzled/error.h>
 
29
#include <drizzled/gettext.h>
 
30
#include <mysys/hash.h>
 
31
#include <drizzled/session.h>
 
32
#include <drizzled/db.h>
 
33
#include <drizzled/sql_base.h>
 
34
#include <drizzled/lock.h>
 
35
#include <drizzled/errmsg_print.h>
 
36
#include <drizzled/replicator.h>
 
37
 
 
38
#define MY_DB_OPT_FILE "db.opt"
31
39
#define MAX_DROP_TABLE_Q_LEN      1024
32
40
 
33
41
const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NULL};
34
42
static TYPELIB deletable_extentions=
35
43
{array_elements(del_exts)-1,"del_exts", del_exts, NULL};
36
44
 
37
 
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
38
 
                                 const char *db, const char *path, uint32_t level, 
 
45
static long mysql_rm_known_files(Session *session, MY_DIR *dirp,
 
46
                                 const char *db, const char *path,
 
47
                                 uint32_t level,
39
48
                                 TableList **dropped_tables);
40
 
         
 
49
 
41
50
static bool rm_dir_w_symlink(const char *org_path, bool send_error);
42
 
static void mysql_change_db_impl(THD *thd,
 
51
static void mysql_change_db_impl(Session *session,
43
52
                                 LEX_STRING *new_db_name,
44
53
                                 const CHARSET_INFO * const new_db_charset);
45
54
 
47
56
/* Database lock hash */
48
57
HASH lock_db_cache;
49
58
pthread_mutex_t LOCK_lock_db;
 
59
bool dbcache_init= false;
50
60
int creating_database= 0;  // how many database locks are made
51
61
 
52
62
 
65
75
extern "C" unsigned char* lock_db_get_key(my_dblock_t *, size_t *, bool not_used);
66
76
 
67
77
unsigned char* lock_db_get_key(my_dblock_t *ptr, size_t *length,
68
 
                       bool not_used __attribute__((unused)))
 
78
                       bool )
69
79
{
70
80
  *length= ptr->name_length;
71
81
  return (unsigned char*) ptr->name;
97
107
    hash_delete(&lock_db_cache, (unsigned char*) opt);
98
108
}
99
109
 
100
 
 
101
 
/* Database options hash */
102
 
static HASH dboptions;
103
 
static bool dboptions_init= 0;
104
 
static rw_lock_t LOCK_dboptions;
105
 
 
106
 
/* Structure for database options */
107
 
typedef struct my_dbopt_st
108
 
{
109
 
  char *name;                   /* Database name                  */
110
 
  uint32_t name_length;         /* Database length name           */
111
 
  const CHARSET_INFO *charset;  /* Database default character set */
112
 
} my_dbopt_t;
113
 
 
114
 
 
115
 
/*
116
 
  Function we use in the creation of our hash to get key.
117
 
*/
118
 
 
119
 
extern "C" unsigned char* dboptions_get_key(my_dbopt_t *opt, size_t *length,
120
 
                                    bool not_used);
121
 
 
122
 
unsigned char* dboptions_get_key(my_dbopt_t *opt, size_t *length,
123
 
                         bool not_used __attribute__((unused)))
124
 
{
125
 
  *length= opt->name_length;
126
 
  return (unsigned char*) opt->name;
127
 
}
128
 
 
129
 
 
130
110
/*
131
111
  Helper function to write a query to binlog used by mysql_rm_db()
132
112
*/
133
113
 
134
 
static inline void write_to_binlog(THD *thd, char *query, uint32_t q_len,
135
 
                                   char *db, uint32_t db_len)
 
114
static inline void write_to_binlog(Session *session, char *query, uint32_t query_length, char *, uint32_t)
136
115
{
137
 
  Query_log_event qinfo(thd, query, q_len, 0, 0);
138
 
  qinfo.error_code= 0;
139
 
  qinfo.db= db;
140
 
  qinfo.db_len= db_len;
141
 
  mysql_bin_log.write(&qinfo);
142
 
}  
143
 
 
 
116
  (void)replicator_statement(session, query, query_length);
 
117
}
144
118
 
145
119
/*
146
 
  Function to free dboptions hash element
147
 
*/
148
 
 
149
 
extern "C" void free_dbopt(void *dbopt);
150
 
 
151
 
void free_dbopt(void *dbopt)
152
 
{
153
 
  free((unsigned char*) dbopt);
154
 
}
155
 
 
156
 
 
157
 
/* 
158
120
  Initialize database option hash and locked database hash.
159
121
 
160
122
  SYNOPSIS
171
133
bool my_database_names_init(void)
172
134
{
173
135
  bool error= false;
174
 
  (void) my_rwlock_init(&LOCK_dboptions, NULL);
175
 
  if (!dboptions_init)
 
136
  if (!dbcache_init)
176
137
  {
177
 
    dboptions_init= 1;
178
 
    error= hash_init(&dboptions, lower_case_table_names ? 
179
 
                     &my_charset_bin : system_charset_info,
180
 
                     32, 0, 0, (hash_get_key) dboptions_get_key,
181
 
                     free_dbopt,0) ||
182
 
           hash_init(&lock_db_cache, lower_case_table_names ? 
 
138
    dbcache_init= true;
 
139
    error= hash_init(&lock_db_cache, lower_case_table_names ?
183
140
                     &my_charset_bin : system_charset_info,
184
141
                     32, 0, 0, (hash_get_key) lock_db_get_key,
185
142
                     lock_db_free_element,0);
188
145
  return error;
189
146
}
190
147
 
191
 
 
192
 
 
193
 
/* 
194
 
  Free database option hash and locked databases hash.
195
 
*/
196
 
 
197
 
void my_database_names_free(void)
198
 
{
199
 
  if (dboptions_init)
200
 
  {
201
 
    dboptions_init= 0;
202
 
    hash_free(&dboptions);
203
 
    (void) rwlock_destroy(&LOCK_dboptions);
204
 
    hash_free(&lock_db_cache);
205
 
  }
206
 
}
207
 
 
208
 
 
209
 
/*
210
 
  Cleanup cached options
211
 
*/
212
 
 
213
 
void my_dbopt_cleanup(void)
214
 
{
215
 
  rw_wrlock(&LOCK_dboptions);
216
 
  hash_free(&dboptions);
217
 
  hash_init(&dboptions, lower_case_table_names ? 
218
 
            &my_charset_bin : system_charset_info,
219
 
            32, 0, 0, (hash_get_key) dboptions_get_key,
220
 
            free_dbopt,0);
221
 
  rw_unlock(&LOCK_dboptions);
222
 
}
223
 
 
224
 
 
225
 
/*
226
 
  Find database options in the hash.
227
 
  
228
 
  DESCRIPTION
229
 
    Search a database options in the hash, usings its path.
230
 
    Fills "create" on success.
231
 
  
232
 
  RETURN VALUES
233
 
    0 on success.
234
 
    1 on error.
235
 
*/
236
 
 
237
 
static bool get_dbopt(const char *dbname, HA_CREATE_INFO *create)
238
 
{
239
 
  my_dbopt_t *opt;
240
 
  uint32_t length;
241
 
  bool error= true;
242
 
  
243
 
  length= (uint) strlen(dbname);
244
 
  
245
 
  rw_rdlock(&LOCK_dboptions);
246
 
  if ((opt= (my_dbopt_t*) hash_search(&dboptions, (unsigned char*) dbname, length)))
247
 
  {
248
 
    create->default_table_charset= opt->charset;
249
 
    error= true;
250
 
  }
251
 
  rw_unlock(&LOCK_dboptions);
252
 
  return error;
253
 
}
254
 
 
255
 
 
256
 
/*
257
 
  Writes database options into the hash.
258
 
  
259
 
  DESCRIPTION
260
 
    Inserts database options into the hash, or updates
261
 
    options if they are already in the hash.
262
 
  
263
 
  RETURN VALUES
264
 
    0 on success.
265
 
    1 on error.
266
 
*/
267
 
 
268
 
static bool put_dbopt(const char *dbname, HA_CREATE_INFO *create)
269
 
{
270
 
  my_dbopt_t *opt;
271
 
  uint32_t length;
272
 
  bool error= false;
273
 
 
274
 
  length= (uint) strlen(dbname);
275
 
  
276
 
  rw_wrlock(&LOCK_dboptions);
277
 
  if (!(opt= (my_dbopt_t*) hash_search(&dboptions, (unsigned char*) dbname, length)))
278
 
  { 
279
 
    /* Options are not in the hash, insert them */
280
 
    char *tmp_name;
281
 
    if (!my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
282
 
                         &opt, (uint) sizeof(*opt), &tmp_name, (uint) length+1,
283
 
                         NULL))
284
 
    {
285
 
      error= true;
286
 
      goto end;
287
 
    }
288
 
    
289
 
    opt->name= tmp_name;
290
 
    my_stpcpy(opt->name, dbname);
291
 
    opt->name_length= length;
292
 
    
293
 
    if ((error= my_hash_insert(&dboptions, (unsigned char*) opt)))
294
 
    {
295
 
      free(opt);
296
 
      goto end;
297
 
    }
298
 
  }
299
 
 
300
 
  /* Update / write options in hash */
301
 
  opt->charset= create->default_table_charset;
302
 
 
303
 
end:
304
 
  rw_unlock(&LOCK_dboptions);  
305
 
  return(error);
306
 
}
307
 
 
308
 
 
309
 
/*
310
 
  Deletes database options from the hash.
311
 
*/
312
 
 
313
 
void del_dbopt(const char *path)
314
 
{
315
 
  my_dbopt_t *opt;
316
 
  rw_wrlock(&LOCK_dboptions);
317
 
  if ((opt= (my_dbopt_t *)hash_search(&dboptions, (const unsigned char*) path,
318
 
                                      strlen(path))))
319
 
    hash_delete(&dboptions, (unsigned char*) opt);
320
 
  rw_unlock(&LOCK_dboptions);
321
 
}
322
 
 
323
 
 
324
 
/*
325
 
  Create database options file:
326
 
 
327
 
  DESCRIPTION
328
 
    Currently database default charset is only stored there.
329
 
 
330
 
  RETURN VALUES
331
 
  0     ok
332
 
  1     Could not create file or write to it.  Error sent through my_error()
333
 
*/
334
 
 
335
 
static bool write_db_opt(THD *thd, const char *path, const char *name, HA_CREATE_INFO *create)
336
 
{
337
 
  bool error= true;
 
148
/**
 
149
  Return default database collation.
 
150
 
 
151
  @param session     Thread context.
 
152
  @param db_name Database name.
 
153
 
 
154
  @return CHARSET_INFO object. The operation always return valid character
 
155
    set, even if the database does not exist.
 
156
*/
 
157
 
 
158
const CHARSET_INFO *get_default_db_collation(Session *session, const char *db_name)
 
159
{
 
160
  HA_CREATE_INFO db_info;
 
161
 
 
162
  if (session->db != NULL && strcmp(db_name, session->db) == 0)
 
163
    return session->db_charset;
 
164
 
 
165
  /*
 
166
    db_info.default_table_charset contains valid character set
 
167
    (collation_server).
 
168
  */
 
169
 
 
170
  load_db_opt_by_name(session, db_name, &db_info);
 
171
 
 
172
  return db_info.default_table_charset;
 
173
}
 
174
 
 
175
/* path is path to database, not schema file */
 
176
static int write_schema_file(Session *session,
 
177
                             const char *path, const char *name,
 
178
                             HA_CREATE_INFO *create)
 
179
{
338
180
  drizzle::Schema db;
 
181
  char schema_file_tmp[FN_REFLEN];
 
182
  string schema_file(path);
339
183
 
 
184
  assert(path);
340
185
  assert(name);
 
186
  assert(create);
 
187
 
 
188
  snprintf(schema_file_tmp, FN_REFLEN, "%s%c%s.tmpXXXXXX", path, FN_LIBCHAR, MY_DB_OPT_FILE);
 
189
 
 
190
  schema_file.append(1, FN_LIBCHAR);
 
191
  schema_file.append(MY_DB_OPT_FILE);
 
192
 
 
193
  int fd= mkstemp(schema_file_tmp);
 
194
 
 
195
  if (fd==-1)
 
196
    return errno;
341
197
 
342
198
  if (!create->default_table_charset)
343
 
    create->default_table_charset= thd->variables.collation_server;
344
 
 
345
 
  if (put_dbopt(path, create))
346
 
    return 1;
 
199
    create->default_table_charset= session->variables.collation_server;
347
200
 
348
201
  db.set_name(name);
349
 
  db.set_characterset(create->default_table_charset->csname);
350
202
  db.set_collation(create->default_table_charset->name);
351
203
 
352
 
  fstream output(path, ios::out | ios::trunc | ios::binary);
353
 
  if (!db.SerializeToOstream(&output)) 
354
 
    error= false;
355
 
 
356
 
  return error;
 
204
  if (!db.SerializeToFileDescriptor(fd))
 
205
  {
 
206
    close(fd);
 
207
    unlink(schema_file_tmp);
 
208
    return -1;
 
209
  }
 
210
 
 
211
  if (rename(schema_file_tmp, schema_file.c_str()) == -1)
 
212
  {
 
213
    close(fd);
 
214
    return errno;
 
215
  }
 
216
 
 
217
  close(fd);
 
218
  return 0;
357
219
}
358
220
 
359
 
 
360
 
/*
361
 
  Load database options file
362
 
 
363
 
  load_db_opt()
364
 
  path          Path for option file
365
 
  create        Where to store the read options
366
 
 
367
 
  DESCRIPTION
368
 
 
369
 
  RETURN VALUES
370
 
  0     File found
371
 
  1     No database file or could not open it
372
 
 
373
 
*/
374
 
 
375
 
bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
 
221
int load_db_opt(Session *session, const char *path, HA_CREATE_INFO *create)
376
222
{
377
 
  bool error=1;
378
223
  drizzle::Schema db;
379
224
  string buffer;
380
225
 
381
226
  memset(create, 0, sizeof(*create));
382
 
  create->default_table_charset= thd->variables.collation_server;
383
 
 
384
 
  /* Check if options for this database are already in the hash */
385
 
  if (!get_dbopt(path, create))
386
 
    return(0);
387
 
 
388
 
  fstream input(path, ios::in | ios::binary);
389
 
  if (!input)
390
 
    goto err1;
391
 
  else if (!db.ParseFromIstream(&input))
392
 
    goto err1;
393
 
 
394
 
  buffer= db.characterset();
395
 
  if (!(create->default_table_charset= get_charset_by_csname(buffer.c_str(), MY_CS_PRIMARY, MYF(0))))
 
227
  create->default_table_charset= session->variables.collation_server;
 
228
 
 
229
  int fd= open(path, O_RDONLY);
 
230
 
 
231
  if (fd == -1)
 
232
    return errno;
 
233
 
 
234
  if (!db.ParseFromFileDescriptor(fd))
396
235
  {
397
 
    sql_print_error(_("Error while loading database options: '%s':"),path);
398
 
    sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
399
 
    create->default_table_charset= default_charset_info;
 
236
    close(fd);
 
237
    return -1;
400
238
  }
 
239
  close(fd);
401
240
 
402
241
  buffer= db.collation();
403
 
  if (!(create->default_table_charset= get_charset_by_name(buffer.c_str(), MYF(0))))
 
242
  if (!(create->default_table_charset= get_charset_by_name(buffer.c_str())))
404
243
  {
405
 
    sql_print_error(_("Error while loading database options: '%s':"),path);
406
 
    sql_print_error(ER(ER_UNKNOWN_COLLATION), buffer.c_str());
 
244
    errmsg_printf(ERRMSG_LVL_ERROR,
 
245
                  _("Error while loading database options: '%s':"),path);
 
246
    errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UNKNOWN_COLLATION), buffer.c_str());
407
247
    create->default_table_charset= default_charset_info;
 
248
    return -1;
408
249
  }
409
250
 
410
 
  /*
411
 
    Put the loaded value into the hash.
412
 
    Note that another thread could've added the same
413
 
    entry to the hash after we called get_dbopt(),
414
 
    but it's not an error, as put_dbopt() takes this
415
 
    possibility into account.
416
 
  */
417
 
  error= put_dbopt(path, create);
418
 
 
419
 
err1:
420
 
  return(error);
 
251
  return 0;
421
252
}
422
253
 
423
 
 
424
 
/*
425
 
  Retrieve database options by name. Load database options file or fetch from
426
 
  cache.
427
 
 
428
 
  SYNOPSIS
429
 
    load_db_opt_by_name()
430
 
    db_name         Database name
431
 
    db_create_info  Where to store the database options
432
 
 
433
 
  DESCRIPTION
434
 
    load_db_opt_by_name() is a shortcut for load_db_opt().
435
 
 
436
 
  NOTE
437
 
    Although load_db_opt_by_name() (and load_db_opt()) returns status of
438
 
    the operation, it is useless usually and should be ignored. The problem
439
 
    is that there are 1) system databases ("mysql") and 2) virtual
440
 
    databases ("information_schema"), which do not contain options file.
441
 
    So, load_db_opt[_by_name]() returns false for these databases, but this
442
 
    is not an error.
443
 
 
444
 
    load_db_opt[_by_name]() clears db_create_info structure in any case, so
445
 
    even on failure it contains valid data. So, common use case is just
446
 
    call load_db_opt[_by_name]() without checking return value and use
447
 
    db_create_info right after that.
448
 
 
449
 
  RETURN VALUES (read NOTE!)
450
 
    false   Success
451
 
    true    Failed to retrieve options
452
 
*/
453
 
 
454
 
bool load_db_opt_by_name(THD *thd, const char *db_name,
455
 
                         HA_CREATE_INFO *db_create_info)
 
254
int load_db_opt_by_name(Session *session, const char *db_name,
 
255
                        HA_CREATE_INFO *db_create_info)
456
256
{
457
257
  char db_opt_path[FN_REFLEN];
458
258
 
463
263
  (void) build_table_filename(db_opt_path, sizeof(db_opt_path),
464
264
                              db_name, "", MY_DB_OPT_FILE, 0);
465
265
 
466
 
  return load_db_opt(thd, db_opt_path, db_create_info);
467
 
}
468
 
 
469
 
 
470
 
/**
471
 
  Return default database collation.
472
 
 
473
 
  @param thd     Thread context.
474
 
  @param db_name Database name.
475
 
 
476
 
  @return CHARSET_INFO object. The operation always return valid character
477
 
    set, even if the database does not exist.
478
 
*/
479
 
 
480
 
const CHARSET_INFO *get_default_db_collation(THD *thd, const char *db_name)
481
 
{
482
 
  HA_CREATE_INFO db_info;
483
 
 
484
 
  if (thd->db != NULL && strcmp(db_name, thd->db) == 0)
485
 
    return thd->db_charset;
486
 
 
487
 
  load_db_opt_by_name(thd, db_name, &db_info);
488
 
 
489
 
  /*
490
 
    NOTE: even if load_db_opt_by_name() fails,
491
 
    db_info.default_table_charset contains valid character set
492
 
    (collation_server). We should not fail if load_db_opt_by_name() fails,
493
 
    because it is valid case. If a database has been created just by
494
 
    "mkdir", it does not contain db.opt file, but it is valid database.
495
 
  */
496
 
 
497
 
  return db_info.default_table_charset;
 
266
  return load_db_opt(session, db_opt_path, db_create_info);
498
267
}
499
268
 
500
269
 
503
272
 
504
273
  SYNOPSIS
505
274
  mysql_create_db()
506
 
  thd           Thread handler
 
275
  session               Thread handler
507
276
  db            Name of database to create
508
277
                Function assumes that this is already validated.
509
278
  create_info   Database create options (like character set)
522
291
 
523
292
*/
524
293
 
525
 
int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info, bool silent)
 
294
int mysql_create_db(Session *session, char *db, HA_CREATE_INFO *create_info, bool silent)
526
295
{
527
296
  char   path[FN_REFLEN+16];
528
297
  char   tmp_query[FN_REFLEN+16];
529
298
  long result= 1;
530
299
  int error= 0;
531
 
  struct stat stat_info;
532
300
  uint32_t create_options= create_info ? create_info->options : 0;
533
301
  uint32_t path_len;
534
302
 
535
303
  /* do not create 'information_schema' db */
536
 
  if (!my_strcasecmp(system_charset_info, db, INFORMATION_SCHEMA_NAME.str))
 
304
  if (!my_strcasecmp(system_charset_info, db, INFORMATION_SCHEMA_NAME.c_str()))
537
305
  {
538
306
    my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
539
307
    return(-1);
541
309
 
542
310
  /*
543
311
    Do not create database if another thread is holding read lock.
544
 
    Wait for global read lock before acquiring LOCK_mysql_create_db.
 
312
    Wait for global read lock before acquiring LOCK_drizzleclient_create_db.
545
313
    After wait_if_global_read_lock() we have protection against another
546
 
    global read lock. If we would acquire LOCK_mysql_create_db first,
 
314
    global read lock. If we would acquire LOCK_drizzleclient_create_db first,
547
315
    another thread could step in and get the global read lock before we
548
316
    reach wait_if_global_read_lock(). If this thread tries the same as we
549
 
    (admin a db), it would then go and wait on LOCK_mysql_create_db...
 
317
    (admin a db), it would then go and wait on LOCK_drizzleclient_create_db...
550
318
    Furthermore wait_if_global_read_lock() checks if the current thread
551
319
    has the global read lock and refuses the operation with
552
320
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
553
321
  */
554
 
  if (wait_if_global_read_lock(thd, 0, 1))
 
322
  if (wait_if_global_read_lock(session, 0, 1))
555
323
  {
556
324
    error= -1;
557
325
    goto exit2;
558
326
  }
559
327
 
560
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
 
328
  pthread_mutex_lock(&LOCK_drizzleclient_create_db);
561
329
 
562
330
  /* Check directory */
563
331
  path_len= build_table_filename(path, sizeof(path), db, "", "", 0);
564
332
  path[path_len-1]= 0;                    // Remove last '/' from path
565
333
 
566
 
  if (!stat(path,&stat_info))
 
334
  if (mkdir(path,0777) == -1)
567
335
  {
568
 
    if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
 
336
    if (errno == EEXIST)
569
337
    {
570
 
      my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
571
 
      error= -1;
 
338
      if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
 
339
      {
 
340
        my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
 
341
        error= -1;
 
342
        goto exit;
 
343
      }
 
344
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
345
                          ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
 
346
      if (!silent)
 
347
        session->my_ok();
 
348
      error= 0;
572
349
      goto exit;
573
350
    }
574
 
    push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
575
 
                        ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS), db);
576
 
    if (!silent)
577
 
      my_ok(thd);
578
 
    error= 0;
 
351
 
 
352
    my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno);
 
353
    error= -1;
579
354
    goto exit;
580
355
  }
581
 
  else
582
 
  {
583
 
    if (errno != ENOENT)
584
 
    {
585
 
      my_error(EE_STAT, MYF(0), path, errno);
586
 
      goto exit;
587
 
    }
588
 
    if (my_mkdir(path,0777,MYF(0)) < 0)
589
 
    {
590
 
      my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno);
591
 
      error= -1;
592
 
      goto exit;
593
 
    }
594
 
  }
595
356
 
596
 
  path[path_len-1]= FN_LIBCHAR;
597
 
  strmake(path+path_len, MY_DB_OPT_FILE, sizeof(path)-path_len-1);
598
 
  if (write_db_opt(thd, path, db, create_info))
 
357
  error= write_schema_file(session, path, db, create_info);
 
358
  if (error && error != EEXIST)
599
359
  {
600
 
    /*
601
 
      Could not create options file.
602
 
      Restore things to beginning.
603
 
    */
604
 
    path[path_len]= 0;
605
360
    if (rmdir(path) >= 0)
606
361
    {
607
362
      error= -1;
608
363
      goto exit;
609
364
    }
610
 
    /*
611
 
      We come here when we managed to create the database, but not the option
612
 
      file.  In this case it's best to just continue as if nothing has
613
 
      happened.  (This is a very unlikely senario)
614
 
    */
615
365
  }
616
 
  
 
366
 
617
367
  if (!silent)
618
368
  {
619
369
    char *query;
620
370
    uint32_t query_length;
621
371
 
622
 
    if (!thd->query)                            // Only in replication
 
372
    if (!session->query)                                // Only in replication
623
373
    {
624
 
      query=         tmp_query;
625
 
      query_length= (uint) (strxmov(tmp_query,"create database `",
626
 
                                    db, "`", NULL) - tmp_query);
 
374
      query= tmp_query;
 
375
      query_length= sprintf(tmp_query, "create database `%s`", db);
627
376
    }
628
377
    else
629
378
    {
630
 
      query=        thd->query;
631
 
      query_length= thd->query_length;
632
 
    }
633
 
 
634
 
    if (mysql_bin_log.is_open())
635
 
    {
636
 
      Query_log_event qinfo(thd, query, query_length, 0, 
637
 
                            /* suppress_use */ true);
638
 
 
639
 
      /*
640
 
        Write should use the database being created as the "current
641
 
        database" and not the threads current database, which is the
642
 
        default. If we do not change the "current database" to the
643
 
        database being created, the CREATE statement will not be
644
 
        replicated when using --binlog-do-db to select databases to be
645
 
        replicated. 
646
 
 
647
 
        An example (--binlog-do-db=sisyfos):
648
 
       
649
 
          CREATE DATABASE bob;        # Not replicated
650
 
          USE bob;                    # 'bob' is the current database
651
 
          CREATE DATABASE sisyfos;    # Not replicated since 'bob' is
652
 
                                      # current database.
653
 
          USE sisyfos;                # Will give error on slave since
654
 
                                      # database does not exist.
655
 
      */
656
 
      qinfo.db     = db;
657
 
      qinfo.db_len = strlen(db);
658
 
 
659
 
      /* These DDL methods and logging protected with LOCK_mysql_create_db */
660
 
      mysql_bin_log.write(&qinfo);
661
 
    }
662
 
    my_ok(thd, result);
 
379
      query=        session->query;
 
380
      query_length= session->query_length;
 
381
    }
 
382
 
 
383
    (void)replicator_statement(session, query, query_length);
 
384
    session->my_ok(result);
663
385
  }
664
386
 
665
387
exit:
666
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
667
 
  start_waiting_global_read_lock(thd);
 
388
  pthread_mutex_unlock(&LOCK_drizzleclient_create_db);
 
389
  start_waiting_global_read_lock(session);
668
390
exit2:
669
391
  return(error);
670
392
}
672
394
 
673
395
/* db-name is already validated when we come here */
674
396
 
675
 
bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
 
397
bool mysql_alter_db(Session *session, const char *db, HA_CREATE_INFO *create_info)
676
398
{
677
 
  char path[FN_REFLEN+16];
678
399
  long result=1;
679
 
  int error= false;
 
400
  int error= 0;
 
401
  char   path[FN_REFLEN+16];
 
402
  uint32_t path_len;
680
403
 
681
404
  /*
682
405
    Do not alter database if another thread is holding read lock.
683
 
    Wait for global read lock before acquiring LOCK_mysql_create_db.
 
406
    Wait for global read lock before acquiring LOCK_drizzleclient_create_db.
684
407
    After wait_if_global_read_lock() we have protection against another
685
 
    global read lock. If we would acquire LOCK_mysql_create_db first,
 
408
    global read lock. If we would acquire LOCK_drizzleclient_create_db first,
686
409
    another thread could step in and get the global read lock before we
687
410
    reach wait_if_global_read_lock(). If this thread tries the same as we
688
 
    (admin a db), it would then go and wait on LOCK_mysql_create_db...
 
411
    (admin a db), it would then go and wait on LOCK_drizzleclient_create_db...
689
412
    Furthermore wait_if_global_read_lock() checks if the current thread
690
413
    has the global read lock and refuses the operation with
691
414
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
692
415
  */
693
 
  if ((error=wait_if_global_read_lock(thd,0,1)))
694
 
    goto exit2;
695
 
 
696
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
697
 
 
698
 
  /* 
699
 
     Recreate db options file: /dbpath/.db.opt
700
 
     We pass MY_DB_OPT_FILE as "extension" to avoid
701
 
     "table name to file name" encoding.
702
 
  */
703
 
  build_table_filename(path, sizeof(path), db, "", MY_DB_OPT_FILE, 0);
704
 
  if ((error=write_db_opt(thd, path, db, create_info)))
 
416
  if ((error=wait_if_global_read_lock(session,0,1)))
705
417
    goto exit;
706
418
 
 
419
  pthread_mutex_lock(&LOCK_drizzleclient_create_db);
 
420
 
707
421
  /* Change options if current database is being altered. */
708
 
 
709
 
  if (thd->db && !strcmp(thd->db,db))
710
 
  {
711
 
    thd->db_charset= create_info->default_table_charset ?
 
422
  path_len= build_table_filename(path, sizeof(path), db, "", "", 0);
 
423
  path[path_len-1]= 0;                    // Remove last '/' from path
 
424
 
 
425
  error= write_schema_file(session, path, db, create_info);
 
426
  if (error && error != EEXIST)
 
427
  {
 
428
    /* TODO: find some witty way of getting back an error message */
 
429
    pthread_mutex_unlock(&LOCK_drizzleclient_create_db);
 
430
    goto exit;
 
431
  }
 
432
 
 
433
  if (session->db && !strcmp(session->db,db))
 
434
  {
 
435
    session->db_charset= create_info->default_table_charset ?
712
436
                     create_info->default_table_charset :
713
 
                     thd->variables.collation_server;
714
 
    thd->variables.collation_database= thd->db_charset;
715
 
  }
716
 
 
717
 
  if (mysql_bin_log.is_open())
718
 
  {
719
 
    Query_log_event qinfo(thd, thd->query, thd->query_length, 0,
720
 
                          /* suppress_use */ true);
721
 
 
722
 
    /*
723
 
      Write should use the database being created as the "current
724
 
      database" and not the threads current database, which is the
725
 
      default.
726
 
    */
727
 
    qinfo.db     = db;
728
 
    qinfo.db_len = strlen(db);
729
 
 
730
 
    thd->clear_error();
731
 
    /* These DDL methods and logging protected with LOCK_mysql_create_db */
732
 
    mysql_bin_log.write(&qinfo);
733
 
  }
734
 
  my_ok(thd, result);
735
 
 
 
437
                     session->variables.collation_server;
 
438
    session->variables.collation_database= session->db_charset;
 
439
  }
 
440
 
 
441
  (void)replicator_statement(session, session->query, session->query_length);
 
442
  session->my_ok(result);
 
443
 
 
444
  pthread_mutex_unlock(&LOCK_drizzleclient_create_db);
 
445
  start_waiting_global_read_lock(session);
736
446
exit:
737
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
738
 
  start_waiting_global_read_lock(thd);
739
 
exit2:
740
447
  return(error);
741
448
}
742
449
 
746
453
 
747
454
  SYNOPSIS
748
455
    mysql_rm_db()
749
 
    thd                 Thread handle
 
456
    session                     Thread handle
750
457
    db                  Database name in the case given by user
751
458
                        It's already validated and set to lower case
752
459
                        (if needed) when we come here
758
465
    ERROR Error
759
466
*/
760
467
 
761
 
bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
 
468
bool mysql_rm_db(Session *session,char *db,bool if_exists, bool silent)
762
469
{
763
470
  long deleted=0;
764
471
  int error= false;
769
476
 
770
477
  if (db && (strcmp(db, "information_schema") == 0))
771
478
  {
772
 
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
 
479
    my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
773
480
    return(true);
774
481
  }
775
482
 
776
483
  /*
777
484
    Do not drop database if another thread is holding read lock.
778
 
    Wait for global read lock before acquiring LOCK_mysql_create_db.
 
485
    Wait for global read lock before acquiring LOCK_drizzleclient_create_db.
779
486
    After wait_if_global_read_lock() we have protection against another
780
 
    global read lock. If we would acquire LOCK_mysql_create_db first,
 
487
    global read lock. If we would acquire LOCK_drizzleclient_create_db first,
781
488
    another thread could step in and get the global read lock before we
782
489
    reach wait_if_global_read_lock(). If this thread tries the same as we
783
 
    (admin a db), it would then go and wait on LOCK_mysql_create_db...
 
490
    (admin a db), it would then go and wait on LOCK_drizzleclient_create_db...
784
491
    Furthermore wait_if_global_read_lock() checks if the current thread
785
492
    has the global read lock and refuses the operation with
786
493
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
787
494
  */
788
 
  if (wait_if_global_read_lock(thd, 0, 1))
 
495
  if (wait_if_global_read_lock(session, 0, 1))
789
496
  {
790
497
    error= -1;
791
498
    goto exit2;
792
499
  }
793
500
 
794
 
  pthread_mutex_lock(&LOCK_mysql_create_db);
795
 
 
796
 
  /*
797
 
    This statement will be replicated as a statement, even when using
798
 
    row-based replication. The flag will be reset at the end of the
799
 
    statement.
800
 
  */
801
 
  thd->clear_current_stmt_binlog_row_based();
 
501
  pthread_mutex_lock(&LOCK_drizzleclient_create_db);
802
502
 
803
503
  length= build_table_filename(path, sizeof(path), db, "", "", 0);
804
 
  my_stpcpy(path+length, MY_DB_OPT_FILE);               // Append db option file name
805
 
  del_dbopt(path);                              // Remove dboption hash entry
 
504
  strcpy(path+length, MY_DB_OPT_FILE);         // Append db option file name
 
505
  unlink(path);
806
506
  path[length]= '\0';                           // Remove file name
807
507
 
808
508
  /* See if the directory exists */
815
515
      goto exit;
816
516
    }
817
517
    else
818
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
518
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
819
519
                          ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS), db);
820
520
  }
821
521
  else
824
524
    remove_db_from_cache(db);
825
525
    pthread_mutex_unlock(&LOCK_open);
826
526
 
827
 
    
 
527
 
828
528
    error= -1;
829
 
    if ((deleted= mysql_rm_known_files(thd, dirp, db, path, 0,
 
529
    if ((deleted= mysql_rm_known_files(session, dirp, db, path, 0,
830
530
                                       &dropped_tables)) >= 0)
831
531
    {
832
532
      ha_drop_database(path);
837
537
  {
838
538
    const char *query;
839
539
    uint32_t query_length;
840
 
    if (!thd->query)
 
540
    if (!session->query)
841
541
    {
842
542
      /* The client used the old obsolete mysql_drop_db() call */
843
543
      query= path;
844
 
      query_length= (uint) (strxmov(path, "drop database `", db, "`",
845
 
                                     NULL) - path);
 
544
      query_length= sprintf(path, "drop database `%s`", db);
846
545
    }
847
546
    else
848
547
    {
849
 
      query =thd->query;
850
 
      query_length= thd->query_length;
851
 
    }
852
 
    if (mysql_bin_log.is_open())
853
 
    {
854
 
      Query_log_event qinfo(thd, query, query_length, 0, 
855
 
                            /* suppress_use */ true);
856
 
      /*
857
 
        Write should use the database being created as the "current
858
 
        database" and not the threads current database, which is the
859
 
        default.
860
 
      */
861
 
      qinfo.db     = db;
862
 
      qinfo.db_len = strlen(db);
863
 
 
864
 
      thd->clear_error();
865
 
      /* These DDL methods and logging protected with LOCK_mysql_create_db */
866
 
      mysql_bin_log.write(&qinfo);
867
 
    }
868
 
    thd->clear_error();
869
 
    thd->server_status|= SERVER_STATUS_DB_DROPPED;
870
 
    my_ok(thd, (uint32_t) deleted);
871
 
    thd->server_status&= ~SERVER_STATUS_DB_DROPPED;
 
548
      query= session->query;
 
549
      query_length= session->query_length;
 
550
    }
 
551
    (void)replicator_statement(session, session->query, session->query_length);
 
552
    session->clear_error();
 
553
    session->server_status|= SERVER_STATUS_DB_DROPPED;
 
554
    session->my_ok((uint32_t) deleted);
 
555
    session->server_status&= ~SERVER_STATUS_DB_DROPPED;
872
556
  }
873
 
  else if (mysql_bin_log.is_open())
 
557
  else
874
558
  {
875
559
    char *query, *query_pos, *query_end, *query_data_start;
876
560
    TableList *tbl;
877
561
    uint32_t db_len;
878
562
 
879
 
    if (!(query= (char*) thd->alloc(MAX_DROP_TABLE_Q_LEN)))
 
563
    if (!(query= (char*) session->alloc(MAX_DROP_TABLE_Q_LEN)))
880
564
      goto exit; /* not much else we can do */
881
 
    query_pos= query_data_start= my_stpcpy(query,"drop table ");
 
565
    query_pos= query_data_start= strcpy(query,"drop table ")+11;
882
566
    query_end= query + MAX_DROP_TABLE_Q_LEN;
883
567
    db_len= strlen(db);
884
568
 
890
574
      tbl_name_len= strlen(tbl->table_name) + 3;
891
575
      if (query_pos + tbl_name_len + 1 >= query_end)
892
576
      {
893
 
        /* These DDL methods and logging protected with LOCK_mysql_create_db */
894
 
        write_to_binlog(thd, query, query_pos -1 - query, db, db_len);
 
577
        /* These DDL methods and logging protected with LOCK_drizzleclient_create_db */
 
578
        write_to_binlog(session, query, query_pos -1 - query, db, db_len);
895
579
        query_pos= query_data_start;
896
580
      }
897
581
 
898
582
      *query_pos++ = '`';
899
 
      query_pos= my_stpcpy(query_pos,tbl->table_name);
 
583
      query_pos= strcpy(query_pos,tbl->table_name) + (tbl_name_len-3);
900
584
      *query_pos++ = '`';
901
585
      *query_pos++ = ',';
902
586
    }
903
587
 
904
588
    if (query_pos != query_data_start)
905
589
    {
906
 
      /* These DDL methods and logging protected with LOCK_mysql_create_db */
907
 
      write_to_binlog(thd, query, query_pos -1 - query, db, db_len);
 
590
      /* These DDL methods and logging protected with LOCK_drizzleclient_create_db */
 
591
      write_to_binlog(session, query, query_pos -1 - query, db, db_len);
908
592
    }
909
593
  }
910
594
 
912
596
  /*
913
597
    If this database was the client's selected database, we silently
914
598
    change the client's selected database to nothing (to have an empty
915
 
    SELECT DATABASE() in the future). For this we free() thd->db and set
 
599
    SELECT DATABASE() in the future). For this we free() session->db and set
916
600
    it to 0.
917
601
  */
918
 
  if (thd->db && !strcmp(thd->db, db))
919
 
    mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
920
 
  pthread_mutex_unlock(&LOCK_mysql_create_db);
921
 
  start_waiting_global_read_lock(thd);
 
602
  if (session->db && !strcmp(session->db, db))
 
603
    mysql_change_db_impl(session, NULL, session->variables.collation_server);
 
604
  pthread_mutex_unlock(&LOCK_drizzleclient_create_db);
 
605
  start_waiting_global_read_lock(session);
922
606
exit2:
923
607
  return(error);
924
608
}
925
609
 
926
610
/*
927
611
  Removes files with known extensions plus.
928
 
  thd MUST be set when calling this function!
 
612
  session MUST be set when calling this function!
929
613
*/
930
614
 
931
 
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
 
615
static long mysql_rm_known_files(Session *session, MY_DIR *dirp, const char *db,
932
616
                                 const char *org_path, uint32_t level,
933
617
                                 TableList **dropped_tables)
934
618
{
940
624
  tot_list_next= &tot_list;
941
625
 
942
626
  for (uint32_t idx=0 ;
943
 
       idx < (uint) dirp->number_off_files && !thd->killed ;
 
627
       idx < (uint) dirp->number_off_files && !session->killed ;
944
628
       idx++)
945
629
  {
946
630
    FILEINFO *file=dirp->dir_entry+idx;
955
639
      extension= strchr(file->name, '\0');
956
640
    if (find_type(extension, &deletable_extentions,1+2) <= 0)
957
641
    {
958
 
      if (find_type(extension, ha_known_exts(),1+2) <= 0)
959
 
        found_other_files++;
 
642
      /*
 
643
        ass ass ass.
 
644
 
 
645
        strange checking for magic extensions that are then deleted if
 
646
        not reg_ext (i.e. .frm).
 
647
 
 
648
        and (previously) we'd err out on drop database if files not matching
 
649
        engine ha_known_exts() or deletable_extensions were present.
 
650
 
 
651
        presumably this was to avoid deleting other user data... except if that
 
652
        data happened to be in files ending in .BAK, .opt or .TMD. *fun*
 
653
       */
 
654
      find_type(extension, ha_known_exts(),1+2);
960
655
      continue;
961
656
    }
962
657
    /* just for safety we use files_charset_info */
963
658
    if (db && !my_strcasecmp(files_charset_info,
964
659
                             extension, reg_ext))
965
660
    {
 
661
      uint32_t db_len= strlen(db);
 
662
 
966
663
      /* Drop the table nicely */
967
664
      *extension= 0;                    // Remove extension
968
665
      TableList *table_list=(TableList*)
969
 
                              thd->calloc(sizeof(*table_list) + 
970
 
                                          strlen(db) + 1 +
971
 
                                          MYSQL50_TABLE_NAME_PREFIX_LENGTH + 
 
666
                              session->calloc(sizeof(*table_list) +
 
667
                                          db_len + 1 +
 
668
                                          MYSQL50_TABLE_NAME_PREFIX_LENGTH +
972
669
                                          strlen(file->name) + 1);
973
670
 
974
671
      if (!table_list)
975
672
        goto err;
976
673
      table_list->db= (char*) (table_list+1);
977
 
      table_list->table_name= my_stpcpy(table_list->db, db) + 1;
 
674
      table_list->table_name= strcpy(table_list->db, db) + db_len + 1;
978
675
      filename_to_tablename(file->name, table_list->table_name,
979
676
                            MYSQL50_TABLE_NAME_PREFIX_LENGTH +
980
677
                            strlen(file->name) + 1);
981
678
      table_list->alias= table_list->table_name;        // If lower_case_table_names=2
982
 
      table_list->internal_tmp_table= is_prefix(file->name, tmp_file_prefix);
 
679
      table_list->internal_tmp_table= is_prefix(file->name, TMP_FILE_PREFIX);
983
680
      /* Link into list */
984
681
      (*tot_list_next)= table_list;
985
682
      tot_list_next= &table_list->next_local;
987
684
    }
988
685
    else
989
686
    {
990
 
      strxmov(filePath, org_path, "/", file->name, NULL);
 
687
      sprintf(filePath, "%s/%s", org_path, file->name);
991
688
      if (my_delete_with_symlink(filePath,MYF(MY_WME)))
992
689
      {
993
690
        goto err;
994
691
      }
995
692
    }
996
693
  }
997
 
  if (thd->killed ||
998
 
      (tot_list && mysql_rm_table_part2(thd, tot_list, 1, 0, 1, 1)))
 
694
  if (session->killed ||
 
695
      (tot_list && mysql_rm_table_part2(session, tot_list, 1, 0, 1)))
999
696
    goto err;
1000
697
 
1001
 
  my_dirend(dirp);  
1002
 
  
 
698
  my_dirend(dirp);
 
699
 
1003
700
  if (dropped_tables)
1004
701
    *dropped_tables= tot_list;
1005
 
  
 
702
 
1006
703
  /*
1007
704
    If the directory is a symbolic link, remove the link first, then
1008
705
    remove the directory the symbolic link pointed at
1082
779
/**
1083
780
  @brief Internal implementation: switch current database to a valid one.
1084
781
 
1085
 
  @param thd            Thread context.
 
782
  @param session            Thread context.
1086
783
  @param new_db_name    Name of the database to switch to. The function will
1087
784
                        take ownership of the name (the caller must not free
1088
785
                        the allocated memory). If the name is NULL, we're
1090
787
  @param new_db_charset Character set of the new database.
1091
788
*/
1092
789
 
1093
 
static void mysql_change_db_impl(THD *thd,
 
790
static void mysql_change_db_impl(Session *session,
1094
791
                                 LEX_STRING *new_db_name,
1095
792
                                 const CHARSET_INFO * const new_db_charset)
1096
793
{
1097
 
  /* 1. Change current database in THD. */
 
794
  /* 1. Change current database in Session. */
1098
795
 
1099
796
  if (new_db_name == NULL)
1100
797
  {
1101
798
    /*
1102
 
      THD::set_db() does all the job -- it frees previous database name and
 
799
      Session::set_db() does all the job -- it frees previous database name and
1103
800
      sets the new one.
1104
801
    */
1105
802
 
1106
 
    thd->set_db(NULL, 0);
 
803
    session->set_db(NULL, 0);
1107
804
  }
1108
 
  else if (new_db_name == &INFORMATION_SCHEMA_NAME)
 
805
  else if (my_strcasecmp(system_charset_info, new_db_name->str,
 
806
                         INFORMATION_SCHEMA_NAME.c_str()) == 0)
1109
807
  {
1110
808
    /*
1111
 
      Here we must use THD::set_db(), because we want to copy
 
809
      Here we must use Session::set_db(), because we want to copy
1112
810
      INFORMATION_SCHEMA_NAME constant.
1113
811
    */
1114
812
 
1115
 
    thd->set_db(INFORMATION_SCHEMA_NAME.str, INFORMATION_SCHEMA_NAME.length);
 
813
    session->set_db(INFORMATION_SCHEMA_NAME.c_str(),
 
814
                    INFORMATION_SCHEMA_NAME.length());
1116
815
  }
1117
816
  else
1118
817
  {
1119
818
    /*
1120
 
      Here we already have a copy of database name to be used in THD. So,
1121
 
      we just call THD::reset_db(). Since THD::reset_db() does not releases
 
819
      Here we already have a copy of database name to be used in Session. So,
 
820
      we just call Session::reset_db(). Since Session::reset_db() does not releases
1122
821
      the previous database name, we should do it explicitly.
1123
822
    */
1124
823
 
1125
 
    if (thd->db)
1126
 
      free(thd->db);
 
824
    if (session->db)
 
825
      free(session->db);
1127
826
 
1128
 
    thd->reset_db(new_db_name->str, new_db_name->length);
 
827
    session->reset_db(new_db_name->str, new_db_name->length);
1129
828
  }
1130
829
 
1131
830
  /* 3. Update db-charset environment variables. */
1132
831
 
1133
 
  thd->db_charset= new_db_charset;
1134
 
  thd->variables.collation_database= new_db_charset;
 
832
  session->db_charset= new_db_charset;
 
833
  session->variables.collation_database= new_db_charset;
1135
834
}
1136
835
 
1137
836
 
1139
838
/**
1140
839
  Backup the current database name before switch.
1141
840
 
1142
 
  @param[in]      thd             thread handle
 
841
  @param[in]      session             thread handle
1143
842
  @param[in, out] saved_db_name   IN: "str" points to a buffer where to store
1144
843
                                  the old database name, "length" contains the
1145
844
                                  buffer size
1151
850
                                  "length" is set to 0.
1152
851
*/
1153
852
 
1154
 
static void backup_current_db_name(THD *thd,
 
853
static void backup_current_db_name(Session *session,
1155
854
                                   LEX_STRING *saved_db_name)
1156
855
{
1157
 
  if (!thd->db)
 
856
  if (!session->db)
1158
857
  {
1159
858
    /* No current (default) database selected. */
1160
859
 
1163
862
  }
1164
863
  else
1165
864
  {
1166
 
    strmake(saved_db_name->str, thd->db, saved_db_name->length - 1);
1167
 
    saved_db_name->length= thd->db_length;
 
865
    strncpy(saved_db_name->str, session->db, saved_db_name->length - 1);
 
866
    saved_db_name->length= session->db_length;
1168
867
  }
1169
868
}
1170
869
 
1196
895
/**
1197
896
  @brief Change the current database and its attributes unconditionally.
1198
897
 
1199
 
  @param thd          thread handle
 
898
  @param session          thread handle
1200
899
  @param new_db_name  database name
1201
900
  @param force_switch if force_switch is false, then the operation will fail if
1202
901
 
1222
921
                          @@collation_server, but the operation will fail;
1223
922
 
1224
923
                        - user privileges will not be checked
1225
 
                          (THD::db_access however is updated);
 
924
                          (Session::db_access however is updated);
1226
925
 
1227
926
                          TODO: is this really the intention?
1228
927
                                (see sp-security.test).
1235
934
  @details The function checks that the database name corresponds to a
1236
935
  valid and existent database, checks access rights and changes the current
1237
936
  database with database attributes (@@collation_database session variable,
1238
 
  THD::db_access).
 
937
  Session::db_access).
1239
938
 
1240
939
  This function is not the only way to switch the database that is
1241
940
  currently employed. When the replication slave thread switches the
1242
 
  database before executing a query, it calls thd->set_db directly.
 
941
  database before executing a query, it calls session->set_db directly.
1243
942
  However, if the query, in turn, uses a stored routine, the stored routine
1244
943
  will use this function, even if it's run on the slave.
1245
944
 
1255
954
    @retval true  Error
1256
955
*/
1257
956
 
1258
 
bool mysql_change_db(THD *thd, const LEX_STRING *new_db_name, bool force_switch)
 
957
bool mysql_change_db(Session *session, const LEX_STRING *new_db_name, bool force_switch)
1259
958
{
1260
959
  LEX_STRING new_db_file_name;
1261
960
  const CHARSET_INFO *db_default_cl;
1275
974
        new_db_name->length == 0.
1276
975
      */
1277
976
 
1278
 
      mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
 
977
      mysql_change_db_impl(session, NULL, session->variables.collation_server);
1279
978
 
1280
979
      return(false);
1281
980
    }
1288
987
  }
1289
988
 
1290
989
  if (my_strcasecmp(system_charset_info, new_db_name->str,
1291
 
                    INFORMATION_SCHEMA_NAME.str) == 0)
 
990
                    INFORMATION_SCHEMA_NAME.c_str()) == 0)
1292
991
  {
1293
992
    /* Switch the current database to INFORMATION_SCHEMA. */
1294
 
 
1295
 
    mysql_change_db_impl(thd, &INFORMATION_SCHEMA_NAME, system_charset_info);
 
993
    /* const_cast<> is safe here: mysql_change_db_impl does a copy */
 
994
    LEX_STRING is_name= { const_cast<char *>(INFORMATION_SCHEMA_NAME.c_str()),
 
995
                          INFORMATION_SCHEMA_NAME.length() };
 
996
    mysql_change_db_impl(session, &is_name, system_charset_info);
1296
997
 
1297
998
    return(false);
1298
999
  }
1304
1005
    TODO: fix check_db_name().
1305
1006
  */
1306
1007
 
1307
 
  new_db_file_name.str= my_strndup(new_db_name->str, new_db_name->length,
1308
 
                                   MYF(MY_WME));
1309
1008
  new_db_file_name.length= new_db_name->length;
1310
 
 
 
1009
  new_db_file_name.str= (char *)malloc(new_db_name->length + 1);
1311
1010
  if (new_db_file_name.str == NULL)
1312
1011
    return(true);                             /* the error is set */
 
1012
  memcpy(new_db_file_name.str, new_db_name->str, new_db_name->length);
 
1013
  new_db_file_name.str[new_db_name->length]= 0;
 
1014
 
1313
1015
 
1314
1016
  /*
1315
1017
    NOTE: if check_db_name() fails, we should throw an error in any case,
1326
1028
    free(new_db_file_name.str);
1327
1029
 
1328
1030
    if (force_switch)
1329
 
      mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
 
1031
      mysql_change_db_impl(session, NULL, session->variables.collation_server);
1330
1032
 
1331
1033
    return(true);
1332
1034
  }
1337
1039
    {
1338
1040
      /* Throw a warning and free new_db_file_name. */
1339
1041
 
1340
 
      push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
1042
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1341
1043
                          ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR),
1342
1044
                          new_db_file_name.str);
1343
1045
 
1345
1047
 
1346
1048
      /* Change db to NULL. */
1347
1049
 
1348
 
      mysql_change_db_impl(thd, NULL, thd->variables.collation_server);
 
1050
      mysql_change_db_impl(session, NULL, session->variables.collation_server);
1349
1051
 
1350
1052
      /* The operation succeed. */
1351
1053
 
1365
1067
  }
1366
1068
 
1367
1069
  /*
1368
 
    NOTE: in mysql_change_db_impl() new_db_file_name is assigned to THD
1369
 
    attributes and will be freed in THD::~THD().
 
1070
    NOTE: in mysql_change_db_impl() new_db_file_name is assigned to Session
 
1071
    attributes and will be freed in Session::~Session().
1370
1072
  */
1371
1073
 
1372
 
  db_default_cl= get_default_db_collation(thd, new_db_file_name.str);
 
1074
  db_default_cl= get_default_db_collation(session, new_db_file_name.str);
1373
1075
 
1374
 
  mysql_change_db_impl(thd, &new_db_file_name, db_default_cl);
 
1076
  mysql_change_db_impl(session, &new_db_file_name, db_default_cl);
1375
1077
 
1376
1078
  return(false);
1377
1079
}
1380
1082
/**
1381
1083
  Change the current database and its attributes if needed.
1382
1084
 
1383
 
  @param          thd             thread handle
 
1085
  @param          session             thread handle
1384
1086
  @param          new_db_name     database name
1385
1087
  @param[in, out] saved_db_name   IN: "str" points to a buffer where to store
1386
1088
                                  the old database name, "length" contains the
1397
1099
                                  the function suceeded)
1398
1100
*/
1399
1101
 
1400
 
bool mysql_opt_change_db(THD *thd,
 
1102
bool mysql_opt_change_db(Session *session,
1401
1103
                         const LEX_STRING *new_db_name,
1402
1104
                         LEX_STRING *saved_db_name,
1403
1105
                         bool force_switch,
1404
1106
                         bool *cur_db_changed)
1405
1107
{
1406
 
  *cur_db_changed= !cmp_db_names(thd->db, new_db_name->str);
 
1108
  *cur_db_changed= !cmp_db_names(session->db, new_db_name->str);
1407
1109
 
1408
1110
  if (!*cur_db_changed)
1409
1111
    return false;
1410
1112
 
1411
 
  backup_current_db_name(thd, saved_db_name);
 
1113
  backup_current_db_name(session, saved_db_name);
1412
1114
 
1413
 
  return mysql_change_db(thd, new_db_name, force_switch);
 
1115
  return mysql_change_db(session, new_db_name, force_switch);
1414
1116
}
1415
1117
 
1416
1118