~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/db.cc

  • Committer: Brian Aker
  • Date: 2011-01-06 05:17:09 UTC
  • Revision ID: brian@tangent.org-20110106051709-oa0se8ur02uc6i9o
Added native functions into the function table.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
 
17
17
/* create and drop of databases */
18
 
#include <config.h>
 
18
#include "config.h"
19
19
 
20
20
#include <fcntl.h>
21
21
#include <sys/stat.h>
25
25
#include <string>
26
26
#include <fstream>
27
27
 
28
 
#include <drizzled/error.h>
 
28
#include <drizzled/message/schema.pb.h>
 
29
#include "drizzled/error.h"
29
30
#include <drizzled/gettext.h>
30
31
#include <drizzled/my_hash.h>
31
 
#include <drizzled/internal/m_string.h>
 
32
#include "drizzled/internal/m_string.h"
32
33
#include <drizzled/session.h>
33
 
#include <drizzled/schema.h>
 
34
#include <drizzled/db.h>
34
35
#include <drizzled/sql_base.h>
35
36
#include <drizzled/lock.h>
36
37
#include <drizzled/errmsg_print.h>
37
38
#include <drizzled/transaction_services.h>
38
39
#include <drizzled/message/schema.pb.h>
39
 
#include <drizzled/sql_table.h>
40
 
#include <drizzled/plugin/storage_engine.h>
41
 
#include <drizzled/plugin/authorization.h>
42
 
#include <drizzled/global_charset_info.h>
43
 
#include <drizzled/pthread_globals.h>
44
 
#include <drizzled/charset.h>
45
 
#include <drizzled/internal/my_sys.h>
 
40
#include "drizzled/sql_table.h"
 
41
#include "drizzled/plugin/storage_engine.h"
 
42
#include "drizzled/plugin/authorization.h"
 
43
#include "drizzled/global_charset_info.h"
 
44
#include "drizzled/pthread_globals.h"
 
45
#include "drizzled/charset.h"
46
46
 
47
47
#include <boost/thread/mutex.hpp>
48
48
 
 
49
boost::mutex LOCK_create_db;
 
50
 
 
51
#include "drizzled/internal/my_sys.h"
 
52
 
49
53
#define MAX_DROP_TABLE_Q_LEN      1024
50
54
 
51
55
using namespace std;
53
57
namespace drizzled
54
58
{
55
59
 
56
 
namespace schema
57
 
{
58
 
 
59
 
static void change_db_impl(Session &session);
60
 
static void change_db_impl(Session &session, identifier::Schema &schema_identifier);
 
60
static void change_db_impl(Session *session);
 
61
static void change_db_impl(Session *session, SchemaIdentifier &schema_identifier);
61
62
 
62
63
/*
63
64
  Create a database
80
81
 
81
82
*/
82
83
 
83
 
bool create(Session &session, const message::Schema &schema_message, const bool is_if_not_exists)
 
84
bool create_db(Session *session, const message::Schema &schema_message, const bool is_if_not_exists)
84
85
{
85
86
  TransactionServices &transaction_services= TransactionServices::singleton();
86
87
  bool error= false;
87
88
 
88
89
  /*
89
90
    Do not create database if another thread is holding read lock.
90
 
    Wait for global read lock before acquiring session->catalog()->schemaLock().
 
91
    Wait for global read lock before acquiring LOCK_create_db.
91
92
    After wait_if_global_read_lock() we have protection against another
92
 
    global read lock. If we would acquire session->catalog()->schemaLock() first,
 
93
    global read lock. If we would acquire LOCK_create_db first,
93
94
    another thread could step in and get the global read lock before we
94
95
    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()...
 
96
    (admin a db), it would then go and wait on LOCK_create_db...
96
97
    Furthermore wait_if_global_read_lock() checks if the current thread
97
98
    has the global read lock and refuses the operation with
98
99
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
99
100
  */
100
 
  if (session.wait_if_global_read_lock(false, true))
 
101
  if (session->wait_if_global_read_lock(false, true))
101
102
  {
102
103
    return false;
103
104
  }
107
108
 
108
109
  // @todo push this lock down into the engine
109
110
  {
110
 
    boost::mutex::scoped_lock scopedLock(session.catalog().schemaLock());
 
111
    boost::mutex::scoped_lock scopedLock(LOCK_create_db);
111
112
 
112
113
    // Check to see if it exists already.  
113
 
    identifier::Schema schema_identifier(schema_message.name());
 
114
    SchemaIdentifier schema_identifier(schema_message.name());
114
115
    if (plugin::StorageEngine::doesSchemaExist(schema_identifier))
115
116
    {
116
117
      if (not is_if_not_exists)
120
121
      }
121
122
      else
122
123
      {
123
 
        push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
124
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
124
125
                            ER_DB_CREATE_EXISTS, ER(ER_DB_CREATE_EXISTS),
125
126
                            schema_message.name().c_str());
126
 
        session.my_ok();
 
127
        session->my_ok();
127
128
      }
128
129
    }
129
130
    else if (not plugin::StorageEngine::createSchema(schema_message)) // Try to create it 
134
135
    else // Created !
135
136
    {
136
137
      transaction_services.createSchema(session, schema_message);
137
 
      session.my_ok(1);
 
138
      session->my_ok(1);
138
139
    }
139
140
  }
140
 
  session.startWaitingGlobalReadLock();
 
141
  session->startWaitingGlobalReadLock();
141
142
 
142
143
  return error;
143
144
}
145
146
 
