~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/db.cc

Removing global errbuff and cleaning up two remaining instances that referenced it.

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