18
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27
#include <drizzled/show.h>
28
#include <drizzled/lock.h>
29
#include <drizzled/session.h>
30
#include <drizzled/statement/alter_table.h>
31
#include <drizzled/global_charset_info.h>
34
#include <drizzled/gettext.h>
35
#include <drizzled/data_home.h>
36
#include <drizzled/sql_table.h>
37
#include <drizzled/table_proto.h>
38
#include <drizzled/optimizer/range.h>
39
#include <drizzled/time_functions.h>
40
#include <drizzled/records.h>
41
#include <drizzled/pthread_globals.h>
42
#include <drizzled/internal/my_sys.h>
43
#include <drizzled/internal/iocache.h>
44
#include <drizzled/plugin/storage_engine.h>
45
#include <drizzled/copy_field.h>
47
#include <drizzled/transaction_services.h>
49
#include <drizzled/filesort.h>
51
#include <drizzled/message.h>
27
#include "drizzled/show.h"
28
#include "drizzled/lock.h"
29
#include "drizzled/session.h"
30
#include "drizzled/statement/alter_table.h"
31
#include "drizzled/global_charset_info.h"
34
#include "drizzled/gettext.h"
35
#include "drizzled/data_home.h"
36
#include "drizzled/sql_table.h"
37
#include "drizzled/table_proto.h"
38
#include "drizzled/optimizer/range.h"
39
#include "drizzled/time_functions.h"
40
#include "drizzled/records.h"
41
#include "drizzled/pthread_globals.h"
42
#include "drizzled/internal/my_sys.h"
43
#include "drizzled/internal/iocache.h"
45
#include "drizzled/transaction_services.h"
47
#include "drizzled/filesort.h"
49
#include "drizzled/message.h"
53
51
using namespace std;
75
73
message::Table &table_message,
76
74
AlterInfo *alter_info);
78
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier);
82
AlterTable::AlterTable(Session *in_session, Table_ident *ident, drizzled::ha_build_method build_arg) :
83
CreateTable(in_session)
85
in_session->getLex()->sql_command= SQLCOM_ALTER_TABLE;
87
alter_info.build_method= build_arg;
90
} // namespace statement
76
static int create_temporary_table(Session *session,
77
TableIdentifier &identifier,
78
HA_CREATE_INFO *create_info,
79
message::Table &create_message,
80
AlterInfo *alter_info);
82
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier);
92
84
bool statement::AlterTable::execute()
94
TableList *first_table= (TableList *) getSession()->getLex()->select_lex.table_list.first;
95
TableList *all_tables= getSession()->getLex()->query_tables;
86
TableList *first_table= (TableList *) session->lex->select_lex.table_list.first;
87
TableList *all_tables= session->lex->query_tables;
96
88
assert(first_table == all_tables && first_table != 0);
97
Select_Lex *select_lex= &getSession()->getLex()->select_lex;
89
Select_Lex *select_lex= &session->lex->select_lex;
98
90
bool need_start_waiting= false;
100
is_engine_set= not createTableMessage().engine().name().empty();
102
92
if (is_engine_set)
104
create_info().db_type=
105
plugin::StorageEngine::findByName(*getSession(), createTableMessage().engine().name());
95
plugin::StorageEngine::findByName(*session, create_table_message.engine().name());
107
if (create_info().db_type == NULL)
97
if (create_info.db_type == NULL)
109
my_error(createTableMessage().engine().name(), ER_UNKNOWN_STORAGE_ENGINE, MYF(0));
99
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0),
100
create_table_message.engine().name().c_str());
141
136
if (not validateCreateTableOption())
144
if (getSession()->inTransaction())
146
my_error(ER_TRANSACTIONAL_DDL_NOT_SUPPORTED, MYF(0));
139
/* ALTER TABLE ends previous transaction */
140
if (not session->endActiveTransaction())
150
if (not (need_start_waiting= not getSession()->wait_if_global_read_lock(0, 1)))
143
if (not (need_start_waiting= not session->wait_if_global_read_lock(0, 1)))
154
147
if (original_table_message->type() == message::Table::STANDARD )
156
identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName());
157
identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
158
getSession()->getLex()->name.str ? getSession()->getLex()->name.str : first_table->getTableName());
149
TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName());
150
TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
151
session->lex->name.str ? session->lex->name.str : first_table->getTableName());
160
res= alter_table(getSession(),
153
res= alter_table(session,
164
157
*original_table_message,
165
createTableMessage(),
158
create_table_message,
168
161
select_lex->order_list.elements,
169
162
(Order *) select_lex->order_list.first,
170
getSession()->getLex()->ignore);
163
session->lex->ignore);
174
identifier::Table catch22(first_table->getSchemaName(), first_table->getTableName());
175
Table *table= getSession()->find_temporary_table(catch22);
167
TableIdentifier catch22(first_table->getSchemaName(), first_table->getTableName());
168
Table *table= session->find_temporary_table(catch22);
178
identifier::Table identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
179
identifier::Table new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
180
getSession()->getLex()->name.str ? getSession()->getLex()->name.str : first_table->getTableName(),
181
table->getMutableShare()->getPath());
171
TableIdentifier identifier(first_table->getSchemaName(), first_table->getTableName(), table->getMutableShare()->getPath());
172
TableIdentifier new_identifier(select_lex->db ? select_lex->db : first_table->getSchemaName(),
173
session->lex->name.str ? session->lex->name.str : first_table->getTableName(),
174
table->getMutableShare()->getPath());
183
res= alter_table(getSession(),
176
res= alter_table(session,
187
180
*original_table_message,
188
createTableMessage(),
181
create_table_message,
191
184
select_lex->order_list.elements,
192
185
(Order *) select_lex->order_list.first,
193
getSession()->getLex()->ignore);
186
session->lex->ignore);
245
238
@retval false success
247
240
static bool prepare_alter_table(Session *session,
249
HA_CREATE_INFO *create_info,
250
const message::Table &original_proto,
251
message::Table &table_message,
252
AlterInfo *alter_info)
242
HA_CREATE_INFO *create_info,
243
const message::Table &original_proto,
244
message::Table &table_message,
245
AlterInfo *alter_info)
254
247
/* New column definitions are added here */
255
248
List<CreateField> new_create_list;
256
249
/* New key definitions are added here */
257
250
List<Key> new_key_list;
258
List<AlterDrop>::iterator drop_it(alter_info->drop_list.begin());
259
List<CreateField>::iterator def_it(alter_info->create_list.begin());
260
List<AlterColumn>::iterator alter_it(alter_info->alter_list.begin());
261
List<Key>::iterator key_it(alter_info->key_list.begin());
262
List<CreateField>::iterator find_it(new_create_list.begin());
263
List<CreateField>::iterator field_it(new_create_list.begin());
251
List_iterator<AlterDrop> drop_it(alter_info->drop_list);
252
List_iterator<CreateField> def_it(alter_info->create_list);
253
List_iterator<AlterColumn> alter_it(alter_info->alter_list);
254
List_iterator<Key> key_it(alter_info->key_list);
255
List_iterator<CreateField> find_it(new_create_list);
256
List_iterator<CreateField> field_it(new_create_list);
264
257
List<Key_part_spec> key_parts;
265
258
uint32_t used_fields= create_info->used_fields;
266
259
KeyInfo *key_info= table->key_info;
723
700
We set this flag so that ha_innobase::open and ::external_lock() do
724
701
not complain when we lock the table
726
session->setDoingTablespaceOperation(true);
727
if (not (table= session->openTableLock(table_list, TL_WRITE)))
703
session->tablespace_op= true;
704
if (!(table= session->openTableLock(table_list, TL_WRITE)))
729
session->setDoingTablespaceOperation(false);
706
session->tablespace_op= false;
735
error= table->cursor->ha_discard_or_import_tablespace(discard);
737
session->set_proc_info("end");
742
/* The ALTER Table is always in its own transaction */
743
error= transaction_services.autocommitOrRollback(*session, false);
744
if (not session->endActiveTransaction())
750
write_bin_log(session, *session->getQueryString());
754
(void) transaction_services.autocommitOrRollback(*session, error);
755
session->setDoingTablespaceOperation(false);
710
error= table->cursor->ha_discard_or_import_tablespace(discard);
712
session->set_proc_info("end");
717
/* The ALTER Table is always in its own transaction */
718
error= transaction_services.autocommitOrRollback(session, false);
719
if (not session->endActiveTransaction())
725
write_bin_log(session, *session->getQueryString());
728
(void) transaction_services.autocommitOrRollback(session, error);
729
session->tablespace_op=false;
996
974
while the fact that the table is still open gives us protection
997
975
from concurrent DDL statements.
1000
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* DDL wait for/blocker */
1001
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
977
table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
978
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
979
table::Cache::singleton().mutex().unlock();
1003
980
error= table->cursor->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1005
981
/* COND_refresh will be signaled in close_thread_tables() */
1010
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* DDL wait for/blocker */
1011
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
1013
error= table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
984
table::Cache::singleton().mutex().lock(); /* DDL wait for/blocker */
985
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
986
table::Cache::singleton().mutex().unlock();
987
error=table->cursor->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
1015
988
/* COND_refresh will be signaled in close_thread_tables() */
1019
996
if (error == HA_ERR_WRONG_COMMAND)
1022
999
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1023
1000
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1024
1001
table->getAlias());
1027
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* Lock to remove all instances of table from table cache before ALTER */
1004
table::Cache::singleton().mutex().lock(); /* Lock to remove all instances of table from table cache before ALTER */
1029
1006
Unlike to the above case close_cached_table() below will remove ALL
1030
1007
instances of Table from table cache (it will also remove table lock
1261
1237
delete new_table;
1265
boost::mutex::scoped_lock scopedLock(table::Cache::singleton().mutex()); /* ALTER TABLE */
1267
Data is copied. Now we:
1268
1) Wait until all other threads close old version of table.
1269
2) Close instances of table open by this thread and replace them
1270
with exclusive name-locks.
1271
3) Rename the old table to a temp name, rename the new one to the
1273
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
1274
we reopen new version of table.
1275
5) Write statement to the binary log.
1276
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
1277
remove name-locks from list of open tables and table cache.
1278
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
1279
call to remove name-locks from table cache and list of open table.
1282
session->set_proc_info("rename result table");
1284
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1286
my_casedn_str(files_charset_info, old_name);
1288
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
1289
session->close_data_files_and_morph_locks(original_table_identifier);
1294
This leads to the storage engine (SE) not being notified for renames in
1295
rename_table(), because we just juggle with the FRM and nothing
1296
more. If we have an intermediate table, then we notify the SE that
1297
it should become the actual table. Later, we will recycle the old table.
1298
However, in case of ALTER Table RENAME there might be no intermediate
1299
table. This is when the old and new tables are compatible, according to
1300
compare_table(). Then, we need one additional call to
1302
identifier::Table original_table_to_drop(original_table_identifier.getSchemaName(),
1303
old_name, create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1304
message::Table::TEMPORARY);
1306
drizzled::error_t rename_error= EE_OK;
1307
if (rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
1240
table::Cache::singleton().mutex().lock(); /* ALTER TABLE */
1243
Data is copied. Now we:
1244
1) Wait until all other threads close old version of table.
1245
2) Close instances of table open by this thread and replace them
1246
with exclusive name-locks.
1247
3) Rename the old table to a temp name, rename the new one to the
1249
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
1250
we reopen new version of table.
1251
5) Write statement to the binary log.
1252
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
1253
remove name-locks from list of open tables and table cache.
1254
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
1255
call to remove name-locks from table cache and list of open table.
1258
session->set_proc_info("rename result table");
1260
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
1262
my_casedn_str(files_charset_info, old_name);
1264
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
1265
session->close_data_files_and_morph_locks(original_table_identifier);
1270
This leads to the storage engine (SE) not being notified for renames in
1271
rename_table(), because we just juggle with the FRM and nothing
1272
more. If we have an intermediate table, then we notify the SE that
1273
it should become the actual table. Later, we will recycle the old table.
1274
However, in case of ALTER Table RENAME there might be no intermediate
1275
table. This is when the old and new tables are compatible, according to
1276
compare_table(). Then, we need one additional call to
1278
TableIdentifier original_table_to_drop(original_table_identifier.getSchemaName(),
1279
old_name, create_proto.type() != message::Table::TEMPORARY ? message::Table::INTERNAL :
1280
message::Table::TEMPORARY);
1282
if (rename_table(*session, original_engine, original_table_identifier, original_table_to_drop))
1285
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1289
if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1309
error= ER_ERROR_ON_RENAME;
1291
/* Try to get everything back. */
1294
plugin::StorageEngine::dropTable(*session, new_table_identifier);
1310
1296
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1298
rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1314
if (rename_table(*session, new_engine, new_table_as_temporary, new_table_identifier) != 0)
1316
/* Try to get everything back. */
1317
rename_error= ER_ERROR_ON_RENAME;
1319
plugin::StorageEngine::dropTable(*session, new_table_identifier);
1321
plugin::StorageEngine::dropTable(*session, new_table_as_temporary);
1323
rename_table(*session, original_engine, original_table_to_drop, original_table_identifier);
1327
plugin::StorageEngine::dropTable(*session, original_table_to_drop);
1334
An error happened while we were holding exclusive name-lock on table
1335
being altered. To be safe under LOCK TABLES we should remove placeholders
1336
from list of open tables list and table cache.
1338
session->unlink_open_table(table);
1302
plugin::StorageEngine::dropTable(*session, original_table_to_drop);
1309
An error happened while we were holding exclusive name-lock on table
1310
being altered. To be safe under LOCK TABLES we should remove placeholders
1311
from list of open tables list and table cache.
1313
session->unlink_open_table(table);
1314
table::Cache::singleton().mutex().unlock();
1319
table::Cache::singleton().mutex().unlock();
1344
1321
session->set_proc_info("end");
1506
1484
found_count=delete_count=0;
1512
if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
1488
if (to->getShare()->hasPrimaryKey() && to->cursor->primary_key_is_clustered())
1490
char warn_buff[DRIZZLE_ERRMSG_SIZE];
1491
snprintf(warn_buff, sizeof(warn_buff),
1492
_("order_st BY ignored because there is a user-defined clustered "
1493
"index in the table '%-.192s'"),
1494
from->getMutableShare()->getTableName());
1495
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1500
FileSort filesort(*session);
1501
from->sort.io_cache= new internal::IO_CACHE;
1503
memset(&tables, 0, sizeof(tables));
1505
tables.setTableName(const_cast<char *>(from->getMutableShare()->getTableName()));
1506
tables.alias= const_cast<char *>(tables.getTableName());
1507
tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
1510
if (session->lex->select_lex.setup_ref_array(session, order_num) ||
1511
setup_order(session, session->lex->select_lex.ref_pointer_array,
1512
&tables, fields, all_fields, order) ||
1513
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1514
(from->sort.found_records= filesort.run(from, sortorder, length,
1515
(optimizer::SqlSelect *) 0, HA_POS_ERROR,
1516
1, examined_rows)) == HA_POS_ERROR)
1514
char warn_buff[DRIZZLE_ERRMSG_SIZE];
1515
snprintf(warn_buff, sizeof(warn_buff),
1516
_("order_st BY ignored because there is a user-defined clustered "
1517
"index in the table '%-.192s'"),
1518
from->getMutableShare()->getTableName());
1519
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1523
/* Tell handler that we have values for all columns in the to table */
1524
to->use_all_columns();
1525
info.init_read_record(session, from, (optimizer::SqlSelect *) 0, 1, true);
1527
to->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1528
session->row_count= 0;
1529
to->restoreRecordAsDefault(); // Create empty record
1530
while (!(error=info.read_record(&info)))
1532
if (session->getKilled())
1534
session->send_kill_message();
1538
session->row_count++;
1539
/* Return error if source table isn't empty. */
1540
if (error_if_not_empty)
1545
if (to->next_number_field)
1547
if (auto_increment_field_copied)
1548
to->auto_increment_field_not_null= true;
1550
to->next_number_field->reset();
1553
for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
1555
if (not copy->to_field->hasDefault() and copy->from_null_ptr and *copy->from_null_ptr & copy->from_bit)
1524
FileSort filesort(*session);
1525
from->sort.io_cache= new internal::IO_CACHE;
1528
tables.setTableName(from->getMutableShare()->getTableName());
1529
tables.alias= tables.getTableName();
1530
tables.setSchemaName(const_cast<char *>(from->getMutableShare()->getSchemaName()));
1557
copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
1558
ER_WARN_DATA_TRUNCATED, 1);
1559
copy->to_field->reset();
1533
if (session->getLex()->select_lex.setup_ref_array(session, order_num) ||
1534
setup_order(session, session->getLex()->select_lex.ref_pointer_array,
1535
&tables, fields, all_fields, order) ||
1536
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
1537
(from->sort.found_records= filesort.run(from, sortorder, length,
1538
(optimizer::SqlSelect *) 0, HA_POS_ERROR,
1539
1, examined_rows)) == HA_POS_ERROR)
1564
copy_ptr->do_copy(copy_ptr);
1546
/* Tell handler that we have values for all columns in the to table */
1547
to->use_all_columns();
1549
error= info.init_read_record(session, from, (optimizer::SqlSelect *) 0, 1, true);
1552
to->print_error(errno, MYF(0));
1559
to->cursor->extra(HA_EXTRA_IGNORE_DUP_KEY);
1562
session->row_count= 0;
1563
to->restoreRecordAsDefault(); // Create empty record
1564
while (not (error=info.read_record(&info)))
1566
if (session->getKilled())
1568
session->send_kill_message();
1572
session->row_count++;
1573
/* Return error if source table isn't empty. */
1574
if (error_if_not_empty)
1579
if (to->next_number_field)
1581
if (auto_increment_field_copied)
1582
to->auto_increment_field_not_null= true;
1584
to->next_number_field->reset();
1587
for (CopyField *copy_ptr= copy; copy_ptr != copy_end ; copy_ptr++)
1589
if (not copy->to_field->hasDefault() and copy->from_null_ptr and *copy->from_null_ptr & copy->from_bit)
1591
copy->to_field->set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN,
1592
ER_WARN_DATA_TRUNCATED, 1);
1593
copy->to_field->reset();
1598
copy_ptr->do_copy(copy_ptr);
1606
prev_insert_id= to->cursor->next_insert_id;
1607
error= to->cursor->insertRecord(to->record[0]);
1608
to->auto_increment_field_not_null= false;
1572
prev_insert_id= to->cursor->next_insert_id;
1573
error= to->cursor->insertRecord(to->record[0]);
1574
to->auto_increment_field_not_null= false;
1578
if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1612
if (!ignore || to->cursor->is_fatal_error(error, HA_CHECK_DUP))
1614
to->print_error(error, MYF(0));
1617
to->cursor->restore_auto_increment(prev_insert_id);
1580
to->print_error(error, MYF(0));
1583
to->cursor->restore_auto_increment(prev_insert_id);
1626
info.end_read_record();
1627
from->free_io_cache();
1628
delete [] copy; // This is never 0
1630
if (to->cursor->ha_end_bulk_insert() && error <= 0)
1632
to->print_error(errno, MYF(0));
1635
to->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1638
Ensure that the new table is saved properly to disk so that we
1641
if (transaction_services.autocommitOrRollback(*session, false))
1644
if (not session->endActiveTransaction())
1649
session->setAbortOnWarning(false);
1592
info.end_read_record();
1593
from->free_io_cache();
1594
delete [] copy; // This is never 0
1596
if (to->cursor->ha_end_bulk_insert() && error <= 0)
1598
to->print_error(errno, MYF(0));
1601
to->cursor->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
1604
Ensure that the new table is saved properly to disk so that we
1607
if (transaction_services.autocommitOrRollback(session, false))
1609
if (! session->endActiveTransaction())
1613
session->abort_on_warning= 0;
1650
1614
from->free_io_cache();
1651
1615
*copied= found_count;
1652
1616
*deleted=delete_count;
1653
1617
to->cursor->ha_release_auto_increment();
1655
if (to->cursor->ha_external_lock(session, F_UNLCK))
1618
if (to->cursor->ha_external_lock(session,F_UNLCK))
1660
1621
return(error > 0 ? -1 : 0);
1663
static Table *open_alter_table(Session *session, Table *table, identifier::Table &identifier)
1625
create_temporary_table(Session *session,
1626
TableIdentifier &identifier,
1627
HA_CREATE_INFO *create_info,
1628
message::Table &create_proto,
1629
AlterInfo *alter_info)
1634
Create a table with a temporary name.
1635
We don't log the statement, it will be logged later.
1637
create_proto.set_name(identifier.getTableName());
1639
create_proto.mutable_engine()->set_name(create_info->db_type->getName());
1641
error= create_table(session,
1643
create_info, create_proto, alter_info, true, 0, false);
1648
static Table *open_alter_table(Session *session, Table *table, TableIdentifier &identifier)
1665
1650
Table *new_table;