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() == drizzled::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 (! lex_identified_temp_table)
78
if (! 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 ? NO_TMP_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 (! lex_identified_temp_table)
135
session->lex->link_first_table_back(create_table, link_to_local);
136
create_table->create= true;
139
if (! (res= session->openTablesLock(session->lex->query_tables)))
142
Is table which we are changing used somewhere in other parts
145
if (! 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,
178
CREATE from SELECT give its Select_Lex for SELECT,
179
and item_list belong to SELECT
181
res= handle_select(session, session->lex, result, 0);
185
else if (! lex_identified_temp_table)
187
create_table= session->lex->unlink_first_table(&link_to_local);
193
if (is_create_table_like)
195
res= mysql_create_like_table(session,
206
for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
208
message::Table::Field *field= create_table_proto.add_field();
210
*field= alter_info.alter_proto.added_field(x);
213
res= mysql_create_table(session,
214
new_table_identifier,
229
Release the protection against the global read lock and wake
230
everyone, who might want to set a global read lock.
232
start_waiting_global_read_lock(session);
237
} /* namespace drizzled */