~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/schema_engine.cc

  • Committer: Olaf van der Spek
  • Date: 2011-03-28 14:32:36 UTC
  • mto: (2257.1.1 build) (2276.1.2 build)
  • mto: This revision was merged to the branch mainline in revision 2258.
  • Revision ID: olafvdspek@gmail.com-20110328143236-4ge1d793iqaktfq0
Common fwd

Show diffs side-by-side

added added

removed removed

Lines of Context:
17
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
18
 */
19
19
 
20
 
#include "config.h"
21
 
 
22
 
#include "drizzled/session.h"
23
 
 
24
 
#include "drizzled/global_charset_info.h"
25
 
#include "drizzled/charset.h"
26
 
#include "drizzled/transaction_services.h"
27
 
 
28
 
#include "drizzled/plugin/storage_engine.h"
29
 
#include "drizzled/plugin/authorization.h"
 
20
#include <config.h>
 
21
 
 
22
#include <drizzled/session.h>
 
23
#include <drizzled/sql_base.h>
 
24
#include <drizzled/global_charset_info.h>
 
25
#include <drizzled/charset.h>
 
26
#include <drizzled/transaction_services.h>
 
27
 
 
28
#include <drizzled/plugin/storage_engine.h>
 
29
#include <drizzled/plugin/authorization.h>
30
30
 
