18
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
#include <drizzled/server_includes.h>
22
22
#include <drizzled/show.h>
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>
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
27
using namespace drizzled;
80
29
bool statement::CreateTable::execute()
82
TableList *first_table= (TableList *) getSession()->lex->select_lex.table_list.first;
83
TableList *all_tables= getSession()->lex->query_tables;
31
TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
32
TableList *all_tables= session->lex->query_tables;
84
33
assert(first_table == all_tables && first_table != 0);
34
Select_Lex *select_lex= &session->lex->select_lex;
35
Select_Lex_Unit *unit= &session->lex->unit;
85
36
bool need_start_waiting= false;
86
lex_identified_temp_table= createTableMessage().type() == message::Table::TEMPORARY;
88
is_engine_set= not createTableMessage().engine().name().empty();
92
create_info().db_type=
93
plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
95
if (create_info().db_type == NULL)
97
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0),
98
createTableMessage().engine().name().c_str());
103
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())
117
my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
38
bool link_to_local= false;
40
/* If CREATE TABLE of non-temporary table, do implicit commit */
41
if (! (session->lex->create_info.options & HA_LEX_CREATE_TMP_TABLE))
43
if (! session->endActiveTransaction())
121
48
/* 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))
132
/* put tables back for PS rexecuting */
133
getSession()->lex->link_first_table_back(create_table_list, link_to_local);
49
TableList *create_table= session->lex->unlink_first_table(&link_to_local);
50
TableList *select_tables= session->lex->query_tables;
52
Code below (especially in mysql_create_table() and select_create
53
methods) may modify HA_CREATE_INFO structure in LEX, so we have to
54
use a copy of this structure to make execution prepared statement-
55
safe. A shallow copy is enough as this code won't modify any memory
56
referenced from this structure.
58
HA_CREATE_INFO create_info(session->lex->create_info);
60
We need to copy alter_info for the same reasons of re-execution
61
safety, only in case of AlterInfo we have to do (almost) a deep
64
AlterInfo alter_info(session->lex->alter_info, session->mem_root);
66
if (session->is_fatal_error)
68
/* If out of memory when creating a copy of alter_info. */
69
/* put tables back for PS rexecuting */
70
session->lex->link_first_table_back(create_table, link_to_local);
74
if (create_table_precheck(session, select_tables, create_table))
76
/* put tables back for PS rexecuting */
77
session->lex->link_first_table_back(create_table, link_to_local);
137
81
/* Might have been updated in create_table_precheck */
138
create_info().alias= create_table_list->alias;
82
create_info.alias= create_table->alias;
141
85
The create-select command will open and read-lock the select table
150
94
TABLE in the same way. That way we avoid that a new table is
151
95
created during a gobal read lock.
153
if (! (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
97
if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
155
99
/* put tables back for PS rexecuting */
156
getSession()->lex->link_first_table_back(create_table_list, link_to_local);
100
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;
103
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)))
105
select_result *result;
107
select_lex->options|= SELECT_NO_UNLOCK;
108
unit->set_limit(select_lex);
110
if (! (create_info.options & HA_LEX_CREATE_TMP_TABLE))
112
session->lex->link_first_table_back(create_table, link_to_local);
113
create_table->create= true;
116
if (! (res= session->openTablesLock(session->lex->query_tables)))
119
Is table which we are changing used somewhere in other parts
122
if (! (create_info.options & HA_LEX_CREATE_TMP_TABLE))
124
TableList *duplicate= NULL;
125
create_table= session->lex->unlink_first_table(&link_to_local);
126
if ((duplicate= unique_table(session, create_table, select_tables, 0)))
128
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);
130
Release the protection against the global read lock and wake
131
everyone, who might want to set a global read lock.
133
start_waiting_global_read_lock(session);
134
/* put tables back for PS rexecuting */
135
session->lex->link_first_table_back(create_table, link_to_local);
238
else if (not lex_identified_temp_table)
141
select_create is currently not re-execution friendly and
142
needs to be created for every execution of a PS/SP.
144
if ((result= new select_create(create_table,
146
session->lex->create_table_proto,
148
select_lex->item_list,
149
session->lex->duplicates,
150
session->lex->ignore,
240
create_table_list= getSession()->lex->unlink_first_table(&link_to_local);
154
CREATE from SELECT give its Select_Lex for SELECT,
155
and item_list belong to SELECT
157
res= handle_select(session, session->lex, result, 0);
161
else if (! (create_info.options & HA_LEX_CREATE_TMP_TABLE))
163
create_table= session->lex->unlink_first_table(&link_to_local);
168
/* So that CREATE TEMPORARY TABLE gets to binlog at commit/rollback */
169
if (create_info.options & HA_LEX_CREATE_TMP_TABLE)
170
session->options|= OPTION_KEEP_LOG;
172
if (create_info.options & HA_LEX_CREATE_TABLE_LIKE)
174
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();
181
res= mysql_create_table(session,
183
create_table->table_name,
185
session->lex->create_table_proto,
197
Release the protection against the global read lock and wake
198
everyone, who might want to set a global read lock.
200
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
} /* namespace drizzled */