~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/db.cc

  • Committer: Andrew Hutchings
  • Date: 2011-01-04 11:36:01 UTC
  • mto: This revision was merged to the branch mainline in revision 2057.
  • Revision ID: andrew@linuxjedi.co.uk-20110104113601-diiveyfl32dgaa6f
Refix using placement new for join code, vector for join cache buffer.
Also refix a bug in COND_CMP properly

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 "config.h"
19
19
 
20
20
#include <fcntl.h>
21
21
#include <sys/stat.h>
25
25
#include <string>
26
26
#include <fstream>
27
27
 
28
 
#include <drizzled/error.h>
 
28
#include <drizzled/message/schema.pb.h>
 
29
#include "drizzled/error.h"
29
30
#include <drizzled/gettext.h>
30
31
#include <drizzled/my_hash.h>
31
 
#include <drizzled/internal/m_string.h>
 
32
#include "drizzled/internal/m_string.h"
32
33
#include <drizzled/session.h>
33
 
#include <drizzled/schema.h>
 
34
#include <drizzled/db.h>
34
35
#include <drizzled/sql_base.h>
35
36
#include <drizzled/lock.h>
36
37
#include <drizzled/errmsg_print.h>
37
38
#include <drizzled/transaction_services.h>
38
39
#include <drizzled/message/schema.pb.h>
39
 
#include <drizzled/sql_table.h>
40
 
#include <drizzled/plugin/storage_engine.h>
41
 
#include <drizzled/plugin/authorization.h>
42
 
#include <drizzled/global_charset_info.h>
43
 
#include <drizzled/pthread_globals.h>
44
 
#include <drizzled/charset.h>
45
 
#include <drizzled/internal/my_sys.h>
 
40
#include "drizzled/sql_table.h"
 
41
#include "drizzled/plugin/storage_engine.h"
 
42
#include "drizzled/plugin/authorization.h"
 
43
#include "drizzled/global_charset_info.h"
 
44
#include "drizzled/pthread_globals.h"
 
45
#include "drizzled/charset.h"
46
46
 
47
47
#include <boost/thread/mutex.hpp>
48
48
 
 
49
boost::mutex LOCK_create_db;
 
50
 
 
51
#include "drizzled/internal/my_sys.h"
 
52
 
49
53
#define MAX_DROP_TABLE_Q_LEN      1024
50
54
 
