~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2003 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
15
16
17
/* create and drop of databases */
1241.9.36 by Monty Taylor
ZOMG. I deleted drizzled/server_includes.h.
18
#include "config.h"
1259.3.7 by Monty Taylor
Fixed OSX build error.
19
20
#include <fcntl.h>
21
#include <sys/stat.h>
22
#include <sys/types.h>
23
24
#include <set>
318 by Brian Aker
Modified sql_db to now use Google Proto buffers instead of MySQL type.
25
#include <string>
26
#include <fstream>
1259.3.7 by Monty Taylor
Fixed OSX build error.
27
988.1.1 by Jay Pipes
Changes libserialize to libdrizzledmessage per ML discussion. All GPB messages are now in the drizzled::message namespace.
28
#include <drizzled/message/schema.pb.h>
1271.5.3 by Tim Penhey
change the include files
29
#include "drizzled/error.h"
538 by Monty Taylor
Moved gettext.h into drizzled in anticipation of the new client lib.
30
#include <drizzled/gettext.h>
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
31
#include <drizzled/my_hash.h>
1241.9.64 by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal.
32
#include "drizzled/internal/m_string.h"
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
33
#include <drizzled/session.h>
34
#include <drizzled/db.h>
35
#include <drizzled/sql_base.h>
670.2.4 by Monty Taylor
Removed more stuff from the headers.
36
#include <drizzled/lock.h>
722.4.1 by Mark Atwood
integrate errmsg plugin into sql_print_* functions
37
#include <drizzled/errmsg_print.h>
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
38
#include <drizzled/transaction_services.h>
1089.10.1 by Stewart Smith
fix SHOW CREATE DATABASE for default collation. Move database metadata reading code around to be a bit more sane.
39
#include <drizzled/message/schema.pb.h>
1241.9.12 by Monty Taylor
Trims more out of server_includes.h.
40
#include "drizzled/sql_table.h"
1273.20.3 by Brian Aker
Fixing charset return.
41
#include "drizzled/plugin/storage_engine.h"
1317.2.1 by Monty Taylor
Removed an unused variable.
42
#include "drizzled/plugin/authorization.h"
1241.9.28 by Monty Taylor
Removed global_charset_info.h from server_includes.h
43
#include "drizzled/global_charset_info.h"
1241.9.31 by Monty Taylor
Moved global pthread variables into their own header.
44
#include "drizzled/pthread_globals.h"
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
45
#include "drizzled/charset.h"
1241.9.28 by Monty Taylor
Removed global_charset_info.h from server_includes.h
46
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
47
#include <boost/thread/mutex.hpp>
48
49
boost::mutex LOCK_create_db;
50
1241.9.64 by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal.
51
#include "drizzled/internal/my_sys.h"
988.1.6 by Jay Pipes
Removed old protobuf_replicator plugin, fixed up db.cc and other files to use new
52
1 by brian
clean slate
53
#define MAX_DROP_TABLE_Q_LEN      1024
54
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
55
using namespace std;
56
57
namespace drizzled
58
{
59
1601 by Brian Aker
Move functions to class methods.
60
static long drop_tables_via_filenames(Session *session,
1415 by Brian Aker
Mass overhaul to use schema_identifier.
61
                                 SchemaIdentifier &schema_identifier,
1966.2.4 by Brian Aker
Style cleanup.
62
                                 TableIdentifier::vector &dropped_tables);
1415 by Brian Aker
Mass overhaul to use schema_identifier.
63
static void mysql_change_db_impl(Session *session);
64
static void mysql_change_db_impl(Session *session, SchemaIdentifier &schema_identifier);
820.1.11 by Stewart Smith
re-introduce db.opt, but with parsing it from disk instead of in process cache with mutex.
65
1 by brian
clean slate
66
/*
67
  Create a database
68
69
  SYNOPSIS
70
  mysql_create_db()
520.1.22 by Brian Aker
Second pass of thd cleanup
71
  session		Thread handler
1 by brian
clean slate
72
  db		Name of database to create
73
		Function assumes that this is already validated.
74
  create_info	Database create options (like character set)
75
76
  SIDE-EFFECTS
77
   1. Report back to client that command succeeded (my_ok)
78
   2. Report errors to client
79
   3. Log event to binary log
80
81
  RETURN VALUES
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
82
  false ok
83
  true  Error
1 by brian
clean slate
84
85
*/
86
1309.1.9 by Brian Aker
Baby steps.
87
bool mysql_create_db(Session *session, const message::Schema &schema_message, const bool is_if_not_exists)
1 by brian
clean slate
88
{
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
89
  TransactionServices &transaction_services= TransactionServices::singleton();
1039.1.3 by Brian Aker
Remove dead bits from db create/rm
90
  bool error= false;
1235.4.14 by Stewart Smith
use message::Schema in mysql_create_db instead of HA_CREATE_INFO
91
1 by brian
clean slate
92
  /*
93
    Do not create database if another thread is holding read lock.
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
94
    Wait for global read lock before acquiring LOCK_create_db.
1 by brian
clean slate
95
    After wait_if_global_read_lock() we have protection against another
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
96
    global read lock. If we would acquire LOCK_create_db first,
1 by brian
clean slate
97
    another thread could step in and get the global read lock before we
98
    reach wait_if_global_read_lock(). If this thread tries the same as we
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
99
    (admin a db), it would then go and wait on LOCK_create_db...
1 by brian
clean slate
100
    Furthermore wait_if_global_read_lock() checks if the current thread
101
    has the global read lock and refuses the operation with
102
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
103
  */
1910.2.3 by Brian Aker
Second pass on move code to global lock encapsulation.
104
  if (session->wait_if_global_read_lock(false, true))
1 by brian
clean slate
105
  {
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
106
    return false;
1 by brian
clean slate
107
  }
108
1273.19.28 by Brian Aker
More cleanup on ALTER SCHEMA. Hey! MySQL never had errors on half of it...
109
  assert(schema_message.has_name());
110
  assert(schema_message.has_collation());
111
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
112
  // @todo push this lock down into the engine
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
113
  {
114
    boost::mutex::scoped_lock scopedLock(LOCK_create_db);
1 by brian
clean slate
115
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
116
    // Check to see if it exists already.  
117
    SchemaIdentifier schema_identifier(schema_message.name());
118
    if (plugin::StorageEngine::doesSchemaExist(schema_identifier))
119
    {
120
      if (not is_if_not_exists)
121
      {
122
        my_error(ER_DB_CREATE_EXISTS, MYF(0), schema_message.name().c_str());
123
        error= true;
124
      }
125
      else
126
      {
127
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
128
                            ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
129
                            schema_message.name().c_str());
130
        session->my_ok();
131
      }
132
    }
1856.2.8 by Joseph Daly
working alter, drop, create schema
133
    else if (not plugin::StorageEngine::createSchema(schema_message)) // Try to create it 
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
134
    {
135
      my_error(ER_CANT_CREATE_DB, MYF(0), schema_message.name().c_str(), errno);
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
136
      error= true;
137
    }
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
138
    else // Created !
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
139
    {
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
140
      transaction_services.createSchema(session, schema_message);
141
      session->my_ok(1);
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
142
    }
143
  }
1910.2.2 by Brian Aker
First pass through the global lock refactor merge.
144
  session->startWaitingGlobalReadLock();
1273.19.25 by Brian Aker
createSchema() now works via SE interface.
145
1039.1.3 by Brian Aker
Remove dead bits from db create/rm
146
  return error;
1 by brian
clean slate
147
}
148
149
150
/* db-name is already validated when we come here */
151
1273.19.26 by Brian Aker
Move Alter schema to SE interface.
152
bool mysql_alter_db(Session *session, const message::Schema &schema_message)
1 by brian
clean slate
153
{
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
154
  TransactionServices &transaction_services= TransactionServices::singleton();
1 by brian
clean slate
155
156
  /*
157
    Do not alter database if another thread is holding read lock.
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
158
    Wait for global read lock before acquiring LOCK_create_db.
1 by brian
clean slate
159
    After wait_if_global_read_lock() we have protection against another
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
160
    global read lock. If we would acquire LOCK_create_db first,
1 by brian
clean slate
161
    another thread could step in and get the global read lock before we
162
    reach wait_if_global_read_lock(). If this thread tries the same as we
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
163
    (admin a db), it would then go and wait on LOCK_create_db...
1 by brian
clean slate
164
    Furthermore wait_if_global_read_lock() checks if the current thread
165
    has the global read lock and refuses the operation with
166
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
167
  */
1910.2.3 by Brian Aker
Second pass on move code to global lock encapsulation.
168
  if ((session->wait_if_global_read_lock(false, true)))
1273.19.26 by Brian Aker
Move Alter schema to SE interface.
169
    return false;
1235.4.16 by Stewart Smith
use Schema proto for ALTER DATABASE/SCHEMA as well. Fix 'ALTER DATABASE COLLATE = foo'. Remove now obsolete fill_schema_message. HA_CREATE_INFO is no longer used in CREATE or ALTER SCHEMA.
170
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
171
  bool success;
172
  {
173
    boost::mutex::scoped_lock scopedLock(LOCK_create_db);
174
175
    SchemaIdentifier schema_idenifier(schema_message.name());
176
    if (not plugin::StorageEngine::doesSchemaExist(schema_idenifier))
177
    {
178
      my_error(ER_SCHEMA_DOES_NOT_EXIST, MYF(0), schema_message.name().c_str());
179
      return false;
180
    }
181
182
    /* Change options if current database is being altered. */
183
    success= plugin::StorageEngine::alterSchema(schema_message);
184
185
    if (success)
186
    {
1921.4.13 by Brian Aker
Fix issue where session info might not be correct.
187
      transaction_services.rawStatement(session, *session->getQueryString());
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
188
      session->my_ok(1);
189
    }
190
    else
191
    {
192
      my_error(ER_ALTER_SCHEMA, MYF(0), schema_message.name().c_str());
193
    }
194
  }
1910.2.2 by Brian Aker
First pass through the global lock refactor merge.
195
  session->startWaitingGlobalReadLock();
1273.19.26 by Brian Aker
Move Alter schema to SE interface.
196
197
  return success;
1 by brian
clean slate
198
}
199
200
201
/*
202
  Drop all tables in a database and the database itself
203
204
  SYNOPSIS
205
    mysql_rm_db()
520.1.22 by Brian Aker
Second pass of thd cleanup
206
    session			Thread handle
1 by brian
clean slate
207
    db			Database name in the case given by user
208
		        It's already validated and set to lower case
209
                        (if needed) when we come here
210
    if_exists		Don't give error if database doesn't exists
211
    silent		Don't generate errors
212
213
  RETURN
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
214
    false ok (Database dropped)
1 by brian
clean slate
215
    ERROR Error
216
*/
217
1415 by Brian Aker
Mass overhaul to use schema_identifier.
218
bool mysql_rm_db(Session *session, SchemaIdentifier &schema_identifier, const bool if_exists)
1 by brian
clean slate
219
{
220
  long deleted=0;
253 by Brian Aker
Removed final my_bool from sql_db.
221
  int error= false;
1966.2.4 by Brian Aker
Style cleanup.
222
  TableIdentifier::vector dropped_tables;
1309.1.8 by Brian Aker
Modest update to drop schema.
223
  message::Schema schema_proto;
1 by brian
clean slate
224
225
  /*
226
    Do not drop database if another thread is holding read lock.
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
227
    Wait for global read lock before acquiring LOCK_create_db.
1 by brian
clean slate
228
    After wait_if_global_read_lock() we have protection against another
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
229
    global read lock. If we would acquire LOCK_create_db first,
1 by brian
clean slate
230
    another thread could step in and get the global read lock before we
231
    reach wait_if_global_read_lock(). If this thread tries the same as we
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
232
    (admin a db), it would then go and wait on LOCK_create_db...
1 by brian
clean slate
233
    Furthermore wait_if_global_read_lock() checks if the current thread
234
    has the global read lock and refuses the operation with
235
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
236
  */
1910.2.3 by Brian Aker
Second pass on move code to global lock encapsulation.
237
  if (session->wait_if_global_read_lock(false, true))
1 by brian
clean slate
238
  {
1259.3.3 by Monty Taylor
Removed last use of my_dir.
239
    return -1;
1 by brian
clean slate
240
  }
241
1387 by Brian Aker
Fix for cases where not all files are removed during a deletion of a schema.
242
  // Lets delete the temporary tables first outside of locks.  
243
  set<string> set_of_names;
1415 by Brian Aker
Mass overhaul to use schema_identifier.
244
  session->doGetTableNames(schema_identifier, set_of_names);
1387 by Brian Aker
Fix for cases where not all files are removed during a deletion of a schema.
245
246
  for (set<string>::iterator iter= set_of_names.begin(); iter != set_of_names.end(); iter++)
247
  {
1415 by Brian Aker
Mass overhaul to use schema_identifier.
248
    TableIdentifier identifier(schema_identifier, *iter, message::Table::TEMPORARY);
1387 by Brian Aker
Fix for cases where not all files are removed during a deletion of a schema.
249
    Table *table= session->find_temporary_table(identifier);
250
    session->close_temporary_table(table);
251
  }
252
1 by brian
clean slate
253
  {
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
254
    boost::mutex::scoped_lock scopedLock(LOCK_create_db);
255
256
    /* See if the schema exists */
257
    if (not plugin::StorageEngine::doesSchemaExist(schema_identifier))
1309.1.8 by Brian Aker
Modest update to drop schema.
258
    {
1954.2.1 by Brian Aker
getSQLPath() modified to take a string so that we can const the table
259
      std::string path;
260
      schema_identifier.getSQLPath(path);
261
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
262
      if (if_exists)
263
      {
264
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
265
                            ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS),
1954.2.1 by Brian Aker
getSQLPath() modified to take a string so that we can const the table
266
                            path.c_str());
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
267
      }
268
      else
269
      {
270
        error= -1;
1954.2.1 by Brian Aker
getSQLPath() modified to take a string so that we can const the table
271
        my_error(ER_DB_DROP_EXISTS, MYF(0), path.c_str());
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
272
        goto exit;
273
      }
1309.1.8 by Brian Aker
Modest update to drop schema.
274
    }
