~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/schema.cc

  • Committer: Brian Aker
  • Date: 2011-02-22 06:12:02 UTC
  • mfrom: (2190.1.6 drizzle-build)
  • Revision ID: brian@tangent.org-20110222061202-k03czxykqy4x9hjs
List update, header fixes, multiple symbols, and David deletes some code.

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/message/schema.pb.h>
29
 
#include "drizzled/error.h"
 
28
#include <drizzled/error.h>
30
29
#include <drizzled/gettext.h>
31
30
#include <drizzled/my_hash.h>
32
 
#include "drizzled/internal/m_string.h"
 
31
#include <drizzled/internal/m_string.h>
33
32
#include <drizzled/session.h>
34
 
#include <drizzled/db.h>
 
33
#include <drizzled/schema.h>
35
34
#include <drizzled/sql_base.h>
36
35
#include <drizzled/lock.h>
37
36
#include <drizzled/errmsg_print.h>
38
37
#include <drizzled/transaction_services.h>
39
38
#include <drizzled/message/schema.pb.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"
 
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>
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
 
 
53
49
#define MAX_DROP_TABLE_Q_LEN      1024
54
50
 
55
51
using namespace std;
57
53
namespace drizzled
58
54
{
59
55
 
60
 
static long drop_tables_via_filenames(Session *session,
61
 
                                 SchemaIdentifier &schema_identifier,
62
 
                                 TableIdentifier::vector &dropped_tables);
63
 
static void mysql_change_db_impl(Session *session);
64
 
static void mysql_change_db_impl(Session *session, SchemaIdentifier &schema_identifier);
 
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);
65
61
 
66
62
/*
67
63
  Create a database
68
64
 
69
65
  SYNOPSIS
70
 
  mysql_create_db()
 
66
  create_db()
71
67
  session               Thread handler
72
68
  db            Name of database to create
73
69
                Function assumes that this is already validated.
84
80
 
85
81
*/
86
82
 
87
 
bool mysql_create_db(Session *session, const message::Schema &schema_message, const bool is_if_not_exists)
 
83
bool create(Session &session, const message::Schema &schema_message, const bool is_if_not_exists)
88
84
{
89
85
  TransactionServices &transaction_services= TransactionServices::singleton();
90
86
  bool error= false;
91
87
 
92
88
  /*
93
89
    Do not create database if another thread is holding read lock.
94
 
    Wait for global read lock before acquiring LOCK_create_db.
 
90
    Wait for global read lock before acquiring session->catalog()->schemaLock().
95
91
    After wait_if_global_read_lock() we have protection against another
96
 
    global read lock. If we would acquire LOCK_create_db first,
 
92
    global read lock. If we would acquire session->catalog()->schemaLock() first,
97
93
    another thread could step in and get the global read lock before we
98
94
    reach wait_if_global_read_lock(). If this thread tries the same as we
99
 
    (admin a db), it would then go and wait on LOCK_create_db...
 
95
    (admin a db), it would then go and wait on session->catalog()->schemaLock()...
100
96
    Furthermore wait_if_global_read_lock() checks if the current thread
101
97
    has the global read lock and refuses the operation with
102
98
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
103
99
  */
104
 
  if (session->wait_if_global_read_lock(false, true))
 
100
  if (session.wait_if_global_read_lock(false, true))
105
101
  {
106
102
    return false;
107
103
  }
111
107
 
112
108
  // @todo push this lock down into the engine
113
109
  {
114
 
    boost::mutex::scoped_lock scopedLock(LOCK_create_db);
 
110
    boost::mutex::scoped_lock scopedLock(session.catalog().schemaLock());
115
111
 
116
112
    // Check to see if it exists already.  
117
 
    SchemaIdentifier schema_identifier(schema_message.name());
 
113
    identifier::Schema schema_identifier(schema_message.name());
118
114
    if (plugin::StorageEngine::doesSchemaExist(schema_identifier))
119
115
    {
120
116
      if (not is_if_not_exists)
121
117
      {
122
 
        my_error(ER_DB_CREATE_EXISTS, MYF(0), schema_message.name().c_str());
 
118
        my_error(ER_DB_CREATE_EXISTS, schema_identifier);
123
119
        error= true;
124
120
      }
125
121
      else
126
122
      {
127
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
123
        push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
128
124
                            ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
129
125
                            schema_message.name().c_str());
130
 
        session->my_ok();
 
126
        session.my_ok();
131
127
      }
132
128
    }
133
129
    else if (not plugin::StorageEngine::createSchema(schema_message)) // Try to create it 
138
134
    else // Created !
139
135
    {
140
136
      transaction_services.createSchema(session, schema_message);
141
 
      session->my_ok(1);
 
137
      session.my_ok(1);
142
138
    }
143
139
  }
144
 
  session->startWaitingGlobalReadLock();
 
