~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_table.cc

  • Committer: Lee Bieber
  • Date: 2011-01-15 03:08:27 UTC
  • mfrom: (1994.5.38 doc)
  • mto: This revision was merged to the branch mainline in revision 2087.
  • Revision ID: kalebral@gmail.com-20110115030827-0h9s99kiknrmt9ti
Merge Stewart - some documentation clean up

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* drop and alter of tables */
17
17
 
18
 
#include <config.h>
 
18
#include "config.h"
19
19
#include <plugin/myisam/myisam.h>
20
20
#include <drizzled/show.h>
21
21
#include <drizzled/error.h>
26
26
#include <drizzled/sql_lex.h>
27
27
#include <drizzled/session.h>
28
28
#include <drizzled/sql_base.h>
29
 
#include <drizzled/strfunc.h>
 
29
#include "drizzled/strfunc.h"
 
30
#include <drizzled/db.h>
30
31
#include <drizzled/lock.h>
31
32
#include <drizzled/unireg.h>
32
33
#include <drizzled/item/int.h>
33
34
#include <drizzled/item/empty_string.h>
34
35
#include <drizzled/transaction_services.h>
35
 
#include <drizzled/transaction_services.h>
 
36
#include "drizzled/transaction_services.h"
36
37
#include <drizzled/table_proto.h>
37
38
#include <drizzled/plugin/client.h>
38
39
#include <drizzled/identifier.h>
39
 
#include <drizzled/internal/m_string.h>
40
 
#include <drizzled/global_charset_info.h>
41
 
#include <drizzled/charset.h>
42
 
 
43
 
#include <drizzled/definition/cache.h>
44
 
 
45
 
#include <drizzled/statement/alter_table.h>
46
 
#include <drizzled/sql_table.h>
47
 
#include <drizzled/pthread_globals.h>
48
 
#include <drizzled/typelib.h>
49
 
#include <drizzled/plugin/storage_engine.h>
 
40
#include "drizzled/internal/m_string.h"
 
41
#include "drizzled/global_charset_info.h"
 
42
#include "drizzled/charset.h"
 
43
 
 
44
#include "drizzled/definition/cache.h"
 
45
 
 
46
 
 
47
#include "drizzled/statement/alter_table.h"
 
48
#include "drizzled/sql_table.h"
 
49
#include "drizzled/pthread_globals.h"
50
50
 
51
51
#include <algorithm>
52
52
#include <sstream>
58
58
namespace drizzled
59
59
{
60
60
 
 
61
extern pid_t current_pid;
 
62
 
61
63
bool is_primary_key(KeyInfo *key_info)
62
64
{
63
65
  static const char * primary_key_name="PRIMARY";
85
87
    let's fetch the database default character set and
86
88
    apply it to the table.
87
89
  */
88
 
  identifier::Schema identifier(db);
 
90
  SchemaIdentifier identifier(db);
89
91
  if (create_info->default_table_charset == NULL)
90
92
    create_info->default_table_charset= plugin::StorageEngine::getSchemaCollation(identifier);
91
93
}
108
110
void write_bin_log(Session *session, const std::string &query)
109
111
{
110
112
  TransactionServices &transaction_services= TransactionServices::singleton();
111
 
  transaction_services.rawStatement(*session, query);
 
113
  transaction_services.rawStatement(session, query);
112
114
}
113
115
 
114
116
/*
139
141
*/
140
142
 
141
143
int rm_table_part2(Session *session, TableList *tables, bool if_exists,
142
 
                   bool drop_temporary)
 
144
                         bool drop_temporary)
143
145
{
144
146
  TableList *table;
145
 
  util::string::vector wrong_tables;
 
147
  String wrong_tables;
146
148
  int error= 0;
147
149
  bool foreign_key_error= false;
148
150
 
160
162
 
161
163
    for (table= tables; table; table= table->next_local)
162
164
    {
163
 
      identifier::Table tmp_identifier(table->getSchemaName(), table->getTableName());
 
165
      TableIdentifier tmp_identifier(table->getSchemaName(), table->getTableName());
164
166
 
165
167
      error= session->drop_temporary_table(tmp_identifier);
166
168
 
196
198
          break;
197
199
        }
198
200
      }