51
55
using namespace std;
53
57
namespace drizzled
54
58
{
55
59
 
56
 
namespace schema
57
 
{
58
 
 
59
 
static void change_db_impl(Session &session);
60
 
static void change_db_impl(Session &session, identifier::Schema &schema_identifier);
 
60
static long drop_tables_via_filenames(Session *session,
 
61
                                 SchemaIdentifier &schema_identifier,
 
62
                                 TableIdentifier::vector &dropped_tables);
 
63
static void change_db_impl(Session *session);
 
64
static void change_db_impl(Session *session, SchemaIdentifier &schema_identifier);
61
65
 
62
66
/*
63
67
  Create a database
80
84
 
81
85
*/
82
86
 
83
 
bool create(Session &session, const message::Schema &schema_message, const bool is_if_not_exists)
 
87
bool create_db(Session *session, const message::Schema &schema_message, const bool is_if_not_exists)
84
88
{
85
89
  TransactionServices &transaction_services= TransactionServices::singleton();
86
90
  bool error= false;
87
91
 
88
92
  /*
89
93
    Do not create database if another thread is holding read lock.
90
 
    Wait for global read lock before acquiring session->catalog()->schemaLock().
 
94
    Wait for global read lock before acquiring LOCK_create_db.
91
95
    After wait_if_global_read_lock() we have protection against another
92
 
    global read lock. If we would acquire session->catalog()->schemaLock() first,
 
96
    global read lock. If we would acquire LOCK_create_db first,
93
97
    another thread could step in and get the global read lock before we
94
98
    reach wait_if_global_read_lock(). If this thread tries the same as we
95
 
    (admin a db), it would then go and wait on session->catalog()->schemaLock()...
 
99
    (admin a db), it would then go and wait on LOCK_create_db...
96
100
    Furthermore wait_if_global_read_lock() checks if the current thread
97
101
    has the global read lock and refuses the operation with
98
102
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
99
103
  */
100
 
  if (session.wait_if_global_read_lock(false, true))
 
104
  if (session->wait_if_global_read_lock(false, true))
101
105
  {
102
106
    return false;
103
107
  }
107
111
 
108
112
  // @todo push this lock down into the engine
109
113
  {
110
 
    boost::mutex::scoped_lock scopedLock(session.catalog().schemaLock());
 
114
    boost::mutex::scoped_lock scopedLock(LOCK_create_db);
111
115
 
112
116
    // Check to see if it exists already.  
113
 
    identifier::Schema schema_identifier(schema_message.name());
 
117
    SchemaIdentifier schema_identifier(schema_message.name());
114
118
    if (plugin::StorageEngine::doesSchemaExist(schema_identifier))
115
119
    {
116
120
      if (not is_if_not_exists)
117
121
      {
118
 
        my_error(ER_DB_CREATE_EXISTS, schema_identifier);
 
122
        my_error(ER_DB_CREATE_EXISTS, MYF(0), schema_message.name().c_str());
119
123
        error= true;
120
124
      }
121
125
      else
122
126
      {
123
 
        push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
127
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
124
128
                            ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
125
129
                            schema_message.name().c_str());
126
 
        session.my_ok();
 
130
        session->my_ok();
127
131
      }
128
132
    }
129
133
    else if (not plugin::StorageEngine::createSchema(schema_message)) // Try to create it 
134
138
    else // Created !
135
139
    {
136
140
      transaction_services.createSchema(session, schema_message);
137
 
      session.my_ok(1);
 
141
      session->my_ok(1);
138
142
    }
139
143
  }
140
 
  session.startWaitingGlobalReadLock();
 
144
  session->startWaitingGlobalReadLock();
141
145
 
142
146
  return error;
143
147
}
145
149
 
146
150
/* db-name is already validated when we come here */
147
151
 
148
 
bool alter(Session &session,
149
 
           const message::Schema &schema_message,
150
 
           const message::Schema &original_schema)
 
152
bool alter_db(Session *session, const message::Schema &schema_message)
151
153
{
152
154
  TransactionServices &transaction_services= TransactionServices::singleton();
153
155
 
154
156
  /*
155
157
    Do not alter database if another thread is holding read lock.
156
 
    Wait for global read lock before acquiring session->catalog()->schemaLock().
 
158
    Wait for global read lock before acquiring LOCK_create_db.
157
159
    After wait_if_global_read_lock() we have protection against another
158
 
    global read lock. If we would acquire session->catalog()->schemaLock() first,
 
160
    global read lock. If we would acquire LOCK_create_db first,
159
161
    another thread could step in and get the global read lock before we
160
162
    reach wait_if_global_read_lock(). If this thread tries the same as we
161
 
    (admin a db), it would then go and wait on session->catalog()->schemaLock()...
 
163
    (admin a db), it would then go and wait on LOCK_create_db...
162
164
    Furthermore wait_if_global_read_lock() checks if the current thread
163
165
    has the global read lock and refuses the operation with
164
166
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
165
167
  */
166
 
  if ((session.wait_if_global_read_lock(false, true)))
 
168
  if ((session->wait_if_global_read_lock(false, true)))
167
169
    return false;
168
170
 
169
171
  bool success;
170
172
  {
171
 
    boost::mutex::scoped_lock scopedLock(session.catalog().schemaLock());
 
173
    boost::mutex::scoped_lock scopedLock(LOCK_create_db);
172
174
 
173
 
    identifier::Schema schema_idenifier(schema_message.name());
 
175
    SchemaIdentifier schema_idenifier(schema_message.name());
174
176
    if (not plugin::StorageEngine::doesSchemaExist(schema_idenifier))
175
177
    {
176
 
      my_error(ER_SCHEMA_DOES_NOT_EXIST, schema_idenifier);
 
178
      my_error(ER_SCHEMA_DOES_NOT_EXIST, MYF(0), schema_message.name().c_str());
177
179
      return false;
178
180
    }
179
181
 
182
184
 
183
185
    if (success)
184
186
    {
185
 
      transaction_services.alterSchema(session, original_schema, schema_message);
186
 
      session.my_ok(1);
 
187
      transaction_services.rawStatement(session, *session->getQueryString());
 
188
      session->my_ok(1);
187
189
    }
188
190
    else
189
191
    {
190
 
      my_error(ER_ALTER_SCHEMA, schema_idenifier);
 
192
      my_error(ER_ALTER_SCHEMA, MYF(0), schema_message.name().c_str());
191
193
    }
192
194
  }
193
 
  session.startWaitingGlobalReadLock();
 
195
  session->startWaitingGlobalReadLock();
194
196
 
195
197
  return success;
196
198
}
213
215
    ERROR Error
214
216
*/
215
217
 
216
 
bool drop(Session &session, identifier::Schema &schema_identifier, const bool if_exists)
 
218
bool rm_db(Session *session, SchemaIdentifier &schema_identifier, const bool if_exists)
217
219
{
218
 
  bool error= false;
 
220
  long deleted=0;
 
221
  int error= false;
 
222
  TableIdentifier::vector dropped_tables;
 
223
  message::Schema schema_proto;
219
224
 
220
225
  /*
221
226
    Do not drop database if another thread is holding read lock.
222
 
    Wait for global read lock before acquiring session->catalog()->schemaLock().
 
227
    Wait for global read lock before acquiring LOCK_create_db.
223
228
    After wait_if_global_read_lock() we have protection against another
224
 
    global read lock. If we would acquire session->catalog()->schemaLock() first,
 
229
    global read lock. If we would acquire LOCK_create_db first,
225
230
    another thread could step in and get the global read lock before we
226
231
    reach wait_if_global_read_lock(). If this thread tries the same as we
227
 
    (admin a db), it would then go and wait on session->catalog()->schemaLock()...
 
232
    (admin a db), it would then go and wait on LOCK_create_db...
228
233
    Furthermore wait_if_global_read_lock() checks if the current thread
229
234
    has the global read lock and refuses the operation with
230
235
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
231
236
  */
232
 
  if (session.wait_if_global_read_lock(false, true))
233
 
  {
234
 
    return true;
235
 
  }
236
 
 
237
 
  do
238
 
  {
239
 
    boost::mutex::scoped_lock scopedLock(session.catalog().schemaLock());
240
 
    message::schema::shared_ptr message= plugin::StorageEngine::getSchemaDefinition(schema_identifier);
 
237
  if (session->wait_if_global_read_lock(false, true))
 
238
  {
 
239
    return -1;
 
240
  }
 
241
 
 
242
  // Lets delete the temporary tables first outside of locks.  
 
243
  set<string> set_of_names;
 
244
  session->doGetTableNames(schema_identifier, set_of_names);
 
245
 
 
246
  for (set<string>::iterator iter= set_of_names.begin(); iter != set_of_names.end(); iter++)
 
247
  {
 
248
    TableIdentifier identifier(schema_identifier, *iter, message::Table::TEMPORARY);
 
249
    Table *table= session->find_temporary_table(identifier);
 
250
    session->close_temporary_table(table);
 
251
  }
 
252
 
 
253
  {
 
254
    boost::mutex::scoped_lock scopedLock(LOCK_create_db);
241
255
 
242
256
    /* See if the schema exists */
243
 
    if (not message)
 
257
    if (not plugin::StorageEngine::doesSchemaExist(schema_identifier))
244
258
    {
 
259
      std::string path;
 
260
      schema_identifier.getSQLPath(path);
 
261
 
245
262
      if (if_exists)
246
263
      {
247
 
        std::string path;
248
 
        schema_identifier.getSQLPath(path);
249
 
 
250
 
        push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
264
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
251
265
                            ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS),
252
266
                            path.c_str());
253
267
      }
254
268
      else
255
269
      {
256
 
        error= true;
257
 
        my_error(ER_DB_DROP_EXISTS, schema_identifier);
258
 
        break;
259
 
      }
260
 
    }
261
 
    else
262
 
    {
263
 
      error= plugin::StorageEngine::dropSchema(session, schema_identifier, *message);
264
 
    }
265
 
 
266
 
  } while (0);
267
 
 
268
 
  /*
269
 
    If this database was the client's selected database, we silently
270
 
    change the client's selected database to nothing (to have an empty
271
 
    SELECT DATABASE() in the future). For this we free() session->db and set
272
 
    it to 0.
273
 
  */
274
 
  if (not error and schema_identifier.compare(*session.schema()))
275
 
    change_db_impl(session);
276
 
 
277
 
  session.startWaitingGlobalReadLock();
 
270
        error= -1;
 
271
        my_error(ER_DB_DROP_EXISTS, MYF(0), path.c_str());
 
272
        goto exit;
 
273
      }
 