140
  session.startWaitingGlobalReadLock();
145
141
 
146
142
  return error;
147
143
}
149
145
 
150
146
/* db-name is already validated when we come here */
151
147
 
152
 
bool mysql_alter_db(Session *session, const message::Schema &schema_message)
 
148
bool alter(Session &session,
 
149
           const message::Schema &schema_message,
 
150
           const message::Schema &original_schema)
153
151
{
154
152
  TransactionServices &transaction_services= TransactionServices::singleton();
155
153
 
156
154
  /*
157
155
    Do not alter database if another thread is holding read lock.
158
 
    Wait for global read lock before acquiring LOCK_create_db.
 
156
    Wait for global read lock before acquiring session->catalog()->schemaLock().
159
157
    After wait_if_global_read_lock() we have protection against another
160
 
    global read lock. If we would acquire LOCK_create_db first,
 
158
    global read lock. If we would acquire session->catalog()->schemaLock() first,
161
159
    another thread could step in and get the global read lock before we
162
160
    reach wait_if_global_read_lock(). If this thread tries the same as we
163
 
    (admin a db), it would then go and wait on LOCK_create_db...
 
161
    (admin a db), it would then go and wait on session->catalog()->schemaLock()...
164
162
    Furthermore wait_if_global_read_lock() checks if the current thread
165
163
    has the global read lock and refuses the operation with
166
164
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
167
165
  */
168
 
  if ((session->wait_if_global_read_lock(false, true)))
 
166
  if ((session.wait_if_global_read_lock(false, true)))
169
167
    return false;
170
168
 
171
169
  bool success;
172
170
  {
173
 
    boost::mutex::scoped_lock scopedLock(LOCK_create_db);
 
171
    boost::mutex::scoped_lock scopedLock(session.catalog().schemaLock());
174
172
 
175
 
    SchemaIdentifier schema_idenifier(schema_message.name());
 
173
    identifier::Schema schema_idenifier(schema_message.name());
176
174
    if (not plugin::StorageEngine::doesSchemaExist(schema_idenifier))
177
175
    {
178
 
      my_error(ER_SCHEMA_DOES_NOT_EXIST, MYF(0), schema_message.name().c_str());
 
176
      my_error(ER_SCHEMA_DOES_NOT_EXIST, schema_idenifier);
179
177
      return false;
180
178
    }
181
179
 
184
182
 
185
183
    if (success)
186
184
    {
187
 
      transaction_services.rawStatement(session, *session->getQueryString());
188
 
      session->my_ok(1);
 
185
      transaction_services.alterSchema(session, original_schema, schema_message);
 
186
      session.my_ok(1);
189
187
    }
190
188
    else
191
189
    {
192
 
      my_error(ER_ALTER_SCHEMA, MYF(0), schema_message.name().c_str());
 
190
      my_error(ER_ALTER_SCHEMA, schema_idenifier);
193
191
    }
194
192
  }
195
 
  session->startWaitingGlobalReadLock();
 
193
  session.startWaitingGlobalReadLock();
196
194
 
197
195
  return success;
198
196
}
202
200
  Drop all tables in a database and the database itself
203
201
 
204
202
  SYNOPSIS
205
 
    mysql_rm_db()
 
203
    rm_db()
206
204
    session                     Thread handle
207
205
    db                  Database name in the case given by user
208
206
                        It's already validated and set to lower case
215
213
    ERROR Error
216
214
*/
217
215
 
218
 
bool mysql_rm_db(Session *session, SchemaIdentifier &schema_identifier, const bool if_exists)
 
216
bool drop(Session &session, identifier::Schema &schema_identifier, const bool if_exists)
219
217
{
220
 
  long deleted=0;
221
 
  int error= false;
222
 
  TableIdentifier::vector dropped_tables;
223
 
  message::Schema schema_proto;
 
218
  bool error= false;
224
219
 
225
220
  /*
226
221
    Do not drop database if another thread is holding read lock.
227
 
    Wait for global read lock before acquiring LOCK_create_db.
 
222
    Wait for global read lock before acquiring session->catalog()->schemaLock().
228
223
    After wait_if_global_read_lock() we have protection against another
229
 
    global read lock. If we would acquire LOCK_create_db first,
 
224
    global read lock. If we would acquire session->catalog()->schemaLock() first,
230
225
    another thread could step in and get the global read lock before we
231
226
    reach wait_if_global_read_lock(). If this thread tries the same as we
232
 
    (admin a db), it would then go and wait on LOCK_create_db...
 
227
    (admin a db), it would then go and wait on session->catalog()->schemaLock()...
233
228
    Furthermore wait_if_global_read_lock() checks if the current thread
234
229
    has the global read lock and refuses the operation with
235
230
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
236
231
  */
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);
 
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);
255
241
 
256
242
    /* See if the schema exists */
