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
26
#include <drizzled/identifier.h>
28
#include <drizzled/plugin/storage_engine.h>
30
28
#include <iostream>
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
33
bool statement::CreateTable::execute()
82
TableList *first_table= (TableList *) getSession()->lex->select_lex.table_list.first;
83
TableList *all_tables= getSession()->lex->query_tables;
35
TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
36
TableList *all_tables= session->lex->query_tables;
84
37
assert(first_table == all_tables && first_table != 0);
38
Select_Lex *select_lex= &session->lex->select_lex;
39
Select_Lex_Unit *unit= &session->lex->unit;
85
40
bool need_start_waiting= false;
86
lex_identified_temp_table= createTableMessage().type() == message::Table::TEMPORARY;
88
is_engine_set= not createTableMessage().engine().name().empty();
42
bool link_to_local= false;
43
bool lex_identified_temp_table=
44
create_table_message.type() == message::Table::TEMPORARY;
92
create_info().db_type=
93
plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
49
plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
95
if (create_info().db_type == NULL)
51
if (create_info.db_type == NULL)
97
53
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0),
98
createTableMessage().engine().name().c_str());
54
create_table_message.engine().name().c_str());
103
59
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();
61
create_info.db_type= session->getDefaultStorageEngine();
108
64
if (not validateCreateTableOption())
70
Now we set the name in our Table proto so that it will match
74
create_table_message.mutable_engine()->set_name(create_info.db_type->getName());
78
/* If CREATE TABLE of non-temporary table, do implicit commit */
113
79
if (not lex_identified_temp_table)
115
if (getSession()->inTransaction())
81
if (not session->endActiveTransaction())
117
my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
121
86
/* 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))
87
TableList *create_table= session->lex->unlink_first_table(&link_to_local);
88
TableList *select_tables= session->lex->query_tables;
92
Now that we have the engine, we can figure out the table identifier. We need the engine in order
93
to determine if the table is transactional or not if it is temp.
96
create_table_message.set_schema(create_table->db);
98
TableIdentifier new_table_identifier(create_table->db,
99
create_table->table_name,
100
create_table_message.type());
102
if (create_table_precheck(new_table_identifier))
132
104
/* put tables back for PS rexecuting */
133
getSession()->lex->link_first_table_back(create_table_list, link_to_local);
105
session->lex->link_first_table_back(create_table, link_to_local);
137
109
/* Might have been updated in create_table_precheck */
138
create_info().alias= create_table_list->alias;
110
create_info.alias= create_table->alias;
141
113
The create-select command will open and read-lock the select table
150
122
TABLE in the same way. That way we avoid that a new table is
151
123
created during a gobal read lock.
153
if (! (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
125
if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
155
127
/* put tables back for PS rexecuting */
156
getSession()->lex->link_first_table_back(create_table_list, link_to_local);
128
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;
132
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);
134
select_result *result;
136
select_lex->options|= SELECT_NO_UNLOCK;
137
unit->set_limit(select_lex);
139
if (not lex_identified_temp_table)
141
session->lex->link_first_table_back(create_table, link_to_local);
142
create_table->setCreate(true);
145
if (not (res= session->openTablesLock(session->lex->query_tables)))
148
Is table which we are changing used somewhere in other parts
187
151
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)))
153
TableList *duplicate= NULL;
154
create_table= session->lex->unlink_first_table(&link_to_local);
155
if ((duplicate= unique_table(create_table, select_tables)))
157
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);
159
Release the protection against the global read lock and wake
160
everyone, who might want to set a global read lock.
162
start_waiting_global_read_lock(session);
163
/* put tables back for PS rexecuting */
164
session->lex->link_first_table_back(create_table, link_to_local);
238
else if (not lex_identified_temp_table)
170
select_create is currently not re-execution friendly and
171
needs to be created for every execution of a PS/SP.
173
if ((result= new select_create(create_table,
176
create_table_message,
178
select_lex->item_list,
179
session->lex->duplicates,
180
session->lex->ignore,
182
new_table_identifier)))
240
create_table_list= getSession()->lex->unlink_first_table(&link_to_local);
185
CREATE from SELECT give its Select_Lex for SELECT,
186
and item_list belong to SELECT
188
res= handle_select(session, session->lex, result, 0);
192
else if (not lex_identified_temp_table)
194
create_table= session->lex->unlink_first_table(&link_to_local);
200
if (is_create_table_like)
202
res= mysql_create_like_table(session,
203
new_table_identifier,
206
create_table_message,
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();
213
for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
215
message::Table::Field *field= create_table_message.add_field();
217
*field= alter_info.alter_proto.added_field(x);
220
res= mysql_create_table(session,
221
new_table_identifier,
223
create_table_message,
237
Release the protection against the global read lock and wake
238
everyone, who might want to set a global read lock.
240
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
245
bool statement::CreateTable::validateCreateTableOption()
315
size_t num_engine_options= createTableMessage().engine().options_size();
248
size_t num_engine_options= create_table_message.engine().options_size();
317
assert(create_info().db_type);
250
assert(create_info.db_type);
319
252
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());
254
bool valid= create_info.db_type->validateCreateTableOption(create_table_message.engine().options(y).name(),
255
create_table_message.engine().options(y).state());
326
259
my_error(ER_UNKNOWN_ENGINE_OPTION, MYF(0),
327
createTableMessage().engine().options(y).name().c_str(),
328
createTableMessage().engine().options(y).state().c_str());
260
create_table_message.engine().options(y).name().c_str(),
261
create_table_message.engine().options(y).state().c_str());