00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <drizzled/show.h>
00024 #include <drizzled/lock.h>
00025 #include <drizzled/session.h>
00026 #include <drizzled/statement/create_table.h>
00027 #include <drizzled/message.h>
00028 #include <drizzled/identifier.h>
00029 #include <drizzled/plugin/storage_engine.h>
00030 #include <drizzled/select_create.h>
00031 #include <drizzled/table_ident.h>
00032
00033 #include <iostream>
00034
00035 namespace drizzled {
00036 namespace statement {
00037
00038 CreateTable::CreateTable(Session *in_session, Table_ident *ident, bool is_temporary) :
00039 Statement(in_session),
00040 change(NULL),
00041 default_value(NULL),
00042 on_update_value(NULL),
00043 is_engine_set(false),
00044 is_create_table_like(false),
00045 lex_identified_temp_table(false),
00046 link_to_local(false),
00047 create_table_list(NULL)
00048 {
00049 set_command(SQLCOM_CREATE_TABLE);
00050 createTableMessage().set_name(ident->table.data(), ident->table.size());
00051 #if 0
00052 createTableMessage().set_schema(ident->db.data(), ident->db.size());
00053 #endif
00054
00055 createTableMessage().set_type(is_temporary ? message::Table::TEMPORARY : message::Table::STANDARD);
00056 }
00057
00058 CreateTable::CreateTable(Session *in_session) :
00059 Statement(in_session),
00060 change(NULL),
00061 default_value(NULL),
00062 on_update_value(NULL),
00063 is_engine_set(false),
00064 is_create_table_like(false),
00065 lex_identified_temp_table(false),
00066 link_to_local(false),
00067 create_table_list(NULL)
00068 {
00069 set_command(SQLCOM_CREATE_TABLE);
00070 }
00071
00072 }
00073
00074 bool statement::CreateTable::execute()
00075 {
00076 TableList *first_table= (TableList *) lex().select_lex.table_list.first;
00077 TableList *all_tables= lex().query_tables;
00078 assert(first_table == all_tables && first_table != 0);
00079 lex_identified_temp_table= createTableMessage().type() == message::Table::TEMPORARY;
00080
00081 is_engine_set= not createTableMessage().engine().name().empty();
00082
00083 if (is_engine_set)
00084 {
00085 create_info().db_type=
00086 plugin::StorageEngine::findByName(session(), createTableMessage().engine().name());
00087
00088 if (create_info().db_type == NULL)
00089 {
00090 my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0),
00091 createTableMessage().engine().name().c_str());
00092
00093 return true;
00094 }
00095 }
00096 else
00097 {
00098 create_info().db_type= session().getDefaultStorageEngine();
00099 }
00100
00101 if (not validateCreateTableOption())
00102 {
00103 return true;
00104 }
00105
00106 if (not lex_identified_temp_table)
00107 {
00108 if (session().inTransaction())
00109 {
00110 my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
00111 return true;
00112 }
00113 }
00114
00115 create_table_list= lex().unlink_first_table(&link_to_local);
00116
00117 drizzled::message::table::init(createTableMessage(), createTableMessage().name(), create_table_list->getSchemaName(), create_info().db_type->getName());
00118
00119 identifier::Table new_table_identifier(create_table_list->getSchemaName(),
00120 create_table_list->getTableName(),
00121 createTableMessage().type());
00122
00123 if (not check(new_table_identifier))
00124 {
00125
00126 lex().link_first_table_back(create_table_list, link_to_local);
00127 return true;
00128 }
00129
00130
00131 create_info().alias= create_table_list->alias;
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146 if (session().wait_if_global_read_lock(0, 1))
00147 {
00148
00149 lex().link_first_table_back(create_table_list, link_to_local);
00150 return true;
00151 }
00152
00153 bool res= executeInner(new_table_identifier);
00154
00155
00156
00157
00158
00159 session().startWaitingGlobalReadLock();
00160
00161 return res;
00162 }
00163
00164 bool statement::CreateTable::executeInner(const identifier::Table& new_table_identifier)
00165 {
00166 bool res= false;
00167 Select_Lex *select_lex= &lex().select_lex;
00168 TableList *select_tables= lex().query_tables;
00169
00170 do
00171 {
00172 if (select_lex->item_list.size())
00173 {
00174 Select_Lex_Unit *unit= &lex().unit;
00175 select_result *result;
00176
00177 select_lex->options|= SELECT_NO_UNLOCK;
00178 unit->set_limit(select_lex);
00179
00180 if (not lex_identified_temp_table)
00181 {
00182 lex().link_first_table_back(create_table_list, link_to_local);
00183 create_table_list->setCreate(true);
00184 }
00185
00186 if (not (res= session().openTablesLock(lex().query_tables)))
00187 {
00188
00189
00190
00191
00192 if (not lex_identified_temp_table)
00193 {
00194 create_table_list= lex().unlink_first_table(&link_to_local);
00195
00196 if (unique_table(create_table_list, select_tables))
00197 {
00198 my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table_list->alias);
00199
00200 lex().link_first_table_back(create_table_list, link_to_local);
00201
00202 res= true;
00203 break;
00204 }
00205 }
00206
00207
00208
00209
00210
00211 if ((result= new select_create(create_table_list,
00212 lex().exists(),
00213 &create_info(),
00214 createTableMessage(),
00215 &alter_info,
00216 select_lex->item_list,
00217 lex().duplicates,
00218 lex().ignore,
00219 select_tables,
00220 new_table_identifier)))
00221 {
00222
00223
00224
00225
00226 res= handle_select(&session(), &lex(), result, 0);
00227 delete result;
00228 }
00229 }
00230 else if (not lex_identified_temp_table)
00231 {
00232 create_table_list= lex().unlink_first_table(&link_to_local);
00233 }
00234 }
00235 else
00236 {
00237
00238 if (is_create_table_like)
00239 {
00240 res= create_like_table(&session(),
00241 new_table_identifier,
00242 identifier::Table(select_tables->getSchemaName(),
00243 select_tables->getTableName()),
00244 createTableMessage(),
00245 lex().exists(),
00246 is_engine_set);
00247 }
00248 else
00249 {
00250
00251 for (int32_t x= 0; x < alter_info.added_fields_proto.added_field_size(); x++)
00252 {
00253 message::Table::Field *field= createTableMessage().add_field();
00254
00255 *field= alter_info.added_fields_proto.added_field(x);
00256 }
00257
00258 res= create_table(&session(),
00259 new_table_identifier,
00260 &create_info(),
00261 createTableMessage(),
00262 &alter_info,
00263 false,
00264 0,
00265 lex().exists());
00266 }
00267
00268 if (not res)
00269 {
00270 session().my_ok();
00271 }
00272 }
00273 } while (0);
00274
00275 return res;
00276 }
00277
00278 bool statement::CreateTable::check(const identifier::Table &identifier)
00279 {
00280
00281 if (not identifier.isValid())
00282 return false;
00283
00284
00285 if (not plugin::StorageEngine::canCreateTable(identifier))
00286 {
00287 identifier::Schema schema_identifier= identifier;
00288 error::access(*session().user(), schema_identifier);
00289
00290 return false;
00291 }
00292
00293
00294
00295 if (not plugin::StorageEngine::doesSchemaExist(identifier))
00296 {
00297 identifier::Schema schema_identifier= identifier;
00298 my_error(ER_BAD_DB_ERROR, schema_identifier);
00299
00300 return false;
00301 }
00302
00303 return true;
00304 }
00305
00306 bool statement::CreateTable::validateCreateTableOption()
00307 {
00308 bool rc= true;
00309 size_t num_engine_options= createTableMessage().engine().options_size();
00310
00311 assert(create_info().db_type);
00312
00313 for (size_t y= 0; y < num_engine_options; ++y)
00314 {
00315 bool valid= create_info().db_type->validateCreateTableOption(createTableMessage().engine().options(y).name(),
00316 createTableMessage().engine().options(y).state());
00317
00318 if (not valid)
00319 {
00320 my_error(ER_UNKNOWN_ENGINE_OPTION, MYF(0),
00321 createTableMessage().engine().options(y).name().c_str(),
00322 createTableMessage().engine().options(y).state().c_str());
00323
00324 rc= false;
00325 }
00326 }
00327
00328 return rc;
00329 }
00330
00331 }