257
 
    if (not plugin::StorageEngine::doesSchemaExist(schema_identifier))
 
243
    if (not message)
258
244
    {
259
 
      std::string path;
260
 
      schema_identifier.getSQLPath(path);
261
 
 
262
245
      if (if_exists)
263
246
      {
264
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
247
        std::string path;
 
248
        schema_identifier.getSQLPath(path);
 
249
 
 
250
        push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
265
251
                            ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS),
266
252
                            path.c_str());
267
253
      }
268
254
      else
269
255
      {
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
 
 
281
 
      error= -1;
282
 
      deleted= drop_tables_via_filenames(session, schema_identifier, dropped_tables);
283
 
      if (deleted >= 0)
284
 
      {
285
 
        error= 0;
286
 
      }
287
 
    }
288
 
    if (deleted >= 0)
289
 
    {
290
 
      assert(not session->getQueryString()->empty());
291
 
 
292
 
      TransactionServices &transaction_services= TransactionServices::singleton();
293
 
      transaction_services.dropSchema(session, schema_identifier.getSchemaName());
294
 
      session->clear_error();
295
 
      session->server_status|= SERVER_STATUS_DB_DROPPED;
296
 
      session->my_ok((uint32_t) deleted);
297
 
      session->server_status&= ~SERVER_STATUS_DB_DROPPED;
298
 
    }
299
 
    else
300
 
    {
301
 
      char *query, *query_pos, *query_end, *query_data_start;
302
 
 
303
 
      if (!(query= (char*) session->alloc(MAX_DROP_TABLE_Q_LEN)))
304
 
        goto exit; /* not much else we can do */
305
 
      query_pos= query_data_start= strcpy(query,"drop table ")+11;
306
 
      query_end= query + MAX_DROP_TABLE_Q_LEN;
307
 
 
308
 
      TransactionServices &transaction_services= TransactionServices::singleton();
309
 
      for (TableIdentifier::vector::iterator it= dropped_tables.begin();
310
 
           it != dropped_tables.end();
311
 
           it++)
312
 
      {
313
 
        uint32_t tbl_name_len;
314
 
 
315
 
        /* 3 for the quotes and the comma*/
316
 
        tbl_name_len= (*it).getTableName().length() + 3;
317
 
        if (query_pos + tbl_name_len + 1 >= query_end)
318
 
        {
319
 
          /* These DDL methods and logging protected with LOCK_create_db */
320
 
          transaction_services.rawStatement(session, query);
321
 
          query_pos= query_data_start;
322
 
        }
323
 
 
324
 
        *query_pos++ = '`';
325
 
        query_pos= strcpy(query_pos, (*it).getTableName().c_str()) + (tbl_name_len-3);
326
 
        *query_pos++ = '`';
327
 
        *query_pos++ = ',';
328
 
      }
329
 
 
330
 
      if (query_pos != query_data_start)
331
 
      {
332
 
        /* These DDL methods and logging protected with LOCK_create_db */
333
 
        transaction_services.rawStatement(session, query);
334
 
      }
335
 
    }
336
 
 
337
 
exit:
338
 
    /*
339
 
      If this database was the client's selected database, we silently
340
 
      change the client's selected database to nothing (to have an empty
341
 
      SELECT DATABASE() in the future). For this we free() session->db and set
342
 
      it to 0.
343
 
    */
344
 
    if (schema_identifier.compare(*session->schema()))
345
 
      mysql_change_db_impl(session);
346
 
  }
347
 
 
348
 
  session->startWaitingGlobalReadLock();
 
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();
349
278
 
350
279
  return error;
351
280
}
352
281
 
353
 
 
354
 
static int rm_table_part2(Session *session, TableList *tables)
355
 
