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 identifier::Table &destination_identifier,
2004
const identifier::Table &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 identifier::Table &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
identifier::Table src_identifier(src_table->table->getShare()->getSchemaName(),
2101
src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
2101
bool table_exists= false;
2104
2104
Check that destination tables does not exist. Note that its name
2118
bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2119
src_identifier, is_engine_set);
2117
bool was_created= create_table_wrapper(*session,
2119
destination_identifier,
2120
2122
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2122
2124
(void) session->rm_temporary_table(destination_identifier, true);
2162
2164
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2163
2165
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2164
src_identifier, is_engine_set);
2166
source_identifier, is_engine_set);
2167
2169
// So we blew the creation of the table, and we scramble to clean up
2190
2192
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2191
2193
snprintf(warn_buff, sizeof(warn_buff),
2192
ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2194
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2193
2195
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2194
ER_TABLE_EXISTS_ERROR,warn_buff);
2199
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);