18
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
23
#include <drizzled/show.h>
23
24
#include <drizzled/lock.h>
24
25
#include <drizzled/session.h>
25
26
#include <drizzled/statement/create_table.h>
26
27
#include <drizzled/message.h>
27
28
#include <drizzled/identifier.h>
29
#include <drizzled/plugin/storage_engine.h>
30
#include <drizzled/select_create.h>
31
#include <drizzled/table_ident.h>
29
33
#include <iostream>
40
CreateTable::CreateTable(Session *in_session, Table_ident *ident, bool is_temporary) :
41
Statement(in_session),
44
on_update_value(NULL),
46
is_create_table_like(false),
47
lex_identified_temp_table(false),
49
create_table_list(NULL)
51
set_command(SQLCOM_CREATE_TABLE);
52
createTableMessage().set_name(ident->table.str, ident->table.length);
54
createTableMessage().set_schema(ident->db.str, ident->db.length);
59
createTableMessage().set_type(message::Table::TEMPORARY);
63
createTableMessage().set_type(message::Table::STANDARD);
67
CreateTable::CreateTable(Session *in_session) :
68
Statement(in_session),
71
on_update_value(NULL),
73
is_create_table_like(false),
74
lex_identified_temp_table(false),
76
create_table_list(NULL)
78
set_command(SQLCOM_CREATE_TABLE);
81
} // namespace statement
34
83
bool statement::CreateTable::execute()
36
TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
37
TableList *all_tables= session->lex->query_tables;
85
TableList *first_table= (TableList *) lex().select_lex.table_list.first;
86
TableList *all_tables= lex().query_tables;
38
87
assert(first_table == all_tables && first_table != 0);
39
Select_Lex *select_lex= &session->lex->select_lex;
40
Select_Lex_Unit *unit= &session->lex->unit;
41
88
bool need_start_waiting= false;
43
bool link_to_local= false;
44
bool lex_identified_temp_table=
45
create_table_message.type() == message::Table::TEMPORARY;
89
lex_identified_temp_table= createTableMessage().type() == message::Table::TEMPORARY;
91
is_engine_set= not createTableMessage().engine().name().empty();
50
plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
95
create_info().db_type=
96
plugin::StorageEngine::findByName(session(), createTableMessage().engine().name());
52
if (create_info.db_type == NULL)
98
if (create_info().db_type == NULL)
54
100
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0),
55
create_table_message.engine().name().c_str());
101
createTableMessage().engine().name().c_str());
60
106
else /* We now get the default, place it in create_info, and put the engine name in table proto */
62
create_info.db_type= session->getDefaultStorageEngine();
108
create_info().db_type= session().getDefaultStorageEngine();
65
111
if (not validateCreateTableOption())
71
/* If CREATE TABLE of non-temporary table, do implicit commit */
72
116
if (not lex_identified_temp_table)
74
if (not session->endActiveTransaction())
118
if (session().inTransaction())
120
my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
79
124
/* Skip first table, which is the table we are creating */
80
TableList *create_table= session->lex->unlink_first_table(&link_to_local);
81
TableList *select_tables= session->lex->query_tables;
83
drizzled::message::init(create_table_message, create_table_message.name(), create_table->getSchemaName(), create_info.db_type->getName());
85
TableIdentifier new_table_identifier(create_table->getSchemaName(),
86
create_table->getTableName(),
87
create_table_message.type());
125
create_table_list= lex().unlink_first_table(&link_to_local);
127
drizzled::message::table::init(createTableMessage(), createTableMessage().name(), create_table_list->getSchemaName(), create_info().db_type->getName());
129
identifier::Table new_table_identifier(create_table_list->getSchemaName(),
130
create_table_list->getTableName(),
131
createTableMessage().type());
89
133
if (not check(new_table_identifier))
91
135
/* put tables back for PS rexecuting */
92
session->lex->link_first_table_back(create_table, link_to_local);
136
lex().link_first_table_back(create_table_list, link_to_local);
96
140
/* Might have been updated in create_table_precheck */
97
create_info.alias= create_table->alias;
141
create_info().alias= create_table_list->alias;
100
144
The create-select command will open and read-lock the select table
109
153
TABLE in the same way. That way we avoid that a new table is
110
154
created during a gobal read lock.
112
if (! (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
156
if (! (need_start_waiting= not session().wait_if_global_read_lock(0, 1)))
114
158
/* put tables back for PS rexecuting */
115
session->lex->link_first_table_back(create_table, link_to_local);
159
lex().link_first_table_back(create_table_list, link_to_local);
119
if (select_lex->item_list.elements) // With select
163
bool res= executeInner(new_table_identifier);
166
Release the protection against the global read lock and wake
167
everyone, who might want to set a global read lock.
169
session().startWaitingGlobalReadLock();
174
bool statement::CreateTable::executeInner(identifier::Table::const_reference new_table_identifier)
177
Select_Lex *select_lex= &lex().select_lex;
178
TableList *select_tables= lex().query_tables;
121
select_result *result;
123
select_lex->options|= SELECT_NO_UNLOCK;
124
unit->set_limit(select_lex);
126
if (not lex_identified_temp_table)
128
session->lex->link_first_table_back(create_table, link_to_local);
129
create_table->setCreate(true);
132
if (not (res= session->openTablesLock(session->lex->query_tables)))
135
Is table which we are changing used somewhere in other parts
182
if (select_lex->item_list.size()) // With select
184
Select_Lex_Unit *unit= &lex().unit;
185
select_result *result;
187
select_lex->options|= SELECT_NO_UNLOCK;
188
unit->set_limit(select_lex);
138
190
if (not lex_identified_temp_table)
140
TableList *duplicate= NULL;
141
create_table= session->lex->unlink_first_table(&link_to_local);
142
if ((duplicate= unique_table(create_table, select_tables)))
144
my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->alias);
192
lex().link_first_table_back(create_table_list, link_to_local);
193
create_table_list->setCreate(true);
196
if (not (res= session().openTablesLock(lex().query_tables)))
199
Is table which we are changing used somewhere in other parts
202
if (not lex_identified_temp_table)
204
TableList *duplicate= NULL;
205
create_table_list= lex().unlink_first_table(&link_to_local);
207
if ((duplicate= unique_table(create_table_list, select_tables)))
209
my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table_list->alias);
210
/* put tables back for PS rexecuting */
211
lex().link_first_table_back(create_table_list, link_to_local);
219
select_create is currently not re-execution friendly and
220
needs to be created for every execution of a PS/SP.
222
if ((result= new select_create(create_table_list,
225
createTableMessage(),
227
select_lex->item_list,
231
new_table_identifier)))
146
Release the protection against the global read lock and wake
147
everyone, who might want to set a global read lock.
149
session->startWaitingGlobalReadLock();
150
/* put tables back for PS rexecuting */
151
session->lex->link_first_table_back(create_table, link_to_local);
234
CREATE from SELECT give its Select_Lex for SELECT,
235
and item_list belong to SELECT
237
res= handle_select(&session(), &lex(), result, 0);
158
select_create is currently not re-execution friendly and
159
needs to be created for every execution of a PS/SP.
161
if ((result= new select_create(create_table,
164
create_table_message,
166
select_lex->item_list,
167
session->lex->duplicates,
168
session->lex->ignore,
170
new_table_identifier)))
241
else if (not lex_identified_temp_table)
173
CREATE from SELECT give its Select_Lex for SELECT,
174
and item_list belong to SELECT
176
res= handle_select(session, session->lex, result, 0);
243
create_table_list= lex().unlink_first_table(&link_to_local);
180
else if (not lex_identified_temp_table)
182
create_table= session->lex->unlink_first_table(&link_to_local);
188
if (is_create_table_like)
190
res= mysql_create_like_table(session,
191
new_table_identifier,
194
create_table_message,
201
for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
203
message::Table::Field *field= create_table_message.add_field();
205
*field= alter_info.alter_proto.added_field(x);
208
res= mysql_create_table(session,
209
new_table_identifier,
211
create_table_message,
225
Release the protection against the global read lock and wake
226
everyone, who might want to set a global read lock.
228
session->startWaitingGlobalReadLock();
249
if (is_create_table_like)
251
res= create_like_table(&session(),
252
new_table_identifier,
253
identifier::Table(select_tables->getSchemaName(),
254
select_tables->getTableName()),
255
createTableMessage(),
262
for (int32_t x= 0; x < alter_info.added_fields_proto.added_field_size(); x++)
264
message::Table::Field *field= createTableMessage().add_field();
266
*field= alter_info.added_fields_proto.added_field(x);
269
res= create_table(&session(),
270
new_table_identifier,
272
createTableMessage(),
233
bool statement::CreateTable::check(const TableIdentifier &identifier)
289
bool statement::CreateTable::check(const identifier::Table &identifier)
235
291
// Check table name for validity
236
292
if (not identifier.isValid())
259
317
bool statement::CreateTable::validateCreateTableOption()
262
size_t num_engine_options= create_table_message.engine().options_size();
320
size_t num_engine_options= createTableMessage().engine().options_size();
264
assert(create_info.db_type);
322
assert(create_info().db_type);
266
324
for (size_t y= 0; y < num_engine_options; ++y)
268
bool valid= create_info.db_type->validateCreateTableOption(create_table_message.engine().options(y).name(),
269
create_table_message.engine().options(y).state());
326
bool valid= create_info().db_type->validateCreateTableOption(createTableMessage().engine().options(y).name(),
327
createTableMessage().engine().options(y).state());
273
331
my_error(ER_UNKNOWN_ENGINE_OPTION, MYF(0),
274
create_table_message.engine().options(y).name().c_str(),
275
create_table_message.engine().options(y).state().c_str());
332
createTableMessage().engine().options(y).name().c_str(),
333
createTableMessage().engine().options(y).state().c_str());