275
    else
1 by brian
clean slate
276
    {
1938.4.11 by Brian Aker
Scoped locks a bit better.
277
      /* After deleting database, remove all cache entries related to schema */
1877.2.8 by Brian Aker
Additional encapsulation
278
      table::Cache::singleton().removeSchema(schema_identifier);
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
279
280
1 by brian
clean slate
281
      error= -1;
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
282
      deleted= drop_tables_via_filenames(session, schema_identifier, dropped_tables);
283
      if (deleted >= 0)
284
      {
285
        error= 0;
286
      }
1 by brian
clean slate
287
    }
1259.3.3 by Monty Taylor
Removed last use of my_dir.
288
    if (deleted >= 0)
1 by brian
clean slate
289
    {
1921.4.13 by Brian Aker
Fix issue where session info might not be correct.
290
      assert(not session->getQueryString()->empty());
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
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;
1 by brian
clean slate
298
    }
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
299
    else
1 by brian
clean slate
300
    {
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
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();
1966.2.4 by Brian Aker
Style cleanup.
309
      for (TableIdentifier::vector::iterator it= dropped_tables.begin();
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
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)
1 by brian
clean slate
331
      {
971.3.2 by Eric Day
Renamed LOCK_drizzleclient_create_db to LOCK_create_db since this has nothing to do with drizzleclient. I think Monty accidently got this during the drizzleclient rename.
332
        /* These DDL methods and logging protected with LOCK_create_db */
1336.2.2 by Jay Pipes
NO CODE CHANGES - Simply moves pieces of ReplicationServices to TransactionServices. Preparation for making the ReplicationServices component only responsible for communication between replicators, appliers, publishers, and subscribers.
333
        transaction_services.rawStatement(session, query);
1 by brian
clean slate
334
      }
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
335
    }
