~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/plugin/schema_engine.cc

Refactor

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