199
 
      identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
200
 
 
201
 
      message::table::shared_ptr message= plugin::StorageEngine::getTableMessage(*session, identifier, true);
 
201
      TableIdentifier identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
202
202
 
203
203
      if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
204
204
      {
205
205
        // Table was not found on disk and table can't be created from engine
206
206
        if (if_exists)
207
 
        {
208
207
          push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
209
208
                              ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
210
209
                              table->getTableName());
211
 
        }
212
210
        else
213
211
        {
214
212
          error= 1;
221
219
        /* Generate transaction event ONLY when we successfully drop */ 
222
220
        if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
223
221
        {
224
 
          if (message) // If we have no definition, we don't know if the table should have been replicated
225
 
          {
226
 
            TransactionServices &transaction_services= TransactionServices::singleton();
227
 
            transaction_services.dropTable(*session, identifier, *message, if_exists);
228
 
          }
 
222
          TransactionServices &transaction_services= TransactionServices::singleton();
 
223
          transaction_services.dropTable(session, identifier, if_exists);
229
224
        }
230
225
        else
231
226
        {
246
241
 
247
242
      if (error)
248
243
      {
249
 
        wrong_tables.push_back(table->getTableName());
 
244
        if (wrong_tables.length())
 
245
          wrong_tables.append(',');
 
246
        wrong_tables.append(String(table->getTableName(), system_charset_info));
250
247
      }
251
248
    }
252
249
 
254
251
 
255
252
  } while (0);
256
253
 
257
 
  if (wrong_tables.size())
 
254
  if (wrong_tables.length())
258
255
  {
259
256
    if (not foreign_key_error)
260
257
    {
261
 
      std::string table_error;
262
 
 
263
 
      for (util::string::vector::iterator iter= wrong_tables.begin();
264
 
           iter != wrong_tables.end();
265
 
           iter++)
266
 
      {
267
 
        table_error+= *iter;
268
 
        table_error+= ',';
269
 
      }
270
 
      table_error.resize(table_error.size() -1);
271
 
 
272
258
      my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
273
 
                      table_error.c_str());
 
259
                      wrong_tables.c_ptr());
274
260
    }
275
261
    else
276
262
    {
557
543
  int           timestamps= 0, timestamps_with_niladic= 0;
558
544
  int           dup_no;
559
545
  int           select_field_pos,auto_increment=0;
560
 
  List<CreateField>::iterator it(alter_info->create_list.begin());
561
 
  List<CreateField>::iterator it2(alter_info->create_list.begin());
 
546
  List_iterator<CreateField> it(alter_info->create_list);
 
547
  List_iterator<CreateField> it2(alter_info->create_list);
562
548
  uint32_t total_uneven_bit_length= 0;
563
549
 
564
550
  plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
652
638
        interval= sql_field->interval= typelib(session->mem_root,
653
639
                                               sql_field->interval_list);
654
640
 
655
 
        List<String>::iterator int_it(sql_field->interval_list.begin());
 
641
        List_iterator<String> int_it(sql_field->interval_list);
656
642
        String conv, *tmp;
657
643
        char comma_buf[4];
658
644
        int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
678
664
          interval->type_lengths[i]= lengthsp;
679
665
          ((unsigned char *)interval->type_names[i])[lengthsp]= '\0';
680
666
        }
681
 
        sql_field->interval_list.clear(); // Don't need interval_list anymore
 
667
        sql_field->interval_list.empty(); // Don't need interval_list anymore
682
668
      }
683
669
 
684
670
      /* DRIZZLE_TYPE_ENUM */
701
687
          else /* not NULL */
702
688
          {
703
689
            def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
704
 
            if (interval->find_type2(def->ptr(), def->length(), cs) == 0) /* not found */
 
690
            if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
705
691
            {
706
692
              my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
707
693
              return(true);
782
768
      (*db_options)|= HA_OPTION_PACK_RECORD;
783
769
    }
784
770
 
785
 
    it2= alter_info->create_list.begin();
 
771
    it2.rewind();
786
772
  }
787
773
 
788
774
  /* record_offset will be increased with 'length-of-null-bits' later */
789
775
  record_offset= 0;
790
776
  null_fields+= total_uneven_bit_length;
791
777
 
792
 
  it= alter_info->create_list.begin();
 
778
  it.rewind();
793
779
  while ((sql_field=it++))
794
780
  {
795
781
    assert(sql_field->charset != 0);
829
815
 
830
816
  /* Create keys */
831
817
 
832
 
  List<Key>::iterator key_iterator(alter_info->key_list.begin());
833
 
  List<Key>::iterator key_iterator2(alter_info->key_list.begin());
 
818
  List_iterator<Key> key_iterator(alter_info->key_list);
 
819
  List_iterator<Key> key_iterator2(alter_info->key_list);
834
820
  uint32_t key_parts=0, fk_key_count=0;
835
821
  bool primary_key=0,unique_key=0;
836
822
  Key *key, *key2;
880
866
    }
881
867
    if (check_identifier_name(&key->name, ER_TOO_LONG_IDENT))
882
868
      return(true);
883
 
    key_iterator2= alter_info->key_list.begin();
 
869
    key_iterator2.rewind ();
884
870
    if (key->type != Key::FOREIGN_KEY)
885
871
    {
886
872
      while ((key2 = key_iterator2++) != key)
933
919
  if (!*key_info_buffer || ! key_part_info)
934
920
    return(true);                               // Out of memory
935
921
 
936
 
  key_iterator= alter_info->key_list.begin();
 
922
  key_iterator.rewind();
937
923
  key_number=0;
938
924
  for (; (key=key_iterator++) ; key_number++)
939
925
  {
992
978
 
993
979
    message::Table::Field *protofield= NULL;
994
980
 
995
 
    List<Key_part_spec>::iterator cols(key->columns.begin());
996
 
    List<Key_part_spec>::iterator cols2(key->columns.begin());
 
981
    List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
997
982
    for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
998
983
    {
999
984
      uint32_t length;
1000
985
      Key_part_spec *dup_column;
1001
986
      int proto_field_nr= 0;
1002
987
 
1003
 
      it= alter_info->create_list.begin();
 
988
      it.rewind();
1004
989
      field=0;
1005
990
      while ((sql_field=it++) && ++proto_field_nr &&
1006
991
             my_strcasecmp(system_charset_info,
1027
1012
          return(true);
1028
1013
        }
1029
1014
      }
1030
 
      cols2= key->columns.begin();
 
1015
      cols2.rewind();
1031
1016
 
1032
1017
      if (create_proto.field_size() > 0)
1033
1018
        protofield= create_proto.mutable_field(proto_field_nr - 1);
1240
1225
                     (qsort_cmp) sort_keys);
1241
1226
 
1242
1227
  /* Check fields. */
1243
 
  it= alter_info->create_list.begin();
 
1228
  it.rewind();
1244
1229
  while ((sql_field=it++))
1245
1230
  {
1246
1231
    Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1247
1232
 
1248
1233
    if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
1249
1234
        !sql_field->def &&
1250
 
        (sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP  or sql_field->sql_type == DRIZZLE_TYPE_MICROTIME) &&
 
1235
        sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
1251
1236
        (sql_field->flags & NOT_NULL_FLAG) &&
1252
1237
        (type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1253
1238
    {
1311
1296
}
1312
1297
 
1313
1298
static bool locked_create_event(Session *session,
1314
 
                                const identifier::Table &identifier,
 
1299
                                const TableIdentifier &identifier,
1315
1300
                                HA_CREATE_INFO *create_info,
1316
1301
                                message::Table &table_proto,
1317
1302
                                AlterInfo *alter_info,
1346
1331
        return error;
1347
1332
      }
1348
1333
 
1349
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1334
      std::string path;
 
1335
      identifier.getSQLPath(path);
 
1336
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1350
1337
 
1351
1338
      return error;
1352
1339
    }
1366
1353
      */
1367
1354
      if (definition::Cache::singleton().find(identifier.getKey()))
1368
1355
      {
1369
 
        my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1356
        std::string path;
 
1357
        identifier.getSQLPath(path);
 
1358
        my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1370
1359
 
1371
1360
        return error;
1372
1361
      }
1405
1394
  if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1406
1395
  {
1407
1396
    TransactionServices &transaction_services= TransactionServices::singleton();
1408
 
    transaction_services.createTable(*session, table_proto);
 
1397
    transaction_services.createTable(session, table_proto);
1409
1398
  }
1410
1399
 
1411
1400
  return false;
1443
1432
*/
1444
1433
 
1445
1434
bool create_table_no_lock(Session *session,
1446
 
                                const identifier::Table &identifier,
 
1435
                                const TableIdentifier &identifier,
1447
1436
                                HA_CREATE_INFO *create_info,
1448
1437
                                message::Table &table_proto,
1449
1438
                                AlterInfo *alter_info,
1469
1458
 
1470
1459
  /* Build a Table object to pass down to the engine, and the do the actual create. */
1471
1460
  if (not prepare_create_table(session, create_info, table_proto, alter_info,
1472
 
                               internal_tmp_table,
1473
 
                               &db_options,
1474
 
                               &key_info_buffer, &key_count,
1475
 
                               select_field_count))
 
1461
                                     internal_tmp_table,
 
1462
                                     &db_options,
 
1463
                                     &key_info_buffer, &key_count,
 
1464
                                     select_field_count))
1476
1465
  {
1477
1466
    boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1478
1467
    error= locked_create_event(session,
1495
1484
  @note the following two methods implement create [temporary] table.
1496
1485
*/
1497
1486
static bool drizzle_create_table(Session *session,
1498
 
                                 const identifier::Table &identifier,
 
1487
                                 const TableIdentifier &identifier,
1499
1488
                                 HA_CREATE_INFO *create_info,
1500
1489
                                 message::Table &table_proto,
1501
1490
                                 AlterInfo *alter_info,
1522
1511
    }
1523
1512
    else
1524
1513
    {
1525
 
      my_error(ER_TABLE_EXISTS_ERROR, identifier);
 
1514
      std::string path;
 
1515
      identifier.getSQLPath(path);
 
1516
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), path.c_str());
1526
1517
      result= true;
1527
1518
    }
1528
1519
  }
1552
1543
  Database locking aware wrapper for create_table_no_lock(),
1553
1544
*/
1554
1545
bool create_table(Session *session,
1555
 
                        const identifier::Table &identifier,
 
1546
                        const TableIdentifier &identifier,
1556
1547
                        HA_CREATE_INFO *create_info,
1557
1548
                        message::Table &table_proto,
1558
1549
                        AlterInfo *alter_info,
1648
1639
bool
1649
1640
rename_table(Session &session,
1650
1641
                   plugin::StorageEngine *base,
1651
 
                   const identifier::Table &from,
1652
 
                   const identifier::Table &to)
 
1642
                   const TableIdentifier &from,
 
1643
                   const TableIdentifier &to)
1653
1644
{
1654
1645
  int error= 0;
1655
1646
 
1715
1706
  session->abortLock(table);    /* end threads waiting on lock */
1716
1707
 
1717
1708
  /* Wait until all there are no other threads that has this table open */
1718
 
  identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
 
1709
  TableIdentifier identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1719
1710
  table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
1720
1711
}
1721
1712
 
1768
1759
                                                            HA_CHECK_OPT *))
1769
1760
{
1770
1761
  TableList *table;
1771
 
  Select_Lex *select= &session->getLex()->select_lex;
 
1762
  Select_Lex *select= &session->lex->select_lex;
1772
1763
  List<Item> field_list;
1773
1764
  Item *item;
 
1765
  LEX *lex= session->lex;
1774
1766
  int result_code= 0;
1775
1767
  TransactionServices &transaction_services= TransactionServices::singleton();
1776
1768
  const CHARSET_INFO * const cs= system_charset_info;
1777
1769
 
1778
1770
  if (! session->endActiveTransaction())
1779
1771
    return 1;
1780
 
 
1781
1772
  field_list.push_back(item = new Item_empty_string("Table",
1782
1773
                                                    NAME_CHAR_LEN * 2,
1783
1774
                                                    cs));
1793
1784
 
1794
1785
  for (table= tables; table; table= table->next_local)
1795
1786
  {
1796
 
    identifier::Table table_identifier(table->getSchemaName(), table->getTableName());
1797
 
    std::string table_name;
 
1787
    char table_name[NAME_LEN*2+2];
1798
1788
    bool fatal_error=0;
1799
1789
 
1800
 
    table_identifier.getSQLPath(table_name);
1801
 
 
 
1790
    snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
1802
1791
    table->lock_type= lock_type;
1803
1792
    /* open only one table from local list of command */
1804
1793
    {
1813
1802
        so it have to be prepared.
1814
1803
        @todo Investigate if we can put extra tables into argument instead of using lex->query_tables
1815
1804
      */
1816
 
      session->getLex()->query_tables= table;
1817
 
      session->getLex()->query_tables_last= &table->next_global;
1818
 
      session->getLex()->query_tables_own_last= 0;
 
1805
      lex->query_tables= table;
 
1806
      lex->query_tables_last= &table->next_global;
 
1807
      lex->query_tables_own_last= 0;
1819
1808
      session->no_warnings_for_error= 0;
1820
1809
 
1821
1810
      session->openTablesLock(table);
1845
1834
    {
1846
1835
      char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1847
1836
      uint32_t length;
1848
 
      session->getClient()->store(table_name.c_str());
 
1837
      session->getClient()->store(table_name);
1849
1838
      session->getClient()->store(operator_name);
1850
1839
      session->getClient()->store(STRING_WITH_LEN("error"));
1851
1840
      length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1852
 
                       table_name.c_str());
 
1841
                       table_name);
1853
1842
      session->getClient()->store(buff, length);
1854
 
      transaction_services.autocommitOrRollback(*session, false);
 
1843
      transaction_services.autocommitOrRollback(session, false);
1855
1844
      session->endTransaction(COMMIT);
1856
1845
      session->close_thread_tables();
1857
 
      session->getLex()->reset_query_tables_list(false);
 
1846
      lex->reset_query_tables_list(false);
1858
1847
      table->table=0;                           // For query cache
1859
1848
      if (session->getClient()->flush())
1860
1849
        goto err;
1868
1857
      const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1869
1858
                                                  "Waiting to get writelock");
1870
1859
      session->abortLock(table->table);
1871
 
      identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
 
1860
      TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1872
1861
      table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1873
1862
      session->exit_cond(old_message);
1874
1863
      if (session->getKilled())
1880
1869
 
1881
1870
send_result:
1882
1871
 
1883
 
    session->getLex()->cleanup_after_one_table_open();
 
1872
    lex->cleanup_after_one_table_open();
1884
1873
    session->clear_error();  // these errors shouldn't get client
1885
1874
    {
1886
 
      List<DRIZZLE_ERROR>::iterator it(session->warn_list.begin());
 
1875
      List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1887
1876
      DRIZZLE_ERROR *err;
1888
1877
      while ((err= it++))
1889
1878
      {
1890
 
        session->getClient()->store(table_name.c_str());
 
1879
        session->getClient()->store(table_name);
1891
1880
        session->getClient()->store(operator_name);
1892
1881
        session->getClient()->store(warning_level_names[err->level].str,
1893
1882
                               warning_level_names[err->level].length);
1897
1886
      }
1898
1887
      drizzle_reset_errors(session, true);
1899
1888
    }
1900
 
    session->getClient()->store(table_name.c_str());
 
1889
    session->getClient()->store(table_name);
1901
1890
    session->getClient()->store(operator_name);
1902
1891
 
1903
1892
    switch (result_code) {
1970
1959
        else
1971
1960
        {
1972
1961
          boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1973
 
          identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
 
1962
          TableIdentifier identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1974
1963
          table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
1975
1964
        }
1976
1965
      }
1977
1966
    }
1978
 
    transaction_services.autocommitOrRollback(*session, false);
 
1967
    transaction_services.autocommitOrRollback(session, false);
1979
1968
    session->endTransaction(COMMIT);
1980
1969
    session->close_thread_tables();
1981
1970
    table->table=0;                             // For query cache
1987
1976
  return(false);
1988
1977
 
1989
1978
err:
1990
 
  transaction_services.autocommitOrRollback(*session, true);
 
1979
  transaction_services.autocommitOrRollback(session, true);
1991
1980
  session->endTransaction(ROLLBACK);
1992
1981
  session->close_thread_tables();                       // Shouldn't be needed
1993
1982
  if (table)
2010
1999
    during the call to plugin::StorageEngine::createTable().
2011
2000
    See bug #28614 for more info.
2012
2001
  */
2013
 
static bool create_table_wrapper(Session &session,
2014
 
                                 const message::Table& create_table_proto,
2015
 
                                 identifier::Table::const_reference destination_identifier,
2016
 
                                 identifier::Table::const_reference source_identifier,
 
2002
static bool create_table_wrapper(Session &session, const message::Table& create_table_proto,
 
2003
                                 const TableIdentifier &destination_identifier,
 
2004
                                 const TableIdentifier &src_table,
2017
2005
                                 bool is_engine_set)
2018
2006
{
2019
 
  // We require an additional table message because during parsing we used
2020
 
  // a "new" message and it will not have all of the information that the
2021
 
  // source table message would have.
2022
 
  message::Table new_table_message;
2023
 
 
2024
 
  message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier);
2025
 
 
2026
 
  if (not source_table_message)
2027
 
  {
2028
 
    my_error(ER_TABLE_UNKNOWN, source_identifier);
2029
 
    return false;
2030
 
  }
2031
 
 
2032
 
  new_table_message.CopyFrom(*source_table_message);
 
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);
2033
2015
 
2034
2016
  if (destination_identifier.isTmp())
2035
2017
  {
2036
 
    new_table_message.set_type(message::Table::TEMPORARY);
 
2018
    new_proto.set_type(message::Table::TEMPORARY);
2037
2019
  }
2038
2020
  else
2039
2021
  {
2040
 
    new_table_message.set_type(message::Table::STANDARD);
 
2022
    new_proto.set_type(message::Table::STANDARD);
2041
2023
  }
2042
2024
 
2043
2025
  if (is_engine_set)
2044
2026
  {
2045
 
    new_table_message.mutable_engine()->set_name(create_table_proto.engine().name());
 
2027
    new_proto.mutable_engine()->set_name(create_table_proto.engine().name());
2046
2028
  }
2047
2029
 
2048
2030
  { // We now do a selective copy of elements on to the new table.
2049
 
    new_table_message.set_name(create_table_proto.name());
2050
 
    new_table_message.set_schema(create_table_proto.schema());
2051
 
    new_table_message.set_catalog(create_table_proto.catalog());
 
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());
2052
2034
  }
2053
2035
 
2054
 
  /* Fix names of foreign keys being added */
2055
 
  for (int32_t j= 0; j < new_table_message.fk_constraint_size(); j++)
 
2036
  if (protoerr && protoerr != EEXIST)
2056
2037
  {
2057
 
    if (new_table_message.fk_constraint(j).has_name())
2058
 
    {
2059
 
      std::string name(new_table_message.name());
2060
 
      char number[20];
2061
 
 
2062
 
      name.append("_ibfk_");
2063
 
      snprintf(number, sizeof(number), "%d", j+1);
2064
 
      name.append(number);
2065
 
 
2066
 
      message::Table::ForeignKeyConstraint *pfkey= new_table_message.mutable_fk_constraint(j);
2067
 
      pfkey->set_name(name);
2068
 
    }
 
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;
2069
2044
  }
2070
2045
 
2071
2046
  /*
2074
2049
  */
2075
2050
  bool success= plugin::StorageEngine::createTable(session,
2076
2051
                                                   destination_identifier,
2077
 
                                                   new_table_message);
 
2052
                                                   new_proto);
2078
2053
 
2079
2054
  if (success && not destination_identifier.isTmp())
2080
2055
  {
2081
2056
    TransactionServices &transaction_services= TransactionServices::singleton();
2082
 
    transaction_services.createTable(session, new_table_message);
 
2057
    transaction_services.createTable(&session, new_proto);
2083
2058
  }
2084
2059
 
2085
2060
  return success;
2101
2076
*/
2102
2077
 
2103
2078
bool create_like_table(Session* session,
2104
 
                       identifier::Table::const_reference destination_identifier,
2105
 
                       identifier::Table::const_reference source_identifier,
 
2079
                       const TableIdentifier &destination_identifier,
 
2080
                       TableList* table, TableList* src_table,
2106
2081
                       message::Table &create_table_proto,
2107
2082
                       bool is_if_not_exists,
2108
2083
                       bool is_engine_set)
2109
2084
{
2110
2085
  bool res= true;
2111
 
  bool table_exists= false;
 
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
  TableIdentifier src_identifier(src_table->table->getShare()->getSchemaName(),
 
2101
                                 src_table->table->getShare()->getTableName(), src_table->table->getShare()->getType());
 
2102
 
 
2103
 
2112
2104
 
2113
2105
  /*
2114
2106
    Check that destination tables does not exist. Note that its name
2116
2108
 
2117
2109
    For temporary tables we don't aim to grab locks.
2118
2110
  */
 
2111
  bool table_exists= false;
2119
2112
  if (destination_identifier.isTmp())
2120
2113
  {
2121
2114
    if (session->find_temporary_table(destination_identifier))
2124
2117
    }
2125
2118
    else
2126
2119
    {
2127
 
      bool was_created= create_table_wrapper(*session,
2128
 
                                             create_table_proto,
2129
 
                                             destination_identifier,
2130
 
                                             source_identifier,
2131
 
                                             is_engine_set);
 
2120
      bool was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
 
2121
                                             src_identifier, is_engine_set);
2132
2122
      if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2133
2123
      {
2134
2124
        (void) session->rm_temporary_table(destination_identifier, true);
2173
2163
      {
2174
2164
        boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2175
2165
        was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2176
 
                                          source_identifier, is_engine_set);
 
2166
                                               src_identifier, is_engine_set);
2177
2167
      }
2178
2168
 
2179
2169
      // So we blew the creation of the table, and we scramble to clean up
2201
2191
    {
2202
2192
      char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
2193
      snprintf(warn_buff, sizeof(warn_buff),
2204
 
               ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
 
2194
               ER(ER_TABLE_EXISTS_ERROR), table->getTableName());
2205
2195
      push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
 
                   ER_TABLE_EXISTS_ERROR, warn_buff);
2207
 
      return false;
2208
 
    }
2209
 
 
2210
 
    my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2211
 
 
2212
 
    return true;
 
2196
                   ER_TABLE_EXISTS_ERROR,warn_buff);
 
2197
      res= false;
 
2198
    }
 
2199
    else
 
2200
    {
 
2201
      my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table->getTableName());
 
2202
    }
2213
2203
  }
2214
2204
 
2215
 
  return res;
 
2205
  return(res);
2216
2206
}
2217
2207
 
2218
2208