1484
1484
@note the following two methods implement create [temporary] table.
1486
1486
static bool drizzle_create_table(Session *session,
1487
const TableIdentifier &identifier,
1487
const identifier::Table &identifier,
1488
1488
HA_CREATE_INFO *create_info,
1489
1489
message::Table &table_proto,
1490
1490
AlterInfo *alter_info,
1543
1543
Database locking aware wrapper for create_table_no_lock(),
1545
1545
bool create_table(Session *session,
1546
const TableIdentifier &identifier,
1546
const identifier::Table &identifier,
1547
1547
HA_CREATE_INFO *create_info,
1548
1548
message::Table &table_proto,
1549
1549
AlterInfo *alter_info,
1857
1857
const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1858
1858
"Waiting to get writelock");
1859
1859
session->abortLock(table->table);
1860
TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1860
identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1861
1861
table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1862
1862
session->exit_cond(old_message);
1863
1863
if (session->getKilled())
1999
1999
during the call to plugin::StorageEngine::createTable().
2000
2000
See bug #28614 for more info.
2002
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
2003
const TableIdentifier &destination_identifier,
2004
const TableIdentifier &src_table,
2002
static bool create_table_wrapper(Session &session,
2003
const message::Table& create_table_proto,
2004
identifier::Table::const_reference destination_identifier,
2005
identifier::Table::const_reference source_identifier,
2005
2006
bool is_engine_set)
2008
message::Table new_proto;
2009
message::table::shared_ptr src_proto;
2011
protoerr= plugin::StorageEngine::getTableDefinition(session,
2014
new_proto.CopyFrom(*src_proto);
2008
// We require an additional table message because during parsing we used
2009
// a "new" message and it will not have all of the information that the
2010
// source table message would have.
2011
message::Table new_table_message;
2012
drizzled::error_t error;
2014
message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier, error);
2016
if (not source_table_message)
2018
my_error(ER_TABLE_UNKNOWN, source_identifier);
2022
new_table_message.CopyFrom(*source_table_message);
2016
2024
if (destination_identifier.isTmp())
2018
new_proto.set_type(message::Table::TEMPORARY);
2026
new_table_message.set_type(message::Table::TEMPORARY);
2022
new_proto.set_type(message::Table::STANDARD);
2030
new_table_message.set_type(message::Table::STANDARD);
2025
2033
if (is_engine_set)
2027
new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2035
new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
2030
2038
{ // We now do a selective copy of elements on to the new table.
2031
new_proto.set_name(create_table_proto.name());
2032
new_proto.set_schema(create_table_proto.schema());
2033
new_proto.set_catalog(create_table_proto.catalog());
2039
new_table_message.set_name(create_table_proto.name());
2040
new_table_message.set_schema(create_table_proto.schema());
2041
new_table_message.set_catalog(create_table_proto.catalog());
2036
if (protoerr && protoerr != EEXIST)
2044
/* Fix names of foreign keys being added */
2045
for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
2038
if (errno == ENOENT)
2039
my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2041
my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2047
if (new_table_message.fk_constraint(j).has_name())
2049
std::string name(new_table_message.name());
2052
name.append("_ibfk_");
2053
snprintf(number, sizeof(number), "%d", j+1);
2054
name.append(number);
2056
message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2057
pfkey->set_name(name);
2078
2093
bool create_like_table(Session* session,
2079
const TableIdentifier &destination_identifier,
2080
TableList* table, TableList* src_table,
2094
identifier::Table::const_reference destination_identifier,
2095
identifier::Table::const_reference source_identifier,
2081
2096
message::Table &create_table_proto,
2082
2097
bool is_if_not_exists,
2083
2098
bool is_engine_set)
2085
2100
bool res= true;
2089
By opening source table we guarantee that it exists and no concurrent
2090
DDL operation will mess with it. Later we also take an exclusive
2091
name-lock on target table name, which makes copying of .frm cursor,
2092
call to plugin::StorageEngine::createTable() and binlogging atomic
2093
against concurrent DML and DDL operations on target table.
2094
Thus by holding both these "locks" we ensure that our statement is
2095
properly isolated from all concurrent operations which matter.
2097
if (session->open_tables_from_list(&src_table, ¬_used))
2100
TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
2101
src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
2101
bool table_exists= false;
2106
2104
Check that destination tables does not exist. Note that its name
2120
bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2121
src_identifier, is_engine_set);
2117
bool was_created= create_table_wrapper(*session,
2119
destination_identifier,
2122
2122
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2124
2124
(void) session->rm_temporary_table(destination_identifier, true);
2164
2164
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2165
2165
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2166
src_identifier, is_engine_set);
2166
source_identifier, is_engine_set);
2169
2169
// So we blew the creation of the table, and we scramble to clean up
2192
2192
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2193
2193
snprintf(warn_buff, sizeof(warn_buff),
2194
ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2194
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2195
2195
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2196
ER_TABLE_EXISTS_ERROR,warn_buff);
2201
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
2196
ER_TABLE_EXISTS_ERROR, warn_buff);
2200
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);