31
31
namespace drizzled
32
32
{
34
34
namespace plugin
35
35
{
36
36
 
37
 
class AddSchemaNames : 
 
37
class AddSchemaNames :
38
38
  public std::unary_function<StorageEngine *, void>
39
39
{
40
 
  SchemaIdentifier::vector &schemas;
 
40
  identifier::Schema::vector &schemas;
41
41
 
42
42
public:
43
43
 
44
 
  AddSchemaNames(SchemaIdentifier::vector &of_names) :
 
44
  AddSchemaNames(identifier::Schema::vector &of_names) :
45
45
    schemas(of_names)
46
46
  {
47
47
  }
52
52
  }
53
53
};
54
54
 
55
 
void StorageEngine::getIdentifiers(Session &session, SchemaIdentifier::vector &schemas)
 
55
void StorageEngine::getIdentifiers(Session &session, identifier::Schema::vector &schemas)
56
56
{
57
57
  // Add hook here for engines to register schema.
58
58
  std::for_each(StorageEngine::getSchemaEngines().begin(), StorageEngine::getSchemaEngines().end(),
59
59
           AddSchemaNames(schemas));
60
60
 
61
 
  plugin::Authorization::pruneSchemaNames(session.user(), schemas);
 
61
  plugin::Authorization::pruneSchemaNames(*session.user(), schemas);
62
62
}
63
63
 
64
64
class StorageEngineGetSchemaDefinition: public std::unary_function<StorageEngine *, bool>
65
65
{
66
 
  const SchemaIdentifier &identifier;
 
66
  const identifier::Schema &identifier;
67
67
  message::schema::shared_ptr &schema_proto;
68
68
 
69
69
public:
70
 
  StorageEngineGetSchemaDefinition(const SchemaIdentifier &identifier_arg,
 
70
  StorageEngineGetSchemaDefinition(const identifier::Schema &identifier_arg,
71
71
                                   message::schema::shared_ptr &schema_proto_arg) :
72
72
    identifier(identifier_arg),
73
 
    schema_proto(schema_proto_arg) 
 
73
    schema_proto(schema_proto_arg)
74
74
  {
75
75
  }
76
76
 
77
77
  result_type operator() (argument_type engine)
78
78
  {
79
 
    return engine->doGetSchemaDefinition(identifier, schema_proto);
 
79
    schema_proto= engine->doGetSchemaDefinition(identifier);
 
80
    return schema_proto;
80
81
  }
81
82
};
82
83
 
83
84
/*
84
85
  Return value is "if parsed"
85
86
*/
86
 
bool StorageEngine::getSchemaDefinition(const drizzled::TableIdentifier &identifier, message::schema::shared_ptr &proto)
 
87
message::schema::shared_ptr StorageEngine::getSchemaDefinition(const drizzled::identifier::Table &identifier)
87
88
{
88
 
  return StorageEngine::getSchemaDefinition(identifier, proto);
 
89
  identifier::Schema schema_identifier= identifier;
 
90
  return StorageEngine::getSchemaDefinition(schema_identifier);
89
91
}
90
92
 
91
 
bool StorageEngine::getSchemaDefinition(const SchemaIdentifier &identifier, message::schema::shared_ptr &proto)
 
93
message::schema::shared_ptr StorageEngine::getSchemaDefinition(const identifier::Schema &identifier)
92
94
{
 
95
  message::schema::shared_ptr proto;
 
96
 
93
97
  EngineVector::iterator iter=
94
98
    std::find_if(StorageEngine::getSchemaEngines().begin(), StorageEngine::getSchemaEngines().end(),
95
99
                 StorageEngineGetSchemaDefinition(identifier, proto));
96
100
 
97
101
  if (iter != StorageEngine::getSchemaEngines().end())
98
102
  {
99
 
    return true;
 
103
    return proto;
100
104
  }
101
105
 
102
 
  return false;
 
106
  return message::schema::shared_ptr();
103
107
}
104
108
 
105
 
bool StorageEngine::doesSchemaExist(const SchemaIdentifier &identifier)
 
109
bool StorageEngine::doesSchemaExist(const identifier::Schema &identifier)
106
110
{
107
111
  message::schema::shared_ptr proto;
108
112
 
109
 
  return StorageEngine::getSchemaDefinition(identifier, proto);
 
113
  return StorageEngine::getSchemaDefinition(identifier);
110
114
}
111
115
 
112
116
 
113
 
const CHARSET_INFO *StorageEngine::getSchemaCollation(const SchemaIdentifier &identifier)
 
117
const charset_info_st *StorageEngine::getSchemaCollation(const identifier::Schema &identifier)
114
118
{
115
 
  message::schema::shared_ptr schmema_proto;
116
 
  bool found;
117
 
 
118
 
  found= StorageEngine::getSchemaDefinition(identifier, schmema_proto);
119
 
 
120
 
  if (found && schmema_proto->has_collation())
121
 
  {
122
 
    const std::string buffer= schmema_proto->collation();
123
 
    const CHARSET_INFO* cs= get_charset_by_name(buffer.c_str());
124
 
 
125
 
    if (not cs)
126
 
    {
127
 
      std::string path;
128
 
      identifier.getSQLPath(path);
129
 
 
130
 
      errmsg_printf(ERRMSG_LVL_ERROR,
131
 
                    _("Error while loading database options: '%s':"), path.c_str());
132
 
      errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_UNKNOWN_COLLATION), buffer.c_str());
133
 
 
134
 
      return default_charset_info;
135
 
    }
136
 
 
137
 
    return cs;
138
 
  }
139
 
 
 
119
  message::schema::shared_ptr schmema_proto= StorageEngine::getSchemaDefinition(identifier);
 
120
  if (not schmema_proto || not schmema_proto->has_collation())
 
121
                return default_charset_info;
 
122
  const std::string buffer= schmema_proto->collation();
 
123
  if (const charset_info_st* cs= get_charset_by_name(buffer.c_str()))
 
124
                return cs;
 
125
  errmsg_printf(error::ERROR, _("Error while loading database options: '%s':"), identifier.getSQLPath().c_str());
 
126
  errmsg_printf(error::ERROR, ER(ER_UNKNOWN_COLLATION), buffer.c_str());
140
127
  return default_charset_info;
141
128
}
142
129
 
143
 
class CreateSchema : 
 
130
class CreateSchema :
144
131
  public std::unary_function<StorageEngine *, void>
