1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2009 Sun Microsystems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22
#include <drizzled/show.h>
23
#include <drizzled/lock.h>
24
#include <drizzled/session.h>
25
#include <drizzled/statement/create_table.h>
26
#include <drizzled/identifier.h>
33
bool statement::CreateTable::execute()
35
TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
36
TableList *all_tables= session->lex->query_tables;
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;
40
bool need_start_waiting= false;
42
bool link_to_local= false;
43
bool lex_identified_temp_table=
44
create_table_message.type() == message::Table::TEMPORARY;
49
plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
51
if (create_info.db_type == NULL)
53
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0),
54
create_table_message.engine().name().c_str());
59
else /* We now get the default, place it in create_info, and put the engine name in table proto */
61
create_info.db_type= session->getDefaultStorageEngine();
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 */
79
if (not lex_identified_temp_table)
81
if (not session->endActiveTransaction())
86
/* Skip first table, which is the table we are creating */
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))
104
/* put tables back for PS rexecuting */
105
session->lex->link_first_table_back(create_table, link_to_local);
109
/* Might have been updated in create_table_precheck */
110
create_info.alias= create_table->alias;
113
The create-select command will open and read-lock the select table
114
and then create, open and write-lock the new table. If a global
115
read lock steps in, we get a deadlock. The write lock waits for
116
the global read lock, while the global read lock waits for the
117
select table to be closed. So we wait until the global readlock is
118
gone before starting both steps. Note that
119
wait_if_global_read_lock() sets a protection against a new global
120
read lock when it succeeds. This needs to be released by
121
start_waiting_global_read_lock(). We protect the normal CREATE
122
TABLE in the same way. That way we avoid that a new table is
123
created during a gobal read lock.
125
if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
127
/* put tables back for PS rexecuting */
128
session->lex->link_first_table_back(create_table, link_to_local);
132
if (select_lex->item_list.elements) // With select
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
151
if (not lex_identified_temp_table)
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);
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);
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)))
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,
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);
245
bool statement::CreateTable::validateCreateTableOption()
248
size_t num_engine_options= create_table_message.engine().options_size();
250
assert(create_info.db_type);
252
for (size_t y= 0; y < num_engine_options; ++y)
254
bool valid= create_info.db_type->validateCreateTableOption(create_table_message.engine().options(y).name(),
255
create_table_message.engine().options(y).state());
259
my_error(ER_UNKNOWN_ENGINE_OPTION, MYF(0),
260
create_table_message.engine().options(y).name().c_str(),
261
create_table_message.engine().options(y).state().c_str());
270
} /* namespace drizzled */