274
    }
 
275
    else
 
276
    {
 
277
      /* After deleting database, remove all cache entries related to schema */
 
278
      table::Cache::singleton().removeSchema(schema_identifier);
 
279
 
 
280
      error= -1;
 
281
      deleted= drop_tables_via_filenames(session, schema_identifier, dropped_tables);
 
282
      if (deleted >= 0)
 
283
      {
 
284
        error= 0;
 
285
        
 
286
        /* We've already verified that the schema does exist, so safe to log it */
 
287
        TransactionServices &transaction_services= TransactionServices::singleton();
 
288
        transaction_services.dropSchema(session, schema_identifier.getSchemaName());
 
289
      }
 
290
    }
 
291
    if (deleted >= 0)
 
292
    {
 
293
      session->clear_error();
 
294
      session->server_status|= SERVER_STATUS_DB_DROPPED;
 
295
      session->my_ok((uint32_t) deleted);
 
296
      session->server_status&= ~SERVER_STATUS_DB_DROPPED;
 
297
    }
 
298
    else
 
299
    {
 
300
      char *query, *query_pos, *query_end, *query_data_start;
 
301
 
 
302
      if (!(query= (char*) session->alloc(MAX_DROP_TABLE_Q_LEN)))
 
303
        goto exit; /* not much else we can do */
 
304
      query_pos= query_data_start= strcpy(query,"drop table ")+11;
 
305
      query_end= query + MAX_DROP_TABLE_Q_LEN;
 
306
 
 
307
      TransactionServices &transaction_services= TransactionServices::singleton();
 
308
      for (TableIdentifier::vector::iterator it= dropped_tables.begin();
 
309
           it != dropped_tables.end();
 
310
           it++)
 
311
      {
 
312
        uint32_t tbl_name_len;
 
313
 
 
314
        /* 3 for the quotes and the comma*/
 
315
        tbl_name_len= (*it).getTableName().length() + 3;
 
316
        if (query_pos + tbl_name_len + 1 >= query_end)
 
317
        {
 
318
          /* These DDL methods and logging protected with LOCK_create_db */
 
319
          transaction_services.rawStatement(session, query);
 
320
          query_pos= query_data_start;
 
321
        }
 
322
 
 
323
        *query_pos++ = '`';
 
324
        query_pos= strcpy(query_pos, (*it).getTableName().c_str()) + (tbl_name_len-3);
 
325
        *query_pos++ = '`';
 
326
        *query_pos++ = ',';
 
327
      }
 
328
 
 
329
      if (query_pos != query_data_start)
 
330
      {
 
331
        /* These DDL methods and logging protected with LOCK_create_db */
 
332
        transaction_services.rawStatement(session, query);
 
333
      }
 
334
    }
 
