~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/db.cc

  • Committer: Brian Aker
  • Date: 2010-08-09 18:04:12 UTC
  • mfrom: (1689.3.7 staging)
  • Revision ID: brian@gaz-20100809180412-olurwh51ojllev6p
Merge in heap conversion, and case insensitive patch, and remove need for
M_HASH in session.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
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
                                 TableIdentifiers &dropped_tables);
 
63
static void mysql_change_db_impl(Session *session);
 
64
static void mysql_change_db_impl(Session *session, SchemaIdentifier &schema_identifier);
61
65
 
62
66
/*
63
67
  Create a database
64
68
 
65
69
  SYNOPSIS
66
 
  create_db()
 
70
  mysql_create_db()
67
71
  session               Thread handler
68
72
  db            Name of database to create
69
73
                Function assumes that this is already validated.
80
84
 
81
85
*/
82
86
 
83
 
bool create(Session &session, const message::Schema &schema_message, const bool is_if_not_exists)
 
87
bool mysql_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 (wait_if_global_read_lock(session, 0, 1))
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
  start_waiting_global_read_lock(session);
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 mysql_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 ((wait_if_global_read_lock(session, 0, 1)))
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
  start_waiting_global_read_lock(session);
194
196
 
195
197
  return success;
196
198
}
200
202
  Drop all tables in a database and the database itself
201
203
 
202
204
  SYNOPSIS
203
 
    rm_db()
 
205
    mysql_rm_db()
204
206
    session                     Thread handle
205
207
    db                  Database name in the case given by user
206
208
                        It's already validated and set to lower case
213
215
    ERROR Error
214
216
*/
215
217
 
216
 
bool drop(Session &session, identifier::Schema &schema_identifier, const bool if_exists)
 
218
bool mysql_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
  TableIdentifiers 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 (wait_if_global_read_lock(session, 0, 1))
 
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
    {
245
259
      if (if_exists)
246
260
      {
247
 
        std::string path;
248
 
        schema_identifier.getSQLPath(path);
249
 
 
250
 
        push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
261
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
251
262
                            ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS),
252
 
                            path.c_str());
 
263
                            schema_identifier.getSQLPath().c_str());
253
264
      }
254
265
      else
255
266
      {
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();
 
267
        error= -1;
 
268
        my_error(ER_DB_DROP_EXISTS, MYF(0), schema_identifier.getSQLPath().c_str());
 
269
        goto exit;
 
270
      }
 
271
    }
 
272
    else
 
273
    {
 
274
      LOCK_open.lock(); /* After deleting database, remove all cache entries related to schema */
 
275
      remove_db_from_cache(schema_identifier);
 
276
      LOCK_open.unlock();
 
277
 
 
278
 
 
279
      error= -1;
 
280
      deleted= drop_tables_via_filenames(session, schema_identifier, dropped_tables);
 
281
      if (deleted >= 0)
 
282
      {
 
283
        error= 0;
 
284
      }
 
285
    }
 
286
    if (deleted >= 0)
 
287
    {
 
288
      assert(! session->query.empty());
 
289
 
 
290
      TransactionServices &transaction_services= TransactionServices::singleton();
 
291
      transaction_services.dropSchema(session, schema_identifier.getSchemaName());
 
292
      session->clear_error();
 
293
      session->server_status|= SERVER_STATUS_DB_DROPPED;
 
294
      session->my_ok((uint32_t) deleted);
 
295
      session->server_status&= ~SERVER_STATUS_DB_DROPPED;
 
296
    }
 
297
    else
 
298
    {
 
299
      char *query, *query_pos, *query_end, *query_data_start;
 
300
 
 
301
      if (!(query= (char*) session->alloc(MAX_DROP_TABLE_Q_LEN)))
 
302
        goto exit; /* not much else we can do */
 
303
      query_pos= query_data_start= strcpy(query,"drop table ")+11;
 
304
      query_end= query + MAX_DROP_TABLE_Q_LEN;
 
305
 
 
306
      TransactionServices &transaction_services= TransactionServices::singleton();
 
307
      for (TableIdentifiers::iterator it= dropped_tables.begin();
 
308
           it != dropped_tables.end();
 
309
           it++)
 
310
      {
 
311
        uint32_t tbl_name_len;
 
312
 
 
313
        /* 3 for the quotes and the comma*/
 
314
        tbl_name_len= (*it).getTableName().length() + 3;
 
315
        if (query_pos + tbl_name_len + 1 >= query_end)
 
316
        {
 
317
          /* These DDL methods and logging protected with LOCK_create_db */
 
318
          transaction_services.rawStatement(session, query);
 
319
          query_pos= query_data_start;
 
320
        }
 
321
 
 
322
        *query_pos++ = '`';
 
323
        query_pos= strcpy(query_pos, (*it).getTableName().c_str()) + (tbl_name_len-3);
 
324
        *query_pos++ = '`';
 
325
        *query_pos++ = ',';
 
326
      }
 
327
 
 
328
      if (query_pos != query_data_start)
 
329
      {
 
330
        /* These DDL methods and logging protected with LOCK_create_db */
 
331
        transaction_services.rawStatement(session, query);
 
332
      }
 
333
    }
 