{
356
 
  TransactionServices &transaction_services= TransactionServices::singleton();
357
 
 
358
 
  TableList *table;
359
 
  String wrong_tables;
360
 
  int error= 0;
361
 
  bool foreign_key_error= false;
362
 
 
363
 
  {
364
 
    table::Cache::singleton().mutex().lock(); /* Part 2 of rm a table */
365
 
 
366
 
    if (session->lock_table_names_exclusively(tables))
367
 
    {
368
 
      table::Cache::singleton().mutex().unlock();
369
 
      return 1;
370
 
    }
371
 
 
372
 
    /* Don't give warnings for not found errors, as we already generate notes */
373
 
    session->no_warnings_for_error= 1;
374
 
 
375
 
    for (table= tables; table; table= table->next_local)
376
 
    {
377
 
      const char *db=table->getSchemaName();
378
 
      TableIdentifier identifier(table->getSchemaName(), table->getTableName());
379
 
 
380
 
      plugin::StorageEngine *table_type;
381
 
 
382
 
      error= session->drop_temporary_table(identifier);
383
 
 
384
 
      switch (error) {
385
 
      case  0:
386
 
        // removed temporary table
387
 
        continue;
388
 
      case -1:
389
 
        error= 1;
390
 
        tables->unlock_table_names();
391
 
        table::Cache::singleton().mutex().unlock();
392
 
        session->no_warnings_for_error= 0;
393
 
 
394
 
        return(error);
395
 
      default:
396
 
        // temporary table not found
397
 
        error= 0;
398
 
      }
399
 
 
400
 
      table_type= table->getDbType();
401
 
 
402
 
      {
403
 
        Table *locked_table;
404
 
        abort_locked_tables(session, identifier);
405
 
        table::Cache::singleton().removeTable(session, identifier,
406
 
                                              RTFC_WAIT_OTHER_THREAD_FLAG |
407
 
                                              RTFC_CHECK_KILLED_FLAG);
408
 
        /*
409
 
          If the table was used in lock tables, remember it so that
410
 
          unlock_table_names can free it
411
 
        */
412
 
        if ((locked_table= drop_locked_tables(session, identifier)))
413
 
          table->table= locked_table;
414
 
 
415
 
        if (session->getKilled())
416
 
        {
417
 
          error= -1;
418
 
          tables->unlock_table_names();
419
 
          table::Cache::singleton().mutex().unlock();
420
 
          session->no_warnings_for_error= 0;
421
 
 
422
 
          return(error);
423
 
        }
424
 
      }
425
 
      identifier.getPath();
426
 
 
427
 
      if (table_type == NULL && not plugin::StorageEngine::doesTableExist(*session, identifier))
428
 
      {
429
 
        // Table was not found on disk and table can't be created from engine
430
 
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
431
 
                            ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
432
 
                            table->getTableName());
433
 
      }
434
 
      else
435
 
      {
436
 
        error= plugin::StorageEngine::dropTable(*session, identifier);
437
 
 
438
 
        if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE))
439
 
        {
440
 
          error= 0;
441
 
          session->clear_error();
442
 
        }
443
 
 
444
 
        if (error == HA_ERR_ROW_IS_REFERENCED)
445
 
        {
446
 
          /* the table is referenced by a foreign key constraint */
447
 
          foreign_key_error= true;
448
 
        }
449
 
      }
450
 
 
451
 
      if (error == 0 || (foreign_key_error == false))
452
 
      {
453
 
        transaction_services.dropTable(session, string(db), string(table->getTableName()), true);
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
 
 
557
282
/**
558
283
  @brief Change the current database and its attributes unconditionally.
559
284
 
616
341
    @retval true  Error
617
342
*/
618
343
 
619
 
bool mysql_change_db(Session *session, SchemaIdentifier &schema_identifier)
 
344
bool change(Session &session, identifier::Schema &schema_identifier)
620
345
{
621
346
 
622
 
  if (not plugin::Authorization::isAuthorized(session->getSecurityContext(), schema_identifier))
 
347
  if (not plugin::Authorization::isAuthorized(*session.user(), schema_identifier))
623
348
  {
624
349
    /* Error message is set in isAuthorized */
625
350
    return true;
626
351
  }
627
352
 
628
 
  if (not check_db_name(session, schema_identifier))
 
353
  if (not check(session, schema_identifier))
629
354
  {
630
 
    std::string path;
631
 
    schema_identifier.getSQLPath(path);
632
 
    my_error(ER_WRONG_DB_NAME, MYF(0), path.c_str());
 
355
    my_error(ER_WRONG_DB_NAME, schema_identifier);
633
356
 
634
357
    return true;
635
358
  }
636
359
 
637
360
  if (not plugin::StorageEngine::doesSchemaExist(schema_identifier))
638
361
  {
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());
 
362
    my_error(ER_BAD_DB_ERROR, schema_identifier);
644
363
 
645
364
    /* The operation failed. */
646
365
 
647
366
    return true;
648
367
  }
649
368
 
650
 
  mysql_change_db_impl(session, schema_identifier);
 
369
  change_db_impl(session, schema_identifier);
651
370
 
652
371
  return false;
653
372
}
663
382
  @param new_db_charset Character set of the new database.
664
383
*/
665
384
 
666
 
static void mysql_change_db_impl(Session *session, SchemaIdentifier &schema_identifier)
 
385
static void change_db_impl(Session &session, identifier::Schema &schema_identifier)
667
386
{
668
387
  /* 1. Change current database in Session. */
669
388
 
686
405
      the previous database name, we should do it explicitly.
687
406
    */
688
407
 
689
 
    session->set_db(schema_identifier.getSchemaName());
690
 
  }
691
 
}
692
 
 
693
 
static void mysql_change_db_impl(Session *session)
694
 
{
695
 
  session->set_db(string());
696
 
}
 
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 */
697
440
 
698
441
} /* namespace drizzled */