335
 
 
336
exit:
 
337
    /*
 
338
      If this database was the client's selected database, we silently
 
339
      change the client's selected database to nothing (to have an empty
 
340
      SELECT DATABASE() in the future). For this we free() session->db and set
 
341
      it to 0.
 
342
    */
 
343
    if (schema_identifier.compare(*session->schema()))
 
344
      change_db_impl(session);
 
345
  }
 
346
 
 
347
  session->startWaitingGlobalReadLock();
278
348
 
279
349
  return error;
280
350
}
281
351
 
 
352
 
 
353
static int rm_table_part2(Session *session, TableList *tables)
 
354
{
 
355
  TransactionServices &transaction_services= TransactionServices::singleton();
 
356
 
 
357
  TableList *table;
 
358
  String wrong_tables;
 
359
  int error= 0;
 
360
  bool foreign_key_error= false;
 
361
 
 
362
  {
 
363
    table::Cache::singleton().mutex().lock(); /* Part 2 of rm a table */
 
364
 
 
365
    if (session->lock_table_names_exclusively(tables))
 
366
    {
 
367
      table::Cache::singleton().mutex().unlock();
 
368
      return 1;
 
369
    }
 
370
 
 
371
    /* Don't give warnings for not found errors, as we already generate notes */
 
372
    session->no_warnings_for_error= 1;
 
373
 
 
374
    for (table= tables; table; table= table->next_local)
 
375
    {
 
376
      const char *db=table->getSchemaName();
 
377
      TableIdentifier identifier(table->getSchemaName(), table->getTableName());
 
378
 
 
379
      plugin::StorageEngine *table_type;
 
380
 
 
381
      error= session->drop_temporary_table(identifier);
 
382
 
 
383
      switch (error) {
 
384
      case  0:
 
385
        // removed temporary table
 
386
        continue;
 
387
      case -1:
 
388
        error= 1;
 
389
        tables->unlock_table_names();
 
390
        table::Cache::singleton().mutex().unlock();
 
391
        session->no_warnings_for_error= 0;
 
392
 
 
393
        return(error);
 
394
      default:
 
395
        // temporary table not found
 
396
        error= 0;
 
397
      }
 
398
 
 
399
      table_type= table->getDbType();
 
400
 
 
401
      {
 
402
        Table *locked_table;
 
403
        abort_locked_tables(session, identifier);
 
404
        table::Cache::singleton().removeTable(session, identifier,
 
405
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
406
                                              RTFC_CHECK_KILLED_FLAG);
 
407
        /*
 
408
          If the table was used in lock tables, remember it so that
 
409
          unlock_table_names can free it
 
410
        */
 
411
        if ((locked_table= drop_locked_tables(session, identifier)))
 
412
          table->table= locked_table;
 
413
 
 
414
        if (session->getKilled())
 
415
        {
 
416
          error= -1;
 
417
          tables->unlock_table_names();
 
418
          table::Cache::singleton().mutex().unlock();
 
419
          session->no_warnings_for_error= 0;
 
420
 
 
421
          return(error);
 
422
        }
 
423
      }
 
424
      identifier.getPath();
 
425
 
 
426
      if (table_type == NULL && not plugin::StorageEngine::doesTableExist(*session, identifier))
 
427
      {
 
428
        // Table was not found on disk and table can't be created from engine
 
429
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
430
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
431
                            table->getTableName());
 
432
      }
 
433
      else
 
434
      {
 
435
        error= plugin::StorageEngine::dropTable(*session, identifier);
 
436
 
 
437
        /* Generate transaction event ONLY when we successfully drop */ 
 
438
        if (error == 0)
 
439
        {
 
440
          transaction_services.dropTable(session, string(db), string(table->getTableName()));
 
441
        }
 
442
 
 
443
        if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE))
 
444
        {
 
445
          error= 0;
 
446
          session->clear_error();
 
447
        }
 
448
 
 
449
        if (error == HA_ERR_ROW_IS_REFERENCED)
 
450
        {
 
451
          /* the table is referenced by a foreign key constraint */
 
452
          foreign_key_error= true;
 
453
        }
 
454
      }
 