334
 
 
335
exit:
 
336
    /*
 
337
      If this database was the client's selected database, we silently
 
338
      change the client's selected database to nothing (to have an empty
 
339
      SELECT DATABASE() in the future). For this we free() session->db and set
 
340
      it to 0.
 
341
    */
 
342
    if (schema_identifier.compare(session->db))
 
343
      mysql_change_db_impl(session);
 
344
  }
 
345
 
 
346
  start_waiting_global_read_lock(session);
278
347
 
279
348
  return error;
280
349
}
281
350
 
 
351
 
 
352
static int rm_table_part2(Session *session, TableList *tables)
 
353
{
 
354
  TableList *table;
 
355
  String wrong_tables;
 
356
  int error= 0;
 
357
  bool foreign_key_error= false;
 
358
 
 
359
  LOCK_open.lock(); /* Part 2 of rm a table */
 
360
 
 
361
  /*
 
362
    If we have the table in the definition cache, we don't have to check the
 
363
    .frm cursor to find if the table is a normal table (not view) and what
 
364
    engine to use.
 
365
  */
 
366
 
 
367
  for (table= tables; table; table= table->next_local)
 
368
  {
 
369
    TableIdentifier identifier(table->db, table->table_name);
 
370
    TableShare *share;
 
371
    table->setDbType(NULL);
 
372
    if ((share= TableShare::getShare(identifier)))
 
373
    {
 
374
      table->setDbType(share->db_type());
 
375
    }
 
376
  }
 
377
 
 
378
  if (lock_table_names_exclusively(session, tables))
 
379
  {
 
380
    LOCK_open.unlock();
 
381
    return 1;
 
382
  }
 
383
 
 
384
  /* Don't give warnings for not found errors, as we already generate notes */
 
385
  session->no_warnings_for_error= 1;
 
386
 
 
387
  for (table= tables; table; table= table->next_local)
 
388
  {
 
389
    char *db=table->db;
 
390
    plugin::StorageEngine *table_type;
 
391
 
 
392
    error= session->drop_temporary_table(table);
 
393
 
 
394
    switch (error) {
 
395
    case  0:
 
396
      // removed temporary table
 
397
      continue;
 
398
    case -1:
 
399
      error= 1;
 
400
      unlock_table_names(tables, NULL);
 
401
      LOCK_open.unlock();
 
402
      session->no_warnings_for_error= 0;
 
403
 
 
404
      return(error);
 
405
    default:
 
406
      // temporary table not found
 
407
      error= 0;
 
408
    }
 
409
 
 
410
    table_type= table->getDbType();
 
411
 
 
412
    TableIdentifier identifier(db, table->table_name);
 
413
 
 
414
    {
 
415
      Table *locked_table;
 
416
      abort_locked_tables(session, identifier);
 
417
      remove_table_from_cache(session, identifier,
 
418
                              RTFC_WAIT_OTHER_THREAD_FLAG |
 
419
                              RTFC_CHECK_KILLED_FLAG);
 
420
      /*
 
421
        If the table was used in lock tables, remember it so that
 
422
        unlock_table_names can free it
 
423
      */
 
424
      if ((locked_table= drop_locked_tables(session, identifier)))
 
425
        table->table= locked_table;
 
426
 
 
427
      if (session->killed)
 
428
      {
 
429
        error= -1;
 
430
        unlock_table_names(tables, NULL);
 
431
        LOCK_open.unlock();
 
432
        session->no_warnings_for_error= 0;
 
433
 
 
434
        return(error);
 
435
      }
 
436
    }
 
437
    identifier.getPath();
 
438
 
 
439
    if (table_type == NULL && not plugin::StorageEngine::doesTableExist(*session, identifier))
 
440
    {
 
441
      // Table was not found on disk and table can't be created from engine
 
442
      push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
443
                          ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
 
444
                          table->table_name);
 
445
    }
 
446
    else
 
447
    {
 
448
      error= plugin::StorageEngine::dropTable(*session, identifier);
 
449
 
 
450
      if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE))
 
451
      {
 
452
        error= 0;
 
453
        session->clear_error();
 
454
      }
 
455
 
 
456
      if (error == HA_ERR_ROW_IS_REFERENCED)
 
457
      {
 
458
        /* the table is referenced by a foreign key constraint */
 
459
        foreign_key_error= true;
 
460
      }
 
461
    }
 
462
 
 
463
    if (error == 0 || (foreign_key_error == false))
 
464
        write_bin_log_drop_table(session, true, db, table->table_name);
 
465
 
 
466
    if (error)
 
467
    {
 
468
      if (wrong_tables.length())
 
469
        wrong_tables.append(',');
 
470
      wrong_tables.append(String(table->table_name,system_charset_info));
 
471
    }
 
472
  }
 
473
  /*
 
474
    It's safe to unlock LOCK_open: we have an exclusive lock
 
475
    on the table name.
 
476
  */
 
477
  LOCK_open.unlock();
 
478
  error= 0;
 
479
  if (wrong_tables.length())
 