146
147
/* db-name is already validated when we come here */
147
148
 
148
 
bool alter(Session &session,
149
 
           const message::Schema &schema_message,
150
 
           const message::Schema &original_schema)
 
149
bool alter_db(Session *session, const message::Schema &schema_message)
151
150
{
152
151
  TransactionServices &transaction_services= TransactionServices::singleton();
153
152
 
154
153
  /*
155
154
    Do not alter database if another thread is holding read lock.
156
 
    Wait for global read lock before acquiring session->catalog()->schemaLock().
 
155
    Wait for global read lock before acquiring LOCK_create_db.
157
156
    After wait_if_global_read_lock() we have protection against another
158
 
    global read lock. If we would acquire session->catalog()->schemaLock() first,
 
157
    global read lock. If we would acquire LOCK_create_db first,
159
158
    another thread could step in and get the global read lock before we
160
159
    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()...
 
160
    (admin a db), it would then go and wait on LOCK_create_db...
162
161
    Furthermore wait_if_global_read_lock() checks if the current thread
163
162
    has the global read lock and refuses the operation with
164
163
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
165
164
  */
166
 
  if ((session.wait_if_global_read_lock(false, true)))
 
165
  if ((session->wait_if_global_read_lock(false, true)))
167
166
    return false;
168
167
 
169
168
  bool success;
170
169
  {
171
 
    boost::mutex::scoped_lock scopedLock(session.catalog().schemaLock());
 
170
    boost::mutex::scoped_lock scopedLock(LOCK_create_db);
172
171
 
173
 
    identifier::Schema schema_idenifier(schema_message.name());
 
172
    SchemaIdentifier schema_idenifier(schema_message.name());
174
173
    if (not plugin::StorageEngine::doesSchemaExist(schema_idenifier))
175
174
    {
176
175
      my_error(ER_SCHEMA_DOES_NOT_EXIST, schema_idenifier);
182
181
 
183
182
    if (success)
184
183
    {
185
 
      transaction_services.alterSchema(session, original_schema, schema_message);
186
 
      session.my_ok(1);
 
184
      transaction_services.rawStatement(session, *session->getQueryString());
 
185
      session->my_ok(1);
187
186
    }
188
187
    else
189
188
    {
190
189
      my_error(ER_ALTER_SCHEMA, schema_idenifier);
191
190
    }
192
191
  }
193
 
  session.startWaitingGlobalReadLock();
 
192
  session->startWaitingGlobalReadLock();
194
193
 
195
194
  return success;
196
195
}
213
212
    ERROR Error
214
213
*/
215
214
 
216
 
bool drop(Session &session, identifier::Schema &schema_identifier, const bool if_exists)
 
215
bool rm_db(Session *session, SchemaIdentifier &schema_identifier, const bool if_exists)
217
216
{
218
217
  bool error= false;
219
218
 
220
219
  /*
221
220
    Do not drop database if another thread is holding read lock.
222
 
    Wait for global read lock before acquiring session->catalog()->schemaLock().
 
221
    Wait for global read lock before acquiring LOCK_create_db.
223
222
    After wait_if_global_read_lock() we have protection against another
224
 
    global read lock. If we would acquire session->catalog()->schemaLock() first,
 
223
    global read lock. If we would acquire LOCK_create_db first,
225
224
    another thread could step in and get the global read lock before we
226
225
    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()...
 
226
    (admin a db), it would then go and wait on LOCK_create_db...
228
227
    Furthermore wait_if_global_read_lock() checks if the current thread
229
228
    has the global read lock and refuses the operation with
230
229
    ER_CANT_UPDATE_WITH_READLOCK if applicable.
231
230
  */
232
 
  if (session.wait_if_global_read_lock(false, true))
 
231
  if (session->wait_if_global_read_lock(false, true))
233
232
  {
234
233
    return true;
235
234
  }
236
235
 
237
236
  do
238
237
  {
239
 
    boost::mutex::scoped_lock scopedLock(session.catalog().schemaLock());
240
 
    message::schema::shared_ptr message= plugin::StorageEngine::getSchemaDefinition(schema_identifier);
 
238
    boost::mutex::scoped_lock scopedLock(LOCK_create_db);
241
239
 
242
240
    /* See if the schema exists */
243
 
    if (not message)
 
241
    if (not plugin::StorageEngine::doesSchemaExist(schema_identifier))
244
242
    {
 
243
      std::string path;
 
244
      schema_identifier.getSQLPath(path);
 
245
 
245
246
      if (if_exists)
246
247
      {
247
 
        std::string path;
248
 
        schema_identifier.getSQLPath(path);
249
 
 
250
 
        push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
 
248
        push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
251
249
                            ER_DB_DROP_EXISTS, ER(ER_DB_DROP_EXISTS),
252
250
                            path.c_str());
253
251
      }
260
258
    }
261
259
    else
262
260
    {
263
 
      error= plugin::StorageEngine::dropSchema(session, schema_identifier, *message);
 
261
      error= plugin::StorageEngine::dropSchema(*session, schema_identifier);
264
262
    }
265
263
 
266
264
  } while (0);
271
269
    SELECT DATABASE() in the future). For this we free() session->db and set