1 by brian
clean slate
336
337
exit:
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
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
    */
1976.5.4 by Brian Aker
Update schema, make sure that it always ruturns a valid string (it just
344
    if (schema_identifier.compare(*session->schema()))
1685.2.14 by Brian Aker
Use boost for the main lock we use in schema creation/alteration.
345
      mysql_change_db_impl(session);
346
  }
347
1910.2.2 by Brian Aker
First pass through the global lock refactor merge.
348
  session->startWaitingGlobalReadLock();
1309.1.8 by Brian Aker
Modest update to drop schema.
349
1259.3.3 by Monty Taylor
Removed last use of my_dir.
350
  return error;
1 by brian
clean slate
351
}
352
1223.4.10 by Brian Aker
Split remove table into 2 parts. The piece for dropDatabase() needs to be
353
354
static int rm_table_part2(Session *session, TableList *tables)
355
{
1736.2.1 by Joseph Daly
remove write_bin_log_drop_table and use transaction_services
356
  TransactionServices &transaction_services= TransactionServices::singleton();
357
1223.4.10 by Brian Aker
Split remove table into 2 parts. The piece for dropDatabase() needs to be
358
  TableList *table;
359
  String wrong_tables;
360
  int error= 0;
361
  bool foreign_key_error= false;
362
1960.1.2 by Brian Aker
Move mutex behind scoped ().
363
  {
364
    table::Cache::singleton().mutex().lock(); /* Part 2 of rm a table */
365
366
    if (session->lock_table_names_exclusively(tables))
367
    {
1938.4.10 by Brian Aker
Convert LOCK_open to lock in mutex
368
      table::Cache::singleton().mutex().unlock();
1960.1.2 by Brian Aker
Move mutex behind scoped ().
369
      return 1;
1223.4.10 by Brian Aker
Split remove table into 2 parts. The piece for dropDatabase() needs to be
370
    }
371
1960.1.2 by Brian Aker
Move mutex behind scoped ().
372
    /* Don't give warnings for not found errors, as we already generate notes */
373
    session->no_warnings_for_error= 1;
1223.4.10 by Brian Aker
Split remove table into 2 parts. The piece for dropDatabase() needs to be
374
1960.1.2 by Brian Aker
Move mutex behind scoped ().
375
    for (table= tables; table; table= table->next_local)
1223.4.10 by Brian Aker
Split remove table into 2 parts. The piece for dropDatabase() needs to be
376
    {
1960.1.2 by Brian Aker
Move mutex behind scoped ().
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;
1910.2.4 by Brian Aker
Push some functions behind classes.
390
        tables->unlock_table_names();
1938.4.10 by Brian Aker
Convert LOCK_open to lock in mutex
391
        table::Cache::singleton().mutex().unlock();
1680.6.2 by Brian Aker
Remove goto within locking code.
392
        session->no_warnings_for_error= 0;
393
394
        return(error);
1960.1.2 by Brian Aker
Move mutex behind scoped ().
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();
1223.4.10 by Brian Aker
Split remove table into 2 parts. The piece for dropDatabase() needs to be
468
  }
1960.1.2 by Brian Aker
Move mutex behind scoped ().
469
1223.4.10 by Brian Aker
Split remove table into 2 parts. The piece for dropDatabase() needs to be
470
  error= 0;
471
  if (wrong_tables.length())
472
  {
1309.2.19 by Brian Aker
Removing cerr call, and fixed bug where tables might not be dropped if there
473
    if (not foreign_key_error)
1223.4.10 by Brian Aker
Split remove table into 2 parts. The piece for dropDatabase() needs to be
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
1960.1.2 by Brian Aker
Move mutex behind scoped ().
483
  {
484
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* final bit in rm table lock */
485
    tables->unlock_table_names();
486
  }
1223.4.10 by Brian Aker
Split remove table into 2 parts. The piece for dropDatabase() needs to be
487
  session->no_warnings_for_error= 0;
488
489
  return(error);
490
}
491
1 by brian
clean slate
492
/*
255 by Brian Aker
Removed RAID table delete point.
493
  Removes files with known extensions plus.
520.1.22 by Brian Aker
Second pass of thd cleanup
494
  session MUST be set when calling this function!
1 by brian
clean slate
495
*/
496
1601 by Brian Aker
Move functions to class methods.
497
static long drop_tables_via_filenames(Session *session,
498
                                      SchemaIdentifier &schema_identifier,
1966.2.4 by Brian Aker
Style cleanup.
499
                                      TableIdentifier::vector &dropped_tables)
1 by brian
clean slate
500
{
1039.1.3 by Brian Aker
Remove dead bits from db create/rm
501
  long deleted= 0;
502
  TableList *tot_list= NULL, **tot_list_next;
1 by brian
clean slate
503
504
  tot_list_next= &tot_list;
505
1663.1.4 by Brian Aker
Removed identifier bit
506
  plugin::StorageEngine::getIdentifiers(*session, schema_identifier, dropped_tables);
1309.1.10 by Brian Aker
Partial pass through replication code.
507
1966.2.4 by Brian Aker
Style cleanup.
508
  for (TableIdentifier::vector::iterator it= dropped_tables.begin();
1309.1.12 by Brian Aker
Cleanup of rm schema;
509
       it != dropped_tables.end();
510
       it++)
1 by brian
clean slate
511
  {
1415 by Brian Aker
Mass overhaul to use schema_identifier.
512
    size_t db_len= schema_identifier.getSchemaName().size();
1309.1.12 by Brian Aker
Cleanup of rm schema;
513
514
    /* Drop the table nicely */
515
    TableList *table_list=(TableList*)
516
      session->calloc(sizeof(*table_list) +
517
                      db_len + 1 +
1663.1.3 by Brian Aker
Remove table names options.
518
                      (*it).getTableName().length() + 1);
1309.1.12 by Brian Aker
Cleanup of rm schema;
519
520
    if (not table_list)
521
      return -1;
522
1874.1.1 by Brian Aker
Encapsulate schema_name it table_list.
523
    table_list->setSchemaName((char*) (table_list+1));
1874.1.2 by Brian Aker
Encapsulate table_name from table_list.
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
1663.1.3 by Brian Aker
Remove table names options.
527
    table_list->setInternalTmpTable((strncmp((*it).getTableName().c_str(),
1309.1.12 by Brian Aker
Cleanup of rm schema;
528
                                             TMP_FILE_PREFIX,
1637.2.6 by Vijay Samuel
Merge encapsulate TableList-1.
529
                                             strlen(TMP_FILE_PREFIX)) == 0));
1309.1.12 by Brian Aker
Cleanup of rm schema;
530
    /* Link into list */
531
    (*tot_list_next)= table_list;
532
    tot_list_next= &table_list->next_local;
533
    deleted++;
1 by brian
clean slate
534
  }
1910.2.8 by Brian Aker
Enapsulate Kill.
535
  if (session->getKilled())
1259.3.3 by Monty Taylor
Removed last use of my_dir.
536
    return -1;
1 by brian
clean slate
537
1223.4.10 by Brian Aker
Split remove table into 2 parts. The piece for dropDatabase() needs to be
538
  if (tot_list)
539
  {
540
    if (rm_table_part2(session, tot_list))
1259.3.3 by Monty Taylor
Removed last use of my_dir.
541
      return -1;
1223.4.10 by Brian Aker
Split remove table into 2 parts. The piece for dropDatabase() needs to be
542
  }
543
1415 by Brian Aker
Mass overhaul to use schema_identifier.
544
545
  if (not plugin::StorageEngine::dropSchema(schema_identifier))
1060.1.1 by Eric Lambert
-removed rm_dir_w_symlink method call with rmdir since dir should not be a sym link in the first place.
546
  {
1954.2.1 by Brian Aker
getSQLPath() modified to take a string so that we can const the table
547
    std::string path;
548
    schema_identifier.getSQLPath(path);
549
    my_error(ER_DROP_SCHEMA, MYF(0), path.c_str());
550
1034.1.5 by Brian Aker
Small refactor of db.cc
551
    return -1;
1060.1.1 by Eric Lambert
-removed rm_dir_w_symlink method call with rmdir since dir should not be a sym link in the first place.
552
  }
1 by brian
clean slate
553
1039.1.3 by Brian Aker
Remove dead bits from db create/rm
554
  return deleted;
1 by brian
clean slate
555
}
556
557
/**
558
  @brief Change the current database and its attributes unconditionally.
559
520.1.22 by Brian Aker
Second pass of thd cleanup
560
  @param session          thread handle
1 by brian
clean slate
561
  @param new_db_name  database name
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
562
  @param force_switch if force_switch is false, then the operation will fail if
1 by brian
clean slate
563
564
                        - new_db_name is NULL or empty;
565
566
                        - OR new database name is invalid
567
                          (check_db_name() failed);
568
569
                        - OR user has no privilege on the new database;
570
571
                        - OR new database does not exist;
572
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
573
                      if force_switch is true, then
1 by brian
clean slate
574
575
                        - if new_db_name is NULL or empty, the current
576
                          database will be NULL, @@collation_database will
577
                          be set to @@collation_server, the operation will
578
                          succeed.
579
580
                        - if new database name is invalid
581
                          (check_db_name() failed), the current database
582
                          will be NULL, @@collation_database will be set to
583
                          @@collation_server, but the operation will fail;
584
585
                        - user privileges will not be checked
520.1.21 by Brian Aker
THD -> Session rename
586
                          (Session::db_access however is updated);
1 by brian
clean slate
587
588
                          TODO: is this really the intention?
589
                                (see sp-security.test).
590
591
                        - if new database does not exist,the current database
592
                          will be NULL, @@collation_database will be set to
593
                          @@collation_server, a warning will be thrown, the
594
                          operation will succeed.
595
596
  @details The function checks that the database name corresponds to a
597
  valid and existent database, checks access rights and changes the current
598
  database with database attributes (@@collation_database session variable,
520.1.21 by Brian Aker
THD -> Session rename
599
  Session::db_access).
1 by brian
clean slate
600
601
  This function is not the only way to switch the database that is
602
  currently employed. When the replication slave thread switches the
520.1.22 by Brian Aker
Second pass of thd cleanup
603
  database before executing a query, it calls session->set_db directly.
1 by brian
clean slate
604
  However, if the query, in turn, uses a stored routine, the stored routine
605
  will use this function, even if it's run on the slave.
606
607
  This function allocates the name of the database on the system heap: this
608
  is necessary to be able to uniformly change the database from any module
609
  of the server. Up to 5.0 different modules were using different memory to
610
  store the name of the database, and this led to memory corruption:
611
  a stack pointer set by Stored Procedures was used by replication after
612
  the stack address was long gone.
613
614
  @return Operation status
51.1.51 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
615
    @retval false Success
616
    @retval true  Error
1 by brian
clean slate
617
*/
618
1415 by Brian Aker
Mass overhaul to use schema_identifier.
619
bool mysql_change_db(Session *session, SchemaIdentifier &schema_identifier)
1 by brian
clean slate
620
{
621
1415 by Brian Aker
Mass overhaul to use schema_identifier.
622
  if (not plugin::Authorization::isAuthorized(session->getSecurityContext(), schema_identifier))
1317.2.2 by Monty Taylor
Prevent unauthorized users from changing schema.
623
  {
624
    /* Error message is set in isAuthorized */
625
    return true;
626
  }
627
1578.4.11 by Brian Aker
PAss through the code removing current_session
628
  if (not check_db_name(session, schema_identifier))
1 by brian
clean slate
629
  {
1954.2.1 by Brian Aker
getSQLPath() modified to take a string so that we can const the table
630
    std::string path;
631
    schema_identifier.getSQLPath(path);
632
    my_error(ER_WRONG_DB_NAME, MYF(0), path.c_str());
1 by brian
clean slate
633
1014.3.3 by Brian Aker
Formating fix.
634
    return true;
1 by brian
clean slate
635
  }
636
1415 by Brian Aker
Mass overhaul to use schema_identifier.
637
  if (not plugin::StorageEngine::doesSchemaExist(schema_identifier))
1 by brian
clean slate
638
  {
1309.1.9 by Brian Aker
Baby steps.
639
    /* Report an error and free new_db_file_name. */
1954.2.1 by Brian Aker
getSQLPath() modified to take a string so that we can const the table
640
    std::string path;
641
    schema_identifier.getSQLPath(path);
1309.1.9 by Brian Aker
Baby steps.
642
1954.2.1 by Brian Aker
getSQLPath() modified to take a string so that we can const the table
643
    my_error(ER_BAD_DB_ERROR, MYF(0), path.c_str());
1309.1.9 by Brian Aker
Baby steps.
644
645
    /* The operation failed. */
646
647
    return true;
1 by brian
clean slate
648
  }
649
1415 by Brian Aker
Mass overhaul to use schema_identifier.
650
  mysql_change_db_impl(session, schema_identifier);
1 by brian
clean slate
651
1014.3.3 by Brian Aker
Formating fix.
652
  return false;
1 by brian
clean slate
653
}
654
1273 by Brian Aker
Revert db patch.
655
/**
656
  @brief Internal implementation: switch current database to a valid one.
657
658
  @param session            Thread context.
659
  @param new_db_name    Name of the database to switch to. The function will
660
                        take ownership of the name (the caller must not free
661
                        the allocated memory). If the name is NULL, we're
662
                        going to switch to NULL db.
663
  @param new_db_charset Character set of the new database.
664
*/
665
1415 by Brian Aker
Mass overhaul to use schema_identifier.
666
static void mysql_change_db_impl(Session *session, SchemaIdentifier &schema_identifier)
1235.4.18 by Stewart Smith
replace check_db_dir_existence() with class DatabasePathName and a ::exists() method.
667
{
1273 by Brian Aker
Revert db patch.
668
  /* 1. Change current database in Session. */
669
1415 by Brian Aker
Mass overhaul to use schema_identifier.
670
#if 0
1273 by Brian Aker
Revert db patch.
671
  if (new_db_name == NULL)
672
  {
673
    /*
674
      Session::set_db() does all the job -- it frees previous database name and
675
      sets the new one.
676
    */
677
678
    session->set_db(NULL, 0);
679
  }
680
  else
1415 by Brian Aker
Mass overhaul to use schema_identifier.
681
#endif
1273 by Brian Aker
Revert db patch.
682
  {
683
    /*
684
      Here we already have a copy of database name to be used in Session. So,
685
      we just call Session::reset_db(). Since Session::reset_db() does not releases
686
      the previous database name, we should do it explicitly.
687
    */
688
1685.2.12 by Brian Aker
This fixes the lower casing of names from Schema even when we should not.
689
    session->set_db(schema_identifier.getSchemaName());
1273 by Brian Aker
Revert db patch.
690
  }
1235.4.18 by Stewart Smith
replace check_db_dir_existence() with class DatabasePathName and a ::exists() method.
691
}
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
692
1415 by Brian Aker
Mass overhaul to use schema_identifier.
693
static void mysql_change_db_impl(Session *session)
694
{
695
  session->set_db(string());
696
}
697
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
698
} /* namespace drizzled */