480
  {
 
481
    if (not foreign_key_error)
 
482
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
 
483
                      wrong_tables.c_ptr());
 
484
    else
 
485
    {
 
486
      my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
 
487
    }
 
488
    error= 1;
 
489
  }
 
490
 
 
491
  LOCK_open.lock(); /* final bit in rm table lock */
 
492
  unlock_table_names(tables, NULL);
 
493
  LOCK_open.unlock();
 
494
  session->no_warnings_for_error= 0;
 
495
 
 
496
  return(error);
 
497
}
 
498
 
 
499
/*
 
500
  Removes files with known extensions plus.
 
501
  session MUST be set when calling this function!
 
502
*/
 
503
 
 
504
static long drop_tables_via_filenames(Session *session,
 
505
                                      SchemaIdentifier &schema_identifier,
 
506
                                      TableIdentifiers &dropped_tables)
 
507
{
 
508
  long deleted= 0;
 
509
  TableList *tot_list= NULL, **tot_list_next;
 
510
 
 
511
  tot_list_next= &tot_list;
 
512
 
 
513
  plugin::StorageEngine::getIdentifiers(*session, schema_identifier, dropped_tables);
 
514
 
 
515
  for (TableIdentifiers::iterator it= dropped_tables.begin();
 
516
       it != dropped_tables.end();
 
517
       it++)
 
518
  {
 
519
    size_t db_len= schema_identifier.getSchemaName().size();
 
520
 
 
521
    /* Drop the table nicely */
 
522
    TableList *table_list=(TableList*)
 
523
      session->calloc(sizeof(*table_list) +
 
524
                      db_len + 1 +
 
525
                      (*it).getTableName().length() + 1);
 
526
 
 
527
    if (not table_list)
 
528
      return -1;
 
529
 
 
530
    table_list->db= (char*) (table_list+1);
 
531
    table_list->table_name= strcpy(table_list->db, schema_identifier.getSchemaName().c_str()) + db_len + 1;
 
532
    TableIdentifier::filename_to_tablename((*it).getTableName().c_str(), table_list->table_name, (*it).getTableName().size() + 1);
 
533
    table_list->alias= table_list->table_name;  // If lower_case_table_names=2
 
534
    table_list->setInternalTmpTable((strncmp((*it).getTableName().c_str(),
 
535
                                             TMP_FILE_PREFIX,
 
536
                                             strlen(TMP_FILE_PREFIX)) == 0));
 
537
    /* Link into list */
 
538
    (*tot_list_next)= table_list;
 
539
    tot_list_next= &table_list->next_local;
 
540
    deleted++;
 
541
  }
 
542
  if (session->killed)
 
543
    return -1;
 
544
 
 
545
  if (tot_list)
 
546
  {
 
547
    if (rm_table_part2(session, tot_list))
 
548
      return -1;
 
549
  }
 
550
 
 
551
 
 
552
  if (not plugin::StorageEngine::dropSchema(schema_identifier))
 
553
  {
 
554
    my_error(ER_DROP_SCHEMA, MYF(0), schema_identifier.getSQLPath().c_str());
 
555
    return -1;
 
556
  }
 
557
 
 
558
  return deleted;
 
559
}
 
560
 
282
561
/**
283
562
  @brief Change the current database and its attributes unconditionally.
284
563
 
341
620
    @retval true  Error
342
621
*/
343
622
 
344
 
bool change(Session &session, identifier::Schema &schema_identifier)
 
623
bool mysql_change_db(Session *session, SchemaIdentifier &schema_identifier)
345
624
{
346
625
 
347
 
  if (not plugin::Authorization::isAuthorized(*session.user(), schema_identifier))
 
626
  if (not plugin::Authorization::isAuthorized(session->getSecurityContext(), schema_identifier))
348
627
  {
349
628
    /* Error message is set in isAuthorized */
350
629
    return true;
351
630
  }
352
631
 
353
 
  if (not check(session, schema_identifier))
 
632
  if (not check_db_name(session, schema_identifier))
354
633
  {
355
 
    my_error(ER_WRONG_DB_NAME, schema_identifier);
 
634
    my_error(ER_WRONG_DB_NAME, MYF(0), schema_identifier.getSQLPath().c_str());
356
635
 
357
636
    return true;
358
637
  }
359
638
 
360
639
  if (not plugin::StorageEngine::doesSchemaExist(schema_identifier))
361
640
  {
362
 
    my_error(ER_BAD_DB_ERROR, schema_identifier);
 
641
    /* Report an error and free new_db_file_name. */
 
642
 
 
643
    my_error(ER_BAD_DB_ERROR, MYF(0), schema_identifier.getSQLPath().c_str());
363
644
 
364
645
    /* The operation failed. */
365
646
 
366
647
    return true;
367
648
  }
368
649
 
369
 
  change_db_impl(session, schema_identifier);
 
650
  mysql_change_db_impl(session, schema_identifier);
370
651
 
371
652
  return false;
372
653
}
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 mysql_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 mysql_change_db_impl(Session *session)
 
694
{
 
695
  session->set_db(string());
 
696
}
440
697
 
441
698
} /* namespace drizzled */