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