272
270
    it to 0.
273
271
  */
274
 
  if (not error and schema_identifier.compare(*session.schema()))
 
272
  if (not error and schema_identifier.compare(*session->schema()))
275
273
    change_db_impl(session);
276
274
 
277
 
  session.startWaitingGlobalReadLock();
 
275
  session->startWaitingGlobalReadLock();
278
276
 
279
277
  return error;
280
278
}
341
339
    @retval true  Error
342
340
*/
343
341
 
344
 
bool change(Session &session, identifier::Schema &schema_identifier)
 
342
bool change_db(Session *session, SchemaIdentifier &schema_identifier)
345
343
{
346
344
 
347
 
  if (not plugin::Authorization::isAuthorized(*session.user(), schema_identifier))
 
345
  if (not plugin::Authorization::isAuthorized(session->user(), schema_identifier))
348
346
  {
349
347
    /* Error message is set in isAuthorized */
350
348
    return true;
351
349
  }
352
350
 
353
 
  if (not check(session, schema_identifier))
 
351
  if (not check_db_name(session, schema_identifier))
354
352
  {
 
353
    std::string path;
 
354
    schema_identifier.getSQLPath(path);
355
355
    my_error(ER_WRONG_DB_NAME, schema_identifier);
356
356
 
357
357
    return true;
382
382
  @param new_db_charset Character set of the new database.
383
383
*/
384
384
 
385
 
static void change_db_impl(Session &session, identifier::Schema &schema_identifier)
 
385
static void change_db_impl(Session *session, SchemaIdentifier &schema_identifier)
386
386
{
387
387
  /* 1. Change current database in Session. */
388
388
 
405
405
      the previous database name, we should do it explicitly.
406
406
    */
407
407
 
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 */
 
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
}
440
416
 
441
417
} /* namespace drizzled */