~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-07-07 13:41:07 UTC
  • mto: This revision was merged to the branch mainline in revision 2385.
  • Revision ID: olafvdspek@gmail.com-20110707134107-6mi7pauiatxtf4oe
Rename strmake to strdup (standard name)

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