455
 
 
456
      if (error)
 
457
      {
 
458
        if (wrong_tables.length())
 
459
          wrong_tables.append(',');
 
460
        wrong_tables.append(String(table->getTableName(),system_charset_info));
 
461
      }
 
462
    }
 
463
    /*
 
464
      It's safe to unlock table::Cache::singleton().mutex(): we have an exclusive lock
 
465
      on the table name.
 
466
    */
 
467
    table::Cache::singleton().mutex().unlock();
 
468
  }
 
469
 
 
470
  error= 0;
 
471
  if (wrong_tables.length())
 
472
  {
 
473
    if (not foreign_key_error)
 
474
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
 
475
                      wrong_tables.c_ptr());
 
476
    else
 
477
    {
 
478
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
 
479
    }
 
480
    error= 1;
 
481
  }
 
482
 
 
483
  {
 
484
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* final bit in rm table lock */
 
485
    tables->unlock_table_names();
 
486
  }
 
487
  session->no_warnings_for_error= 0;
 
488
 
 
489
  return(error);
 
490
}
 
491
 
 
492
/*
 
493
  Removes files with known extensions plus.
 
494
  session MUST be set when calling this function!
 
495
*/
 
496
 
 
497
static long drop_tables_via_filenames(Session *session,
 
498
                                      SchemaIdentifier &schema_identifier,
 
499
                                      TableIdentifier::vector &dropped_tables)
 
