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>
31
bool statement::CreateTable::execute()
33
TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
34
TableList *all_tables= session->lex->query_tables;
35
assert(first_table == all_tables && first_table != 0);
36
Select_Lex *select_lex= &session->lex->select_lex;
37
Select_Lex_Unit *unit= &session->lex->unit;
38
bool need_start_waiting= false;
40
bool link_to_local= false;
41
bool lex_identified_temp_table=
42
create_table_proto.type() == message::Table::TEMPORARY;
47
plugin::StorageEngine::findByName(*session, create_table_proto.engine().name());
49
if (create_info.db_type == NULL)
51
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0),
52
create_table_proto.name().c_str());
57
else /* We now get the default, place it in create_info, and put the engine name in table proto */
59
create_info.db_type= session->getDefaultStorageEngine();
64
Now we set the name in our Table proto so that it will match
68
message::Table::StorageEngine *protoengine;
70
protoengine= create_table_proto.mutable_engine();
71
protoengine->set_name(create_info.db_type->getName());
75
/* If CREATE TABLE of non-temporary table, do implicit commit */
76
if (not lex_identified_temp_table)
78
if (not session->endActiveTransaction())
83
/* Skip first table, which is the table we are creating */
84
TableList *create_table= session->lex->unlink_first_table(&link_to_local);
85
TableList *select_tables= session->lex->query_tables;
89
Now that we have the engine, we can figure out the table identifier. We need the engine in order
90
to determine if the table is transactional or not if it is temp.
92
TableIdentifier new_table_identifier(create_table->db,
93
create_table->table_name,
94
create_table_proto.type() != message::Table::TEMPORARY ? STANDARD_TABLE : TEMP_TABLE);
96
if (create_table_precheck(new_table_identifier))
98
/* put tables back for PS rexecuting */
99
session->lex->link_first_table_back(create_table, link_to_local);
103
/* Might have been updated in create_table_precheck */
104
create_info.alias= create_table->alias;
107
The create-select command will open and read-lock the select table
108
and then create, open and write-lock the new table. If a global
109
read lock steps in, we get a deadlock. The write lock waits for
110
the global read lock, while the global read lock waits for the
111
select table to be closed. So we wait until the global readlock is
112
gone before starting both steps. Note that
113
wait_if_global_read_lock() sets a protection against a new global
114
read lock when it succeeds. This needs to be released by
115
start_waiting_global_read_lock(). We protect the normal CREATE
116
TABLE in the same way. That way we avoid that a new table is
117
created during a gobal read lock.
119
if (! (need_start_waiting= ! wait_if_global_read_lock(session, 0, 1)))
121
/* put tables back for PS rexecuting */
122
session->lex->link_first_table_back(create_table, link_to_local);
126
if (select_lex->item_list.elements) // With select
128
select_result *result;
130
select_lex->options|= SELECT_NO_UNLOCK;
131
unit->set_limit(select_lex);
133
if (not lex_identified_temp_table)
135
session->lex->link_first_table_back(create_table, link_to_local);
136
create_table->create= true;
139
if (not (res= session->openTablesLock(session->lex->query_tables)))
142
Is table which we are changing used somewhere in other parts
145
if (not lex_identified_temp_table)
147
TableList *duplicate= NULL;
148
create_table= session->lex->unlink_first_table(&link_to_local);
149
if ((duplicate= unique_table(create_table, select_tables)))
151
my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->alias);
153
Release the protection against the global read lock and wake
154
everyone, who might want to set a global read lock.
156
start_waiting_global_read_lock(session);
157
/* put tables back for PS rexecuting */
158
session->lex->link_first_table_back(create_table, link_to_local);
164
select_create is currently not re-execution friendly and
165
needs to be created for every execution of a PS/SP.
167
if ((result= new select_create(create_table,
172
select_lex->item_list,
173
session->lex->duplicates,
174
session->lex->ignore,
176
new_table_identifier)))
179
CREATE from SELECT give its Select_Lex for SELECT,
180
and item_list belong to SELECT
182
res= handle_select(session, session->lex, result, 0);
186
else if (not lex_identified_temp_table)
188
create_table= session->lex->unlink_first_table(&link_to_local);
194
if (is_create_table_like)
196
res= mysql_create_like_table(session,
197
new_table_identifier,
207
for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
209
message::Table::Field *field= create_table_proto.add_field();
211
*field= alter_info.alter_proto.added_field(x);
214
res= mysql_create_table(session,
215
new_table_identifier,
230
Release the protection against the global read lock and wake
231
everyone, who might want to set a global read lock.
233
start_waiting_global_read_lock(session);
238
} /* namespace drizzled */