~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/db.cc

  • Committer: Mark Atwood
  • Date: 2010-06-24 03:15:21 UTC
  • mto: (1637.2.4 build)
  • mto: This revision was merged to the branch mainline in revision 1639.
  • Revision ID: me@mark.atwood.name-20100624031521-gafmppfbf5afm68w
new syslog module, with plugins for query log, error message, and SYSLOG() function

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