500
{
 
501
  long deleted= 0;
 
502
  TableList *tot_list= NULL, **tot_list_next;
 
503
 
 
504
  tot_list_next= &tot_list;
 
505
 
 
506
  plugin::StorageEngine::getIdentifiers(*session, schema_identifier, dropped_tables);
 
507
 
 
508
  for (TableIdentifier::vector::iterator it= dropped_tables.begin();
 
509
       it != dropped_tables.end();
 
510
       it++)
 
511
  {
 
512
    size_t db_len= schema_identifier.getSchemaName().size();
 
513
 
 
514
    /* Drop the table nicely */
 
515
    TableList *table_list=(TableList*)
 
516
      session->calloc(sizeof(*table_list) +
 
517
                      db_len + 1 +
 
518
                      (*it).getTableName().length() + 1);
 
519
 
 
520
    if (not table_list)
 
521
      return -1;
 
522
 
 
523
    table_list->setSchemaName((char*) (table_list+1));
 
524
    table_list->setTableName(strcpy((char*) (table_list+1), schema_identifier.getSchemaName().c_str()) + db_len + 1);
 
525
    TableIdentifier::filename_to_tablename((*it).getTableName().c_str(), const_cast<char *>(table_list->getTableName()), (*it).getTableName().size() + 1);
 
526
    table_list->alias= table_list->getTableName();  // If lower_case_table_names=2
 
527
    table_list->setInternalTmpTable((strncmp((*it).getTableName().c_str(),
 
528
                                             TMP_FILE_PREFIX,
 
529
                                             strlen(TMP_FILE_PREFIX)) == 0));
 
530
    /* Link into list */
 
531
    (*tot_list_next)= table_list;
 
532
    tot_list_next= &table_list->next_local;
 
533
    deleted++;
 
534
  }
 
535
  if (session->getKilled())
 
536
    return -1;
 
537
 
 
538
  if (tot_list)
 
539
  {
 
540
    if (rm_table_part2(session, tot_list))
 
541
      return -1;
 
542
  }
 
543
 
 
544
 
 
545
  if (not plugin::StorageEngine::dropSchema(schema_identifier))
 
546
  {
 
547
    std::string path;
 
548
    schema_identifier.getSQLPath(path);
 
549
    my_error(ER_DROP_SCHEMA, MYF(0), path.c_str());
 
550
 
 
551
    return -1;
 
552
  }
 
553
 
 
554
  return deleted;
 
555
}
 
556
 
282
557
/**
283
558
  @brief Change the current database and its attributes unconditionally.
284
559
 
341
616
    @retval true  Error
342
617
*/
343
618
 
344
 
bool change(Session &session, identifier::Schema &schema_identifier)
 
619
bool change_db(Session *session, SchemaIdentifier &schema_identifier)
345
620
{
346
621
 
347
 
  if (not plugin::Authorization::isAuthorized(*session.user(), schema_identifier))
 
622
  if (not plugin::Authorization::isAuthorized(session->user(), schema_identifier))
348
623
  {
349
624
    /* Error message is set in isAuthorized */
350
625
    return true;
351
626
  }
352
627
 
353
 
  if (not check(session, schema_identifier))
 
628
  if (not check_db_name(session, schema_identifier))
354
629
  {
355
 
    my_error(ER_WRONG_DB_NAME, schema_identifier);
 
630
    std::string path;
 
631
    schema_identifier.getSQLPath(path);
 
632
    my_error(ER_WRONG_DB_NAME, MYF(0), path.c_str());
356
633
 
357
634
    return true;
358
635
  }
359
636
 
360
637
  if (not plugin::StorageEngine::doesSchemaExist(schema_identifier))
361
638
  {
362
 
    my_error(ER_BAD_DB_ERROR, schema_identifier);
 
639
    /* Report an error and free new_db_file_name. */
 
640
    std::string path;
 
641
    schema_identifier.getSQLPath(path);
 
642
 
 
643
    my_error(ER_BAD_DB_ERROR, MYF(0), path.c_str());
363
644
 
364
645
    /* The operation failed. */
365
646
 
382
663
  @param new_db_charset Character set of the new database.
383
664
*/
384
665
 
385
 
static void change_db_impl(Session &session, identifier::Schema &schema_identifier)
 
666
static void change_db_impl(Session *session, SchemaIdentifier &schema_identifier)
386
667
{
387
668
  /* 1. Change current database in Session. */
388
669
 
405
686
      the previous database name, we should do it explicitly.
406
687
    */
407
688
 
408
 
    session.set_db(schema_identifier.getSchemaName());
409
 
  }
410
 
}
411
 
 
412
 
static void change_db_impl(Session &session)
413
 
{
414
 
  session.set_db(string());
415
 
}
416
 
 
417
 
/*
418
 
  Check if database name is valid
419
 
 
420
 
  SYNPOSIS
421
 
    check()
422
 
    org_name            Name of database and length
423
 
 
424
 
  RETURN
425
 
    false error
426
 
    true ok
427
 
*/
428
 
 
429
 
bool check(Session &session, identifier::Schema &schema_identifier)
430
 
{
431
 
  if (not plugin::Authorization::isAuthorized(*session.user(), schema_identifier))
432
 
  {
433
 
    return false;
434
 
  }
435
 
 
436
 
  return schema_identifier.isValid();
437
 
}
438
 
 
439
 
} /* namespace schema */
 
689
    session->set_db(schema_identifier.getSchemaName());
 
690
  }
 
691
}
 
692
 
 
693
static void change_db_impl(Session *session)
 
694
{
 
695
  session->set_db(string());
 
696
}
440
697
 
441
698
} /* namespace drizzled */