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/table_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.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();
65
Now we set the name in our Table proto so that it will match
69
message::Table::StorageEngine *protoengine;
71
protoengine= create_table_message.mutable_engine();
72
protoengine->set_name(create_info.db_type->getName());
76
/* If CREATE TABLE of non-temporary table, do implicit commit */
77
if (not lex_identified_temp_table)
79
if (not session->endActiveTransaction())
84
/* Skip first table, which is the table we are creating */
85
TableList *create_table= session->lex->unlink_first_table(&link_to_local);
86
TableList *select_tables= session->lex->query_tables;
90
Now that we have the engine, we can figure out the table identifier. We need the engine in order
91
to determine if the table is transactional or not if it is temp.
94
create_table_message.set_schema(create_table->db);
96
TableIdentifier new_table_identifier(create_table->db,
97
create_table->table_name,
98
create_table_message.type());
100
if (create_table_precheck(new_table_identifier))
102
/* put tables back for PS rexecuting */
103
session->lex->link_first_table_back(create_table, link_to_local);
107
/* Might have been updated in create_table_precheck */
108
create_info.alias= create_table->alias;
111
The create-select command will open and read-lock the select table
112
and then create, open and write-lock the new table. If a global
113
read lock steps in, we get a deadlock. The write lock waits for
114
the global read lock, while the global read lock waits for the
115
select table to be closed. So we wait until the global readlock is
116
gone before starting both steps. Note that
117
wait_if_global_read_lock() sets a protection against a new global
118
read lock when it succeeds. This needs to be released by
119
start_waiting_global_read_lock(). We protect the normal CREATE
120
TABLE in the same way. That way we avoid that a new table is
121
created during a gobal read lock.
123
if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
125
/* put tables back for PS rexecuting */
126
session->lex->link_first_table_back(create_table, link_to_local);
130
if (select_lex->item_list.elements) // With select
132
select_result *result;
134
select_lex->options|= SELECT_NO_UNLOCK;
135
unit->set_limit(select_lex);
137
if (not lex_identified_temp_table)
139
session->lex->link_first_table_back(create_table, link_to_local);
140
create_table->create= true;
143
if (not (res= session->openTablesLock(session->lex->query_tables)))
146
Is table which we are changing used somewhere in other parts
149
if (not lex_identified_temp_table)
151
TableList *duplicate= NULL;
152
create_table= session->lex->unlink_first_table(&link_to_local);
153
if ((duplicate= unique_table(create_table, select_tables)))
155
my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->alias);
157
Release the protection against the global read lock and wake
158
everyone, who might want to set a global read lock.
160
start_waiting_global_read_lock(session);
161
/* put tables back for PS rexecuting */
162
session->lex->link_first_table_back(create_table, link_to_local);
168
select_create is currently not re-execution friendly and
169
needs to be created for every execution of a PS/SP.
171
if ((result= new select_create(create_table,
174
create_table_message,
176
select_lex->item_list,
177
session->lex->duplicates,
178
session->lex->ignore,
180
new_table_identifier)))
183
CREATE from SELECT give its Select_Lex for SELECT,
184
and item_list belong to SELECT
186
res= handle_select(session, session->lex, result, 0);
190
else if (not lex_identified_temp_table)
192
create_table= session->lex->unlink_first_table(&link_to_local);
198
if (is_create_table_like)
200
res= mysql_create_like_table(session,
201
new_table_identifier,
204
create_table_message,
211
for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
213
message::Table::Field *field= create_table_message.add_field();
215
*field= alter_info.alter_proto.added_field(x);
218
res= mysql_create_table(session,
219
new_table_identifier,
221
create_table_message,
235
Release the protection against the global read lock and wake
236
everyone, who might want to set a global read lock.
238
start_waiting_global_read_lock(session);
243
} /* namespace drizzled */