~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Brian Aker
  • Date: 2011-01-18 07:21:16 UTC
  • mfrom: (2079.3.3 session-fix)
  • Revision ID: brian@tangent.org-20110118072116-nuflltzguzhq9rgg
Merge in update so that test-run.pl runs all of test/suite and fix for
create table like and FK.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1999
1999
    during the call to plugin::StorageEngine::createTable().
2000
2000
    See bug #28614 for more info.
2001
2001
  */
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)
2006
2007
{
2007
 
  int protoerr;
2008
 
  message::Table new_proto;
2009
 
  message::table::shared_ptr src_proto;
2010
 
 
2011
 
  protoerr= plugin::StorageEngine::getTableDefinition(session,
2012
 
                                                      src_table,
2013
 
                                                      src_proto);
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;
 
2013
 
 
2014
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier, error);
 
2015
 
 
2016
  if (not source_table_message)
 
2017
  {
 
2018
    my_error(ER_TABLE_UNKNOWN, source_identifier);
 
2019
    return false;
 
2020
  }
 
2021
 
 
2022
  new_table_message.CopyFrom(*source_table_message);
2015
2023
 
2016
2024
  if (destination_identifier.isTmp())
2017
2025
  {
2018
 
    new_proto.set_type(message::Table::TEMPORARY);
 
2026
    new_table_message.set_type(message::Table::TEMPORARY);
2019
2027
  }
2020
2028
  else
2021
2029
  {
2022
 
    new_proto.set_type(message::Table::STANDARD);
 
2030
    new_table_message.set_type(message::Table::STANDARD);
2023
2031
  }
2024
2032
 
2025
2033
  if (is_engine_set)
2026
2034
  {
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());
2028
2036
  }
2029
2037
 
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());
2034
2042
  }
2035
2043
 
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++)
2037
2046
  {
2038
 
    if (errno == ENOENT)
2039
 
      my_error(ER_BAD_DB_ERROR,MYF(0), destination_identifier.getSchemaName().c_str());
2040
 
    else
2041
 
      my_error(ER_CANT_CREATE_FILE, MYF(0), destination_identifier.getPath().c_str(), errno);
2042
 
 
2043
 
    return false;
 
2047
    if (new_table_message.fk_constraint(j).has_name())
 
2048
    {
 
2049
      std::string name(new_table_message.name());
 
2050
      char number[20];
 
2051
 
 
2052
      name.append("_ibfk_");
 
2053
      snprintf(number, sizeof(number), "%d", j+1);
 
2054
      name.append(number);
 
2055
 
 
2056
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
 
2057
      pfkey->set_name(name);
 
2058
    }
2044
2059
  }
2045
2060
 
2046
2061
  /*
2049
2064
  */
2050
2065
  bool success= plugin::StorageEngine::createTable(session,
2051
2066
                                                   destination_identifier,
2052
 
                                                   new_proto);
 
2067
                                                   new_table_message);
2053
2068
 
2054
2069
  if (success && not destination_identifier.isTmp())
2055
2070
  {
2056
2071
    TransactionServices &transaction_services= TransactionServices::singleton();
2057
 
    transaction_services.createTable(&session, new_proto);
 
2072
    transaction_services.createTable(&session, new_table_message);
2058
2073
  }
2059
2074
 
2060
2075
  return success;
2076
2091
*/
2077
2092
 
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)
2084
2099
{
2085
2100
  bool res= true;
2086
 
  uint32_t not_used;
2087
 
 
2088
 
  /*
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.
2096
 
  */
2097
 
  if (session->open_tables_from_list(&src_table, &not_used))
2098
 
    return true;
2099
 
 
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;
2102
2102
 
2103
2103
  /*
2104
2104
    Check that destination tables does not exist. Note that its name
2106
2106
 
2107
2107
    For temporary tables we don't aim to grab locks.
2108
2108
  */
2109
 
  bool table_exists= false;
2110
2109
  if (destination_identifier.isTmp())
2111
2110
  {
2112
2111
    if (session->find_temporary_table(destination_identifier))
2115
2114
    }
2116
2115
    else
2117
2116
    {
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,
 
2118
                                             create_table_proto,
 
2119
                                             destination_identifier,
 
2120
                                             source_identifier,
 
2121
                                             is_engine_set);
2120
2122
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2121
2123
      {
2122
2124
        (void) session->rm_temporary_table(destination_identifier, true);
2161
2163
      {
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);
2165
2167
      }
2166
2168
 
2167
2169
      // So we blew the creation of the table, and we scramble to clean up
2189
2191
    {
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);
2195
 
      res= false;
2196
 
    }
2197
 
    else
2198
 
    {
2199
 
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
2200
 
    }
 
2196
                   ER_TABLE_EXISTS_ERROR, warn_buff);
 
2197
      return false;
 
2198
    }
 
2199
 
 
2200
    my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
 
2201
 
 
2202
    return true;
2201
2203
  }
2202
2204
 
2203
 
  return(res);
 
2205
  return res;
2204
2206
}
2205
2207
 
2206
2208