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/message.h>
27
#include <drizzled/identifier.h>
34
bool statement::CreateTable::execute()
36
TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
37
TableList *all_tables= session->lex->query_tables;
38
assert(first_table == all_tables && first_table != 0);
39
Select_Lex *select_lex= &session->lex->select_lex;
40
Select_Lex_Unit *unit= &session->lex->unit;
41
bool need_start_waiting= false;
43
bool link_to_local= false;
44
bool lex_identified_temp_table=
45
create_table_message.type() == message::Table::TEMPORARY;
50
plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
52
if (create_info.db_type == NULL)
54
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0),
55
create_table_message.engine().name().c_str());
60
else /* We now get the default, place it in create_info, and put the engine name in table proto */
62
create_info.db_type= session->getDefaultStorageEngine();
65
if (not validateCreateTableOption())
71
/* If CREATE TABLE of non-temporary table, do implicit commit */
72
if (not lex_identified_temp_table)
74
if (not session->endActiveTransaction())
79
/* Skip first table, which is the table we are creating */
80
TableList *create_table= session->lex->unlink_first_table(&link_to_local);
81
TableList *select_tables= session->lex->query_tables;
83
drizzled::message::init(create_table_message, create_table_message.name(), create_table->getSchemaName(), create_info.db_type->getName());
85
TableIdentifier new_table_identifier(create_table->getSchemaName(),
86
create_table->getTableName(),
87
create_table_message.type());
89
if (create_table_precheck(new_table_identifier))
91
/* put tables back for PS rexecuting */
92
session->lex->link_first_table_back(create_table, link_to_local);
96
/* Might have been updated in create_table_precheck */
97
create_info.alias= create_table->alias;
100
The create-select command will open and read-lock the select table
101
and then create, open and write-lock the new table. If a global
102
read lock steps in, we get a deadlock. The write lock waits for
103
the global read lock, while the global read lock waits for the
104
select table to be closed. So we wait until the global readlock is
105
gone before starting both steps. Note that
106
wait_if_global_read_lock() sets a protection against a new global
107
read lock when it succeeds. This needs to be released by
108
start_waiting_global_read_lock(). We protect the normal CREATE
109
TABLE in the same way. That way we avoid that a new table is
110
created during a gobal read lock.
112
if (! (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
114
/* put tables back for PS rexecuting */
115
session->lex->link_first_table_back(create_table, link_to_local);
119
if (select_lex->item_list.elements) // With select
121
select_result *result;
123
select_lex->options|= SELECT_NO_UNLOCK;
124
unit->set_limit(select_lex);
126
if (not lex_identified_temp_table)
128
session->lex->link_first_table_back(create_table, link_to_local);
129
create_table->setCreate(true);
132
if (not (res= session->openTablesLock(session->lex->query_tables)))
135
Is table which we are changing used somewhere in other parts
138
if (not lex_identified_temp_table)
140
TableList *duplicate= NULL;
141
create_table= session->lex->unlink_first_table(&link_to_local);
142
if ((duplicate= unique_table(create_table, select_tables)))
144
my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->alias);
146
Release the protection against the global read lock and wake
147
everyone, who might want to set a global read lock.
149
session->startWaitingGlobalReadLock();
150
/* put tables back for PS rexecuting */
151
session->lex->link_first_table_back(create_table, link_to_local);
158
select_create is currently not re-execution friendly and
159
needs to be created for every execution of a PS/SP.
161
if ((result= new select_create(create_table,
164
create_table_message,
166
select_lex->item_list,
167
session->lex->duplicates,
168
session->lex->ignore,
170
new_table_identifier)))
173
CREATE from SELECT give its Select_Lex for SELECT,
174
and item_list belong to SELECT
176
res= handle_select(session, session->lex, result, 0);
180
else if (not lex_identified_temp_table)
182
create_table= session->lex->unlink_first_table(&link_to_local);
188
if (is_create_table_like)
190
res= mysql_create_like_table(session,
191
new_table_identifier,
194
create_table_message,
201
for (int32_t x= 0; x < alter_info.alter_proto.added_field_size(); x++)
203
message::Table::Field *field= create_table_message.add_field();
205
*field= alter_info.alter_proto.added_field(x);
208
res= mysql_create_table(session,
209
new_table_identifier,
211
create_table_message,
225
Release the protection against the global read lock and wake
226
everyone, who might want to set a global read lock.
228
session->startWaitingGlobalReadLock();
233
bool statement::CreateTable::validateCreateTableOption()
236
size_t num_engine_options= create_table_message.engine().options_size();
238
assert(create_info.db_type);
240
for (size_t y= 0; y < num_engine_options; ++y)
242
bool valid= create_info.db_type->validateCreateTableOption(create_table_message.engine().options(y).name(),
243
create_table_message.engine().options(y).state());
247
my_error(ER_UNKNOWN_ENGINE_OPTION, MYF(0),
248
create_table_message.engine().options(y).name().c_str(),
249
create_table_message.engine().options(y).state().c_str());
258
} /* namespace drizzled */