16
16
/* drop and alter of tables */
19
19
#include <plugin/myisam/myisam.h>
20
20
#include <drizzled/show.h>
21
21
#include <drizzled/error.h>
22
22
#include <drizzled/gettext.h>
23
23
#include <drizzled/data_home.h>
24
24
#include <drizzled/sql_parse.h>
25
#include <drizzled/my_hash.h>
26
25
#include <drizzled/sql_lex.h>
27
26
#include <drizzled/session.h>
28
27
#include <drizzled/sql_base.h>
29
#include "drizzled/strfunc.h"
30
#include <drizzled/db.h>
31
28
#include <drizzled/lock.h>
32
29
#include <drizzled/unireg.h>
33
30
#include <drizzled/item/int.h>
34
31
#include <drizzled/item/empty_string.h>
35
32
#include <drizzled/transaction_services.h>
36
#include "drizzled/transaction_services.h"
33
#include <drizzled/transaction_services.h>
37
34
#include <drizzled/table_proto.h>
38
35
#include <drizzled/plugin/client.h>
39
36
#include <drizzled/identifier.h>
40
#include "drizzled/internal/m_string.h"
41
#include "drizzled/global_charset_info.h"
42
#include "drizzled/charset.h"
44
#include "drizzled/definition/cache.h"
47
#include "drizzled/statement/alter_table.h"
48
#include "drizzled/sql_table.h"
49
#include "drizzled/pthread_globals.h"
50
#include "drizzled/plugin/storage_engine.h"
37
#include <drizzled/internal/m_string.h>
38
#include <drizzled/charset.h>
39
#include <drizzled/definition/cache.h>
40
#include <drizzled/system_variables.h>
41
#include <drizzled/statement/alter_table.h>
42
#include <drizzled/sql_table.h>
43
#include <drizzled/pthread_globals.h>
44
#include <drizzled/typelib.h>
45
#include <drizzled/plugin/storage_engine.h>
46
#include <drizzled/diagnostics_area.h>
47
#include <drizzled/open_tables_state.h>
48
#include <drizzled/table/cache.h>
52
50
#include <algorithm>
99
query_length Length of query
105
Write the binlog if open, routine used in multiple places in this
109
void write_bin_log(Session *session, const std::string &query)
111
TransactionServices &transaction_services= TransactionServices::singleton();
112
transaction_services.rawStatement(*session, query);
116
92
Execute the drop of a normal or temporary table
143
119
bool drop_temporary)
145
121
TableList *table;
122
util::string::vector wrong_tables;
148
124
bool foreign_key_error= false;
152
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex());
128
boost::mutex::scoped_lock scopedLock(table::Cache::mutex());
154
130
if (not drop_temporary && session->lock_table_names_exclusively(tables))
180
156
if (drop_temporary == false)
183
158
abort_locked_tables(session, tmp_identifier);
184
table::Cache::singleton().removeTable(session, tmp_identifier,
185
RTFC_WAIT_OTHER_THREAD_FLAG |
186
RTFC_CHECK_KILLED_FLAG);
159
table::Cache::removeTable(*session, tmp_identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
188
161
If the table was used in lock tables, remember it so that
189
162
unlock_table_names can free it
191
if ((locked_table= drop_locked_tables(session, tmp_identifier)))
164
Table *locked_table= drop_locked_tables(session, tmp_identifier);
192
166
table->table= locked_table;
194
168
if (session->getKilled())
200
174
identifier::Table identifier(table->getSchemaName(), table->getTableName(), table->getInternalTmpTable() ? message::Table::INTERNAL : message::Table::STANDARD);
176
message::table::shared_ptr message= plugin::StorageEngine::getTableMessage(*session, identifier, true);
202
178
if (drop_temporary || not plugin::StorageEngine::doesTableExist(*session, identifier))
204
180
// Table was not found on disk and table can't be created from engine
206
183
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
207
184
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
208
185
table->getTableName());
218
196
/* Generate transaction event ONLY when we successfully drop */
219
197
if (plugin::StorageEngine::dropTable(*session, identifier, local_error))
221
TransactionServices &transaction_services= TransactionServices::singleton();
222
transaction_services.dropTable(*session, identifier, if_exists);
199
if (message) // If we have no definition, we don't know if the table should have been replicated
201
TransactionServices &transaction_services= TransactionServices::singleton();
202
transaction_services.dropTable(*session, identifier, *message, if_exists);
243
if (wrong_tables.length())
244
wrong_tables.append(',');
245
wrong_tables.append(String(table->getTableName(), system_charset_info));
224
wrong_tables.push_back(table->getTableName());
253
if (wrong_tables.length())
232
if (wrong_tables.size())
255
234
if (not foreign_key_error)
236
std::string table_error;
238
BOOST_FOREACH(util::string::vector::reference iter, wrong_tables)
243
table_error.resize(table_error.size() -1);
257
245
my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0),
258
wrong_tables.c_ptr());
246
table_error.c_str());
341
const CHARSET_INFO * const cs;
329
const charset_info_st * const cs;
343
331
typelib_set_member(const char* value, unsigned int length,
344
const CHARSET_INFO * const charset)
332
const charset_info_st * const charset)
345
333
: s(value, length),
371
359
static bool check_duplicates_in_interval(const char *set_or_name,
372
360
const char *name, TYPELIB *typelib,
373
const CHARSET_INFO * const cs,
361
const charset_info_st * const cs,
374
362
unsigned int *dup_val_count)
376
364
TYPELIB tmp= *typelib;
385
373
tmp.type_names++;
386
374
tmp.type_lengths++;
388
if (interval_set.find(typelib_set_member(*cur_value, *cur_length, cs)) != interval_set.end())
376
if (interval_set.count(typelib_set_member(*cur_value, *cur_length, cs)))
390
378
my_error(ER_DUPLICATED_VALUE_IN_TYPE, MYF(0),
391
379
name,*cur_value,set_or_name);
542
530
int timestamps= 0, timestamps_with_niladic= 0;
544
532
int select_field_pos,auto_increment=0;
545
List_iterator<CreateField> it(alter_info->create_list);
546
List_iterator<CreateField> it2(alter_info->create_list);
533
List<CreateField>::iterator it(alter_info->create_list.begin());
534
List<CreateField>::iterator it2(alter_info->create_list.begin());
547
535
uint32_t total_uneven_bit_length= 0;
549
537
plugin::StorageEngine *engine= plugin::StorageEngine::findByName(create_proto.engine().name());
551
select_field_pos= alter_info->create_list.elements - select_field_count;
539
select_field_pos= alter_info->create_list.size() - select_field_count;
552
540
null_fields=blob_columns=0;
553
541
max_key_length= engine->max_key_length();
555
543
for (int32_t field_no=0; (sql_field=it++) ; field_no++)
557
const CHARSET_INFO *save_cs;
545
const charset_info_st *save_cs;
560
548
Initialize length from its original value (number of characters),
637
625
interval= sql_field->interval= typelib(session->mem_root,
638
626
sql_field->interval_list);
640
List_iterator<String> int_it(sql_field->interval_list);
628
List<String>::iterator int_it(sql_field->interval_list.begin());
641
629
String conv, *tmp;
642
630
char comma_buf[4];
643
631
int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
651
639
if (String::needs_conversion(tmp->length(), tmp->charset(),
655
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
642
conv.copy(tmp->ptr(), tmp->length(), cs);
656
643
interval->type_names[i]= session->mem_root->strmake_root(conv.ptr(), conv.length());
657
644
interval->type_lengths[i]= conv.length();
686
673
else /* not NULL */
688
675
def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
689
if (find_type2(interval, def->ptr(), def->length(), cs) == 0) /* not found */
676
if (interval->find_type2(def->ptr(), def->length(), cs) == 0) /* not found */
691
678
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
767
754
(*db_options)|= HA_OPTION_PACK_RECORD;
757
it2= alter_info->create_list.begin();
773
760
/* record_offset will be increased with 'length-of-null-bits' later */
774
761
record_offset= 0;
775
762
null_fields+= total_uneven_bit_length;
764
it= alter_info->create_list.begin();
778
765
while ((sql_field=it++))
780
767
assert(sql_field->charset != 0);
815
802
/* Create keys */
817
List_iterator<Key> key_iterator(alter_info->key_list);
818
List_iterator<Key> key_iterator2(alter_info->key_list);
804
List<Key>::iterator key_iterator(alter_info->key_list.begin());
805
List<Key>::iterator key_iterator2(alter_info->key_list.begin());
819
806
uint32_t key_parts=0, fk_key_count=0;
820
807
bool primary_key=0,unique_key=0;
845
832
fk_key->update_opt,
846
833
fk_key->match_opt);
848
if (fk_key->ref_columns.elements &&
849
fk_key->ref_columns.elements != fk_key->columns.elements)
835
if (fk_key->ref_columns.size() &&
836
fk_key->ref_columns.size() != fk_key->columns.size())
851
838
my_error(ER_WRONG_FK_DEF, MYF(0),
852
839
(fk_key->name.str ? fk_key->name.str :
860
847
tmp= engine->max_key_parts();
861
if (key->columns.elements > tmp)
848
if (key->columns.size() > tmp)
863
850
my_error(ER_TOO_MANY_KEY_PARTS,MYF(0),tmp);
866
853
if (check_identifier_name(&key->name, ER_TOO_LONG_IDENT))
868
key_iterator2.rewind ();
855
key_iterator2= alter_info->key_list.begin();
869
856
if (key->type != Key::FOREIGN_KEY)
871
858
while ((key2 = key_iterator2++) != key)
882
869
/* @todo issue warning message */
883
870
/* mark that the generated key should be ignored */
884
871
if (!key2->generated ||
885
(key->generated && key->columns.elements <
886
key2->columns.elements))
872
(key->generated && key->columns.size() <
873
key2->columns.size()))
887
874
key->name.str= ignore_key;
890
877
key2->name.str= ignore_key;
891
key_parts-= key2->columns.elements;
878
key_parts-= key2->columns.size();
949
936
if (key->generated)
950
937
key_info->flags|= HA_GENERATED_KEY;
952
key_info->key_parts=(uint8_t) key->columns.elements;
939
key_info->key_parts=(uint8_t) key->columns.size();
953
940
key_info->key_part=key_part_info;
954
941
key_info->usable_key_parts= key_number;
955
942
key_info->algorithm= key->key_create_info.algorithm;
978
965
message::Table::Field *protofield= NULL;
980
List_iterator<Key_part_spec> cols(key->columns), cols2(key->columns);
967
List<Key_part_spec>::iterator cols(key->columns.begin());
968
List<Key_part_spec>::iterator cols2(key->columns.begin());
981
969
for (uint32_t column_nr=0 ; (column=cols++) ; column_nr++)
984
972
Key_part_spec *dup_column;
985
973
int proto_field_nr= 0;
975
it= alter_info->create_list.begin();
989
977
while ((sql_field=it++) && ++proto_field_nr &&
990
978
my_strcasecmp(system_charset_info,
1224
1212
(qsort_cmp) sort_keys);
1226
1214
/* Check fields. */
1215
it= alter_info->create_list.begin();
1228
1216
while ((sql_field=it++))
1230
1218
Field::utype type= (Field::utype) MTYP_TYPENR(sql_field->unireg_check);
1232
1220
if (session->variables.sql_mode & MODE_NO_ZERO_DATE &&
1233
1221
!sql_field->def &&
1234
sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP &&
1222
(sql_field->sql_type == DRIZZLE_TYPE_TIMESTAMP or sql_field->sql_type == DRIZZLE_TYPE_MICROTIME) &&
1235
1223
(sql_field->flags & NOT_NULL_FLAG) &&
1236
1224
(type == Field::NONE || type == Field::TIMESTAMP_UN_FIELD))
1440
1428
bool error= true;
1442
1430
/* Check for duplicate fields and check type of table to create */
1443
if (not alter_info->create_list.elements)
1431
if (not alter_info->create_list.size())
1445
1433
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1458
1446
&key_info_buffer, &key_count,
1459
1447
select_field_count))
1461
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1449
boost::mutex::scoped_lock lock(table::Cache::mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1462
1450
error= locked_create_event(session,
1487
1475
uint32_t select_field_count,
1488
1476
bool is_if_not_exists)
1490
Table *name_lock= NULL;
1478
Table *name_lock= session->lock_table_name_if_not_cached(identifier);
1493
if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1497
else if (name_lock == NULL)
1480
if (name_lock == NULL)
1499
1482
if (is_if_not_exists)
1635
1618
const identifier::Table &from,
1636
1619
const identifier::Table &to)
1642
1621
if (not plugin::StorageEngine::doesSchemaExist(to))
1644
1623
my_error(ER_NO_DB_ERROR, MYF(0), to.getSchemaName().c_str());
1648
error= base->renameTable(session, from, to);
1627
int error= base->renameTable(session, from, to);
1650
1628
if (error == HA_ERR_WRONG_COMMAND)
1652
1629
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "ALTER Table");
1654
1630
else if (error)
1656
std::string from_path;
1657
std::string to_path;
1659
from.getSQLPath(from_path);
1660
to.getSQLPath(to_path);
1662
const char *from_identifier= from.isTmp() ? "#sql-temporary" : from_path.c_str();
1663
const char *to_identifier= to.isTmp() ? "#sql-temporary" : to_path.c_str();
1665
my_error(ER_ERROR_ON_RENAME, MYF(0), from_identifier, to_identifier, error);
1632
my_error(ER_ERROR_ON_RENAME, MYF(0),
1633
from.isTmp() ? "#sql-temporary" : from.getSQLPath().c_str(),
1634
to.isTmp() ? "#sql-temporary" : to.getSQLPath().c_str(), error);
1668
return error ? true : false;
1692
1660
enum ha_extra_function function)
1695
safe_mutex_assert_owner(table::Cache::singleton().mutex().native_handle());
1663
safe_mutex_assert_owner(table::Cache::mutex().native_handle());
1697
1665
table->cursor->extra(function);
1698
1666
/* Mark all tables that are in use as 'old' */
1701
1669
/* Wait until all there are no other threads that has this table open */
1702
1670
identifier::Table identifier(table->getShare()->getSchemaName(), table->getShare()->getTableName());
1703
table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
1671
table::Cache::removeTable(*session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG);
1726
1694
wait_while_table_is_used(this, table, HA_EXTRA_FORCE_REOPEN);
1727
1695
/* Close lock if this is not got with LOCK TABLES */
1696
if (open_tables.lock)
1731
lock= NULL; // Start locked threads
1698
unlockTables(open_tables.lock);
1699
open_tables.lock= NULL; // Start locked threads
1733
1701
/* Close all copies of 'table'. This also frees all LOCK TABLES lock */
1734
1702
unlink_open_table(table);
1736
/* When lock on table::Cache::singleton().mutex() is freed other threads can continue */
1704
/* When lock on table::Cache::mutex() is freed other threads can continue */
1737
1705
locking::broadcast_refresh();
1752
1720
HA_CHECK_OPT *))
1754
1722
TableList *table;
1755
Select_Lex *select= &session->lex->select_lex;
1723
Select_Lex *select= &session->lex().select_lex;
1756
1724
List<Item> field_list;
1758
LEX *lex= session->lex;
1759
1726
int result_code= 0;
1760
1727
TransactionServices &transaction_services= TransactionServices::singleton();
1761
const CHARSET_INFO * const cs= system_charset_info;
1728
const charset_info_st * const cs= system_charset_info;
1763
1730
if (! session->endActiveTransaction())
1765
1733
field_list.push_back(item = new Item_empty_string("Table",
1766
1734
NAME_CHAR_LEN * 2,
1778
1746
for (table= tables; table; table= table->next_local)
1780
char table_name[NAME_LEN*2+2];
1748
identifier::Table table_identifier(table->getSchemaName(), table->getTableName());
1781
1749
bool fatal_error=0;
1783
snprintf(table_name, sizeof(table_name), "%s.%s", table->getSchemaName(), table->getTableName());
1751
std::string table_name = table_identifier.getSQLPath();
1784
1753
table->lock_type= lock_type;
1785
1754
/* open only one table from local list of command */
1795
1764
so it have to be prepared.
1796
1765
@todo Investigate if we can put extra tables into argument instead of using lex->query_tables
1798
lex->query_tables= table;
1799
lex->query_tables_last= &table->next_global;
1800
lex->query_tables_own_last= 0;
1767
session->lex().query_tables= table;
1768
session->lex().query_tables_last= &table->next_global;
1769
session->lex().query_tables_own_last= 0;
1801
1770
session->no_warnings_for_error= 0;
1803
1772
session->openTablesLock(table);
1817
1786
if (!table->table)
1819
if (!session->warn_list.elements)
1788
if (!session->main_da().m_warn_list.size())
1820
1789
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1821
1790
ER_CHECK_NO_SUCH_TABLE, ER(ER_CHECK_NO_SUCH_TABLE));
1822
1791
result_code= HA_ADMIN_CORRUPT;
1828
1797
char buff[FN_REFLEN + DRIZZLE_ERRMSG_SIZE];
1829
1798
uint32_t length;
1830
session->getClient()->store(table_name);
1799
session->getClient()->store(table_name.c_str());
1831
1800
session->getClient()->store(operator_name);
1832
1801
session->getClient()->store(STRING_WITH_LEN("error"));
1833
1802
length= snprintf(buff, sizeof(buff), ER(ER_OPEN_AS_READONLY),
1803
table_name.c_str());
1835
1804
session->getClient()->store(buff, length);
1836
1805
transaction_services.autocommitOrRollback(*session, false);
1837
1806
session->endTransaction(COMMIT);
1838
1807
session->close_thread_tables();
1839
lex->reset_query_tables_list(false);
1808
session->lex().reset_query_tables_list(false);
1840
1809
table->table=0; // For query cache
1841
1810
if (session->getClient()->flush())
1846
1815
/* Close all instances of the table to allow repair to rename files */
1847
1816
if (lock_type == TL_WRITE && table->table->getShare()->getVersion())
1849
table::Cache::singleton().mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1850
const char *old_message=session->enter_cond(COND_refresh, table::Cache::singleton().mutex(),
1818
table::Cache::mutex().lock(); /* Lock type is TL_WRITE and we lock to repair the table */
1819
const char *old_message=session->enter_cond(COND_refresh, table::Cache::mutex(),
1851
1820
"Waiting to get writelock");
1852
1821
session->abortLock(table->table);
1853
1822
identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1854
table::Cache::singleton().removeTable(session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1823
table::Cache::removeTable(*session, identifier, RTFC_WAIT_OTHER_THREAD_FLAG | RTFC_CHECK_KILLED_FLAG);
1855
1824
session->exit_cond(old_message);
1856
1825
if (session->getKilled())
1865
lex->cleanup_after_one_table_open();
1834
session->lex().cleanup_after_one_table_open();
1866
1835
session->clear_error(); // these errors shouldn't get client
1868
List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
1837
List<DRIZZLE_ERROR>::iterator it(session->main_da().m_warn_list.begin());
1869
1838
DRIZZLE_ERROR *err;
1870
1839
while ((err= it++))
1872
session->getClient()->store(table_name);
1841
session->getClient()->store(table_name.c_str());
1873
1842
session->getClient()->store(operator_name);
1874
1843
session->getClient()->store(warning_level_names[err->level].str,
1875
1844
warning_level_names[err->level].length);
1954
boost::unique_lock<boost::mutex> lock(table::Cache::singleton().mutex());
1955
identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1956
table::Cache::singleton().removeTable(session, identifier, RTFC_NO_FLAG);
1923
boost::unique_lock<boost::mutex> lock(table::Cache::mutex());
1924
identifier::Table identifier(table->table->getShare()->getSchemaName(), table->table->getShare()->getTableName());
1925
table::Cache::removeTable(*session, identifier, RTFC_NO_FLAG);
1983
1952
Altough exclusive name-lock on target table protects us from concurrent
1984
1953
DML and DDL operations on it we still want to wrap .FRM creation and call
1985
1954
to plugin::StorageEngine::createTable() in critical section protected by
1986
table::Cache::singleton().mutex() in order to provide minimal atomicity against operations which
1955
table::Cache::mutex() in order to provide minimal atomicity against operations which
1987
1956
disregard name-locks, like I_S implementation, for example. This is a
1988
1957
temporary and should not be copied. Instead we should fix our code to
1989
1958
always honor name-locks.
1991
Also some engines (e.g. NDB cluster) require that table::Cache::singleton().mutex() should be held
1960
Also some engines (e.g. NDB cluster) require that table::Cache::mutex() should be held
1992
1961
during the call to plugin::StorageEngine::createTable().
1993
1962
See bug #28614 for more info.
1995
1964
static bool create_table_wrapper(Session &session,
1996
1965
const message::Table& create_table_proto,
1997
identifier::Table::const_reference destination_identifier,
1998
identifier::Table::const_reference source_identifier,
1966
const identifier::Table& destination_identifier,
1967
const identifier::Table& source_identifier,
1999
1968
bool is_engine_set)
2001
1970
// We require an additional table message because during parsing we used
2002
1971
// a "new" message and it will not have all of the information that the
2003
1972
// source table message would have.
2004
1973
message::Table new_table_message;
2005
drizzled::error_t error;
2007
message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier, error);
1975
message::table::shared_ptr source_table_message= plugin::StorageEngine::getTableMessage(session, source_identifier);
2009
1977
if (not source_table_message)
2086
2054
bool create_like_table(Session* session,
2087
identifier::Table::const_reference destination_identifier,
2088
identifier::Table::const_reference source_identifier,
2055
const identifier::Table& destination_identifier,
2056
const identifier::Table& source_identifier,
2089
2057
message::Table &create_table_proto,
2090
2058
bool is_if_not_exists,
2091
2059
bool is_engine_set)
2114
2082
is_engine_set);
2115
2083
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2117
(void) session->rm_temporary_table(destination_identifier, true);
2085
(void) session->open_tables.rm_temporary_table(destination_identifier, true);
2119
2087
else if (not session->open_temporary_table(destination_identifier))
2121
2089
// We created, but we can't open... also, a hack.
2122
(void) session->rm_temporary_table(destination_identifier, true);
2090
(void) session->open_tables.rm_temporary_table(destination_identifier, true);
2130
2098
else // Standard table which will require locks.
2132
Table *name_lock= 0;
2134
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2138
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2139
session->unlink_open_table(name_lock);
2100
Table *name_lock= session->lock_table_name_if_not_cached(destination_identifier);
2145
2101
if (not name_lock)
2147
2103
table_exists= true;
2155
2111
bool was_created;
2157
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2113
boost::mutex::scoped_lock lock(table::Cache::mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2158
2114
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2159
2115
source_identifier, is_engine_set);