23
23
#include <drizzled/lock.h>
24
24
#include <drizzled/session.h>
25
25
#include <drizzled/statement/create_table.h>
26
#include <drizzled/message.h>
27
#include <drizzled/identifier.h>
28
#include <drizzled/plugin/storage_engine.h>
26
#include <drizzled/table_identifier.h>
37
CreateTable::CreateTable(Session *in_session, Table_ident *ident, bool is_temporary) :
38
Statement(in_session),
41
on_update_value(NULL),
43
is_create_table_like(false),
44
lex_identified_temp_table(false),
46
create_table_list(NULL)
48
getSession()->getLex()->sql_command= SQLCOM_CREATE_TABLE;
49
createTableMessage().set_name(ident->table.str, ident->table.length);
51
createTableMessage().set_schema(ident->db.str, ident->db.length);
56
createTableMessage().set_type(message::Table::TEMPORARY);
60
createTableMessage().set_type(message::Table::STANDARD);
64
CreateTable::CreateTable(Session *in_session) :
65
Statement(in_session),
68
on_update_value(NULL),
70
is_create_table_like(false),
71
lex_identified_temp_table(false),
73
create_table_list(NULL)
75
getSession()->getLex()->sql_command= SQLCOM_CREATE_TABLE;
78
} // namespace statement
80
31
bool statement::CreateTable::execute()
82
TableList *first_table= (TableList *) getSession()->lex->select_lex.table_list.first;
83
TableList *all_tables= getSession()->lex->query_tables;
33
TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
34
TableList *all_tables= session->lex->query_tables;
84
35
assert(first_table == all_tables && first_table != 0);
36
Select_Lex *select_lex= &session->lex->select_lex;
37
Select_Lex_Unit *unit= &session->lex->unit;
85
38
bool need_start_waiting= false;
86
lex_identified_temp_table= createTableMessage().type() == message::Table::TEMPORARY;
88
is_engine_set= not createTableMessage().engine().name().empty();
40
bool link_to_local= false;
41
bool lex_identified_temp_table=
42
create_table_proto.type() == message::Table::TEMPORARY;
92
create_info().db_type=
93
plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
47
plugin::StorageEngine::findByName(*session, create_table_proto.engine().name());
95
if (create_info().db_type == NULL)
49
if (create_info.db_type == NULL)
97
51
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0),
98
createTableMessage().engine().name().c_str());
52
create_table_proto.name().c_str());
103
57
else /* We now get the default, place it in create_info, and put the engine name in table proto */
105
create_info().db_type= getSession()->getDefaultStorageEngine();
108
if (not validateCreateTableOption())
113
if (not lex_identified_temp_table)
115
if (getSession()->inTransaction())
59
create_info.db_type= session->getDefaultStorageEngine();
64
Now we set the name in our Table proto so that it will match
68
message::Table::StorageEngine *protoengine;
70
protoengine= create_table_proto.mutable_engine();
71
protoengine->set_name(create_info.db_type->getName());
75
/* If CREATE TABLE of non-temporary table, do implicit commit */
76
if (! lex_identified_temp_table)
78
if (! session->endActiveTransaction())
117
my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
121
83
/* Skip first table, which is the table we are creating */
122
create_table_list= getSession()->lex->unlink_first_table(&link_to_local);
124
drizzled::message::table::init(createTableMessage(), createTableMessage().name(), create_table_list->getSchemaName(), create_info().db_type->getName());
126
identifier::Table new_table_identifier(create_table_list->getSchemaName(),
127
create_table_list->getTableName(),
128
createTableMessage().type());
130
if (not check(new_table_identifier))
84
TableList *create_table= session->lex->unlink_first_table(&link_to_local);
85
TableList *select_tables= session->lex->query_tables;
89
Now that we have the engine, we can figure out the table identifier. We need the engine in order
90
to determine if the table is transactional or not if it is temp.
92
TableIdentifier new_table_identifier(create_table->db,
93
create_table->table_name,
94
create_table_proto.type() != message::Table::TEMPORARY ? NO_TMP_TABLE : TEMP_TABLE);
96
if (create_table_precheck(new_table_identifier))
132
98
/* put tables back for PS rexecuting */
133
getSession()->lex->link_first_table_back(create_table_list, link_to_local);
99
session->lex->link_first_table_back(create_table, link_to_local);
137
103
/* Might have been updated in create_table_precheck */
138
create_info().alias= create_table_list->alias;
104
create_info.alias= create_table->alias;
141
107
The create-select command will open and read-lock the select table
150
116
TABLE in the same way. That way we avoid that a new table is
151
117
created during a gobal read lock.
153
if (! (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
119
if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
155
121
/* put tables back for PS rexecuting */
156
getSession()->lex->link_first_table_back(create_table_list, link_to_local);
122
session->lex->link_first_table_back(create_table, link_to_local);
160
bool res= executeInner(new_table_identifier);
163
Release the protection against the global read lock and wake
164
everyone, who might want to set a global read lock.
166
getSession()->startWaitingGlobalReadLock();
171
bool statement::CreateTable::executeInner(identifier::Table::const_reference new_table_identifier)
174
Select_Lex *select_lex= &getSession()->lex->select_lex;
175
TableList *select_tables= getSession()->lex->query_tables;
126
if (select_lex->item_list.elements) // With select
179
if (select_lex->item_list.elements) // With select
181
Select_Lex_Unit *unit= &getSession()->lex->unit;
182
select_result *result;
184
select_lex->options|= SELECT_NO_UNLOCK;
185
unit->set_limit(select_lex);
187
if (not lex_identified_temp_table)
189
getSession()->lex->link_first_table_back(create_table_list, link_to_local);
190
create_table_list->setCreate(true);
193
if (not (res= getSession()->openTablesLock(getSession()->lex->query_tables)))
196
Is table which we are changing used somewhere in other parts
199
if (not lex_identified_temp_table)
201
TableList *duplicate= NULL;
202
create_table_list= getSession()->lex->unlink_first_table(&link_to_local);
204
if ((duplicate= unique_table(create_table_list, select_tables)))
206
my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table_list->alias);
207
/* put tables back for PS rexecuting */
208
getSession()->lex->link_first_table_back(create_table_list, link_to_local);
216
select_create is currently not re-execution friendly and
217
needs to be created for every execution of a PS/SP.
219
if ((result= new select_create(create_table_list,
220
getSession()->getLex()->exists(),
222
createTableMessage(),
224
select_lex->item_list,
225
getSession()->lex->duplicates,
226
getSession()->lex->ignore,
228
new_table_identifier)))
128
select_result *result;
130
select_lex->options|= SELECT_NO_UNLOCK;
131
unit->set_limit(select_lex);
133
if (! lex_identified_temp_table)
135
session->lex->link_first_table_back(create_table, link_to_local);
136
create_table->create= true;
139
if (! (res= session->openTablesLock(session->lex->query_tables)))
142
Is table which we are changing used somewhere in other parts
145
if (! lex_identified_temp_table)
147
TableList *duplicate= NULL;
148
create_table= session->lex->unlink_first_table(&link_to_local);
149
if ((duplicate= unique_table(create_table, select_tables)))
151
my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->alias);
231
CREATE from SELECT give its Select_Lex for SELECT,
232
and item_list belong to SELECT
234
res= handle_select(getSession(), getSession()->lex, result, 0);
153
Release the protection against the global read lock and wake
154
everyone, who might want to set a global read lock.
156
start_waiting_global_read_lock(session);
157
/* put tables back for PS rexecuting */
158
session->lex->link_first_table_back(create_table, link_to_local);
238
else if (not lex_identified_temp_table)
164
select_create is currently not re-execution friendly and
165
needs to be created for every execution of a PS/SP.
167
if ((result= new select_create(create_table,
172
select_lex->item_list,
173
session->lex->duplicates,
174
session->lex->ignore,
240
create_table_list= getSession()->lex->unlink_first_table(&link_to_local);
178
CREATE from SELECT give its Select_Lex for SELECT,
179
and item_list belong to SELECT
181
res= handle_select(session, session->lex, result, 0);
185
else if (! lex_identified_temp_table)
187
create_table= session->lex->unlink_first_table(&link_to_local);
193
if (is_create_table_like)
195
res= mysql_create_like_table(session,
246
if (is_create_table_like)
248
res= create_like_table(getSession(),
249
new_table_identifier,
250
identifier::Table(select_tables->getSchemaName(),
251
select_tables->getTableName()),
252
createTableMessage(),
253
getSession()->getLex()->exists(),
259
for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
261
message::Table::Field *field= createTableMessage().add_field();
263
*field= alter_info.alter_proto.added_field(x);
266
res= create_table(getSession(),
267
new_table_identifier,
269
createTableMessage(),
273
getSession()->getLex()->exists());
278
getSession()->my_ok();
206
for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
208
message::Table::Field *field= create_table_proto.add_field();
210
*field= alter_info.alter_proto.added_field(x);
213
res= mysql_create_table(session,
214
new_table_identifier,
229
Release the protection against the global read lock and wake
230
everyone, who might want to set a global read lock.
232
start_waiting_global_read_lock(session);
286
bool statement::CreateTable::check(const identifier::Table &identifier)
288
// Check table name for validity
289
if (not identifier.isValid())
292
// See if any storage engine objects to the name of the file
293
if (not plugin::StorageEngine::canCreateTable(identifier))
295
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", identifier.getSchemaName().c_str());
300
// Make sure the schema exists, we will do this again during the actual
301
// create for the table.
302
if (not plugin::StorageEngine::doesSchemaExist(identifier))
304
my_error(ER_BAD_DB_ERROR, MYF(0), identifier.getSchemaName().c_str());
312
bool statement::CreateTable::validateCreateTableOption()
315
size_t num_engine_options= createTableMessage().engine().options_size();
317
assert(create_info().db_type);
319
for (size_t y= 0; y < num_engine_options; ++y)
321
bool valid= create_info().db_type->validateCreateTableOption(createTableMessage().engine().options(y).name(),
322
createTableMessage().engine().options(y).state());
326
my_error(ER_UNKNOWN_ENGINE_OPTION, MYF(0),
327
createTableMessage().engine().options(y).name().c_str(),
328
createTableMessage().engine().options(y).state().c_str());
337
237
} /* namespace drizzled */