145
132
{
146
133
  const drizzled::message::Schema &schema_message;
 
134
  uint64_t &success_count;
147
135
 
148
136
public:
149
137
 
150
 
  CreateSchema(const drizzled::message::Schema &arg) :
151
 
    schema_message(arg)
 
138
  CreateSchema(const drizzled::message::Schema &arg, uint64_t &success_count_arg) :
 
139
    schema_message(arg),
 
140
    success_count(success_count_arg)
152
141
  {
153
142
  }
154
143
 
157
146
    // @todo eomeday check that at least one engine said "true"
158
147
    bool success= engine->doCreateSchema(schema_message);
159
148
 
160
 
    if (success) 
 
149
    if (success)
161
150
    {
 
151
      success_count++;
162
152
      TransactionServices &transaction_services= TransactionServices::singleton();
163
153
      transaction_services.allocateNewTransactionId();
164
154
    }
168
158
bool StorageEngine::createSchema(const drizzled::message::Schema &schema_message)
169
159
{
170
160
  // Add hook here for engines to register schema.
 
161
  uint64_t success_count= 0;
171
162
  std::for_each(StorageEngine::getSchemaEngines().begin(), StorageEngine::getSchemaEngines().end(),
172
 
                CreateSchema(schema_message));
173
 
 
174
 
  return true;
 
163
                CreateSchema(schema_message, success_count));
 
164
 
 
165
  if (success_count)
 
166
  {
 
167
    TransactionServices &transaction_services= TransactionServices::singleton();
 
168
    transaction_services.allocateNewTransactionId();
 
169
  }
 
170
 
 
171
  return (bool)success_count;
175
172
}
176
173
 
177
 
class DropSchema : 
 
174
class DropSchema :
178
175
  public std::unary_function<StorageEngine *, void>
179
176
{
180
177
  uint64_t &success_count;
181
 
  const SchemaIdentifier &identifier;
 
178
  const identifier::Schema &identifier;
182
179
 
183
180
public:
184
181
 
185
 
  DropSchema(const SchemaIdentifier &arg, uint64_t &count_arg) :
 
182
  DropSchema(const identifier::Schema &arg, uint64_t &count_arg) :
186
183
    success_count(count_arg),
187
184
    identifier(arg)
188
185
  {
202
199
  }
203
200
};
204
201
 
205
 
bool StorageEngine::dropSchema(const SchemaIdentifier &identifier)
206
 
{
207
 
  uint64_t counter= 0;
208
 
  // Add hook here for engines to register schema.
209
 
  std::for_each(StorageEngine::getSchemaEngines().begin(), StorageEngine::getSchemaEngines().end(),
210
 
                DropSchema(identifier, counter));
211
 
 
212
 
  return counter ? true : false;
213
 
}
214
 
 
215
 
class AlterSchema : 
 
202
static bool drop_all_tables_in_schema(Session& session,
 
203
                                      const identifier::Schema& identifier,
 
204
                                      identifier::Table::vector &dropped_tables,
 
205
                                      uint64_t &deleted)
 
206
{
 
207
  TransactionServices &transaction_services= TransactionServices::singleton();
 
208
 
 
209
  plugin::StorageEngine::getIdentifiers(session, identifier, dropped_tables);
 
210
 
 
211
  for (identifier::Table::vector::iterator it= dropped_tables.begin();
 
212
       it != dropped_tables.end();
 
213
       it++)
 
214
  {
 
215
    boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
 
216
 
 
217
    message::table::shared_ptr message= StorageEngine::getTableMessage(session, *it, false);
 
218
    if (not message)
 
219
    {
 
220
      my_error(ER_TABLE_DROP, *it);
 
221
      return false;
 
222
    }
 
223
 
 
224
    table::Cache::singleton().removeTable(&session, *it,
 
225
                                          RTFC_WAIT_OTHER_THREAD_FLAG |
 
226
                                          RTFC_CHECK_KILLED_FLAG);
 
227
    if (not plugin::StorageEngine::dropTable(session, *it))
 
228
    {
 
229
      my_error(ER_TABLE_DROP, *it);
 
230
      return false;
 
231
    }
 
232
    transaction_services.dropTable(session, *it, *message, true);
 
233
    deleted++;
 
234
  }
 
235
 
 
236
  return true;
 
237
}
 
238
 
 
239
bool StorageEngine::dropSchema(Session& session,
 
240
                               const identifier::Schema& identifier,
 
241
                               message::schema::const_reference schema_message)
 
242
{
 
243
  uint64_t deleted= 0;
 
244
  bool error= false;
 
245
  identifier::Table::vector dropped_tables;
 
246
 
 
247
  do
 
248
  {
 
249
    // Remove all temp tables first, this prevents loss of table from
 
250
    // shadowing (ie temp over standard table)
 
251
    {
 
252
      // Lets delete the temporary tables first outside of locks.
 
253
      identifier::Table::vector set_of_identifiers;
 
254
      session.doGetTableIdentifiers(identifier, set_of_identifiers);
 
255
 
 
256
      for (identifier::Table::vector::iterator iter= set_of_identifiers.begin(); iter != set_of_identifiers.end(); iter++)
 
257
      {
 
258
        if (session.drop_temporary_table(*iter))
 
259
        {
 
260
          my_error(ER_TABLE_DROP, *iter);
 
261
          error= true;
 
262
          break;
 
263
        }
 
264
      }
 
265
    }
 
266
 
 
267
    /* After deleting database, remove all cache entries related to schema */
 
268
    table::Cache::singleton().removeSchema(identifier);
 
269
 
 
270
    if (not drop_all_tables_in_schema(session, identifier, dropped_tables, deleted))
 
271
    {
 
272
      error= true;
 
273
      my_error(ER_DROP_SCHEMA, identifier);
 
274
      break;
 
275
    }
 
276
 
 
277
    uint64_t counter= 0;
 
278
    // Add hook here for engines to register schema.
 
279
    std::for_each(StorageEngine::getSchemaEngines().begin(), StorageEngine::getSchemaEngines().end(),
 
280
                  DropSchema(identifier, counter));
 
281
 
 
282
    if (not counter)
 
283
    {
 
284
      my_error(ER_DROP_SCHEMA, identifier);
 
285
      error= true;
 
286
 
 
287
      break;
 
288
    }
 
289
    else
 
290
    {
 
291
      /* We've already verified that the schema does exist, so safe to log it */
 
292
      TransactionServices &transaction_services= TransactionServices::singleton();
 
293
      transaction_services.dropSchema(session, identifier, schema_message);
 
294
    }
 
295
  } while (0);
 
296
 
 
297
  if (deleted > 0)
 
298
  {
 
299
    session.clear_error();
 
300
    session.server_status|= SERVER_STATUS_DB_DROPPED;
 
301
    session.my_ok((uint32_t) deleted);
 
302
    session.server_status&= ~SERVER_STATUS_DB_DROPPED;
 
303
  }
 
304
 
 
305
 
 
306
  return error;
 
307
}
 
308
 
 
309
class AlterSchema :
216
310
  public std::unary_function<StorageEngine *, void>
217
311
{
218
312
  uint64_t &success_count;
235
329
    if (success)
236
330
    {
237
331
      success_count++;
238
 
      TransactionServices &transaction_services= TransactionServices::singleton();
239
 
      transaction_services.allocateNewTransactionId();
240
332
    }
241
333
  }
242
334
};
248
340
  std::for_each(StorageEngine::getSchemaEngines().begin(), StorageEngine::getSchemaEngines().end(),
249
341
                AlterSchema(schema_message, success_count));
250
342
 
 
343
  if (success_count)
 
344
  {
 
345
    TransactionServices &transaction_services= TransactionServices::singleton();
 
346
    transaction_services.allocateNewTransactionId();
 
347
  }
 
348
 
251
349
  return success_count ? true : false;
252
350
}
253
351