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