18
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
22
#include <drizzled/show.h>
24
23
#include <drizzled/lock.h>
25
24
#include <drizzled/session.h>
26
25
#include <drizzled/statement/create_table.h>
27
#include <drizzled/message.h>
28
#include <drizzled/identifier.h>
29
#include <drizzled/plugin/storage_engine.h>
30
#include <drizzled/select_create.h>
26
#include <drizzled/table_identifier.h>
32
28
#include <iostream>
39
CreateTable::CreateTable(Session *in_session, Table_ident *ident, bool is_temporary) :
40
Statement(in_session),
43
on_update_value(NULL),
45
is_create_table_like(false),
46
lex_identified_temp_table(false),
48
create_table_list(NULL)
50
getSession()->getLex()->sql_command= SQLCOM_CREATE_TABLE;
51
createTableMessage().set_name(ident->table.str, ident->table.length);
53
createTableMessage().set_schema(ident->db.str, ident->db.length);
58
createTableMessage().set_type(message::Table::TEMPORARY);
62
createTableMessage().set_type(message::Table::STANDARD);
66
CreateTable::CreateTable(Session *in_session) :
67
Statement(in_session),
70
on_update_value(NULL),
72
is_create_table_like(false),
73
lex_identified_temp_table(false),
75
create_table_list(NULL)
77
getSession()->getLex()->sql_command= SQLCOM_CREATE_TABLE;
80
} // namespace statement
82
33
bool statement::CreateTable::execute()
84
TableList *first_table= (TableList *) getSession()->getLex()->select_lex.table_list.first;
85
TableList *all_tables= getSession()->getLex()->query_tables;
35
TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
36
TableList *all_tables= session->lex->query_tables;
86
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;
87
40
bool need_start_waiting= false;
88
lex_identified_temp_table= createTableMessage().type() == message::Table::TEMPORARY;
90
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;
94
create_info().db_type=
95
plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
49
plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
97
if (create_info().db_type == NULL)
51
if (create_info.db_type == NULL)
99
53
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0),
100
createTableMessage().engine().name().c_str());
54
create_table_message.name().c_str());
105
59
else /* We now get the default, place it in create_info, and put the engine name in table proto */
107
create_info().db_type= getSession()->getDefaultStorageEngine();
61
create_info.db_type= session->getDefaultStorageEngine();
110
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 */
115
79
if (not lex_identified_temp_table)
117
if (getSession()->inTransaction())
81
if (not session->endActiveTransaction())
119
my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
123
86
/* Skip first table, which is the table we are creating */
124
create_table_list= getSession()->getLex()->unlink_first_table(&link_to_local);
126
drizzled::message::table::init(createTableMessage(), createTableMessage().name(), create_table_list->getSchemaName(), create_info().db_type->getName());
128
identifier::Table new_table_identifier(create_table_list->getSchemaName(),
129
create_table_list->getTableName(),
130
createTableMessage().type());
132
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))
134
104
/* put tables back for PS rexecuting */
135
getSession()->getLex()->link_first_table_back(create_table_list, link_to_local);
105
session->lex->link_first_table_back(create_table, link_to_local);
139
109
/* Might have been updated in create_table_precheck */
140
create_info().alias= create_table_list->alias;
110
create_info.alias= create_table->alias;
143
113
The create-select command will open and read-lock the select table
152
122
TABLE in the same way. That way we avoid that a new table is
153
123
created during a gobal read lock.
155
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)))
157
127
/* put tables back for PS rexecuting */
158
getSession()->getLex()->link_first_table_back(create_table_list, link_to_local);
128
session->lex->link_first_table_back(create_table, link_to_local);
162
bool res= executeInner(new_table_identifier);
165
Release the protection against the global read lock and wake
166
everyone, who might want to set a global read lock.
168
getSession()->startWaitingGlobalReadLock();
173
bool statement::CreateTable::executeInner(identifier::Table::const_reference new_table_identifier)
176
Select_Lex *select_lex= &getSession()->getLex()->select_lex;
177
TableList *select_tables= getSession()->getLex()->query_tables;
132
if (select_lex->item_list.elements) // With select
181
if (select_lex->item_list.elements) // With select
183
Select_Lex_Unit *unit= &getSession()->getLex()->unit;
184
select_result *result;
186
select_lex->options|= SELECT_NO_UNLOCK;
187
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
189
151
if (not lex_identified_temp_table)
191
getSession()->getLex()->link_first_table_back(create_table_list, link_to_local);
192
create_table_list->setCreate(true);
195
if (not (res= getSession()->openTablesLock(getSession()->getLex()->query_tables)))
198
Is table which we are changing used somewhere in other parts
201
if (not lex_identified_temp_table)
203
TableList *duplicate= NULL;
204
create_table_list= getSession()->getLex()->unlink_first_table(&link_to_local);
206
if ((duplicate= unique_table(create_table_list, select_tables)))
208
my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table_list->alias);
209
/* put tables back for PS rexecuting */
210
getSession()->getLex()->link_first_table_back(create_table_list, link_to_local);
218
select_create is currently not re-execution friendly and
219
needs to be created for every execution of a PS/SP.
221
if ((result= new select_create(create_table_list,
222
getSession()->getLex()->exists(),
224
createTableMessage(),
226
select_lex->item_list,
227
getSession()->getLex()->duplicates,
228
getSession()->getLex()->ignore,
230
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);
233
CREATE from SELECT give its Select_Lex for SELECT,
234
and item_list belong to SELECT
236
res= handle_select(getSession(), getSession()->getLex(), 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);
240
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)))
242
create_table_list= getSession()->getLex()->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,
248
if (is_create_table_like)
250
res= create_like_table(getSession(),
251
new_table_identifier,
252
identifier::Table(select_tables->getSchemaName(),
253
select_tables->getTableName()),
254
createTableMessage(),
255
getSession()->getLex()->exists(),
261
for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
263
message::Table::Field *field= createTableMessage().add_field();
265
*field= alter_info.alter_proto.added_field(x);
268
res= create_table(getSession(),
269
new_table_identifier,
271
createTableMessage(),
275
getSession()->getLex()->exists());
280
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);
288
bool statement::CreateTable::check(const identifier::Table &identifier)
290
// Check table name for validity
291
if (not identifier.isValid())
294
// See if any storage engine objects to the name of the file
295
if (not plugin::StorageEngine::canCreateTable(identifier))
297
identifier::Schema schema_identifier= identifier;
298
error::access(*getSession()->user(), schema_identifier);
303
// Make sure the schema exists, we will do this again during the actual
304
// create for the table.
305
if (not plugin::StorageEngine::doesSchemaExist(identifier))
307
identifier::Schema schema_identifier= identifier;
308
my_error(ER_BAD_DB_ERROR, schema_identifier);
316
245
bool statement::CreateTable::validateCreateTableOption()
319
size_t num_engine_options= createTableMessage().engine().options_size();
248
size_t num_engine_options= create_table_message.engine().options_size();
321
assert(create_info().db_type);
250
assert(create_info.db_type);
323
252
for (size_t y= 0; y < num_engine_options; ++y)
325
bool valid= create_info().db_type->validateCreateTableOption(createTableMessage().engine().options(y).name(),
326
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());
330
259
my_error(ER_UNKNOWN_ENGINE_OPTION, MYF(0),
331
createTableMessage().engine().options(y).name().c_str(),
332
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());