1296
1691
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
1297
1692
MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
1301
1696
if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
1303
1698
if (sql_field->sql_type == DRIZZLE_TYPE_BLOB)
1305
1700
/* The user has given a length to the blob column */
1701
sql_field->sql_type= get_blob_type_from_length(sql_field->length);
1306
1702
sql_field->pack_length= calc_pack_length(sql_field->sql_type, 0);
1308
1704
sql_field->length= 0;
1313
static bool locked_create_event(Session *session,
1314
const identifier::Table &identifier,
1315
HA_CREATE_INFO *create_info,
1316
message::Table &table_proto,
1317
AlterInfo *alter_info,
1318
bool is_if_not_exists,
1319
bool internal_tmp_table,
1322
KeyInfo *key_info_buffer)
1711
Preparation of Create_field for SP function return values.
1712
Based on code used in the inner loop of mysql_prepare_create_table()
1716
sp_prepare_create_field()
1718
sql_field Field to prepare
1721
Prepares the field structures for field creation.
1725
void sp_prepare_create_field(THD *thd, Create_field *sql_field)
1329
@note if we are building a temp table we need to check to see if a temp table
1330
already exists, otherwise we just need to find out if a normal table exists (aka it is fine
1331
to create a table under a temporary table.
1334
plugin::StorageEngine::doesTableExist(*session, identifier,
1335
identifier.getType() != message::Table::STANDARD );
1339
if (is_if_not_exists)
1342
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1343
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1344
identifier.getTableName().c_str());
1345
create_info->table_existed= 1; // Mark that table existed
1349
my_error(ER_TABLE_EXISTS_ERROR, identifier);
1354
if (identifier.getType() == message::Table::STANDARD) // We have a real table
1357
We don't assert here, but check the result, because the table could be
1358
in the table definition cache and in the same time the .frm could be
1359
missing from the disk, in case of manual intervention which deletes
1360
the .frm cursor. The user has to use FLUSH TABLES; to clear the cache.
1361
Then she could create the table. This case is pretty obscure and
1362
therefore we don't introduce a new error message only for it.
1365
@todo improve this error condition.
1367
if (definition::Cache::singleton().find(identifier.getKey()))
1369
my_error(ER_TABLE_EXISTS_ERROR, identifier);
1376
session->set_proc_info("creating table");
1377
create_info->table_existed= 0; // Mark that table is created
1379
create_info->table_options= db_options;
1381
if (not rea_create_table(session, identifier,
1383
create_info, alter_info->create_list,
1384
key_count, key_info_buffer))
1389
if (identifier.getType() == message::Table::TEMPORARY)
1391
/* Open table and put in temporary table list */
1392
if (not (session->open_temporary_table(identifier)))
1394
(void) session->rm_temporary_table(identifier);
1400
We keep this behind the lock to make sure ordering is correct for a table.
1401
This is a very unlikely problem where before we would write out to the
1402
trans log, someone would do a delete/create operation.
1405
if (table_proto.type() == message::Table::STANDARD && not internal_tmp_table)
1407
TransactionServices &transaction_services= TransactionServices::singleton();
1408
transaction_services.createTable(*session, table_proto);
1727
if (sql_field->sql_type == DRIZZLE_TYPE_SET ||
1728
sql_field->sql_type == DRIZZLE_TYPE_ENUM)
1730
uint32_t field_length, dummy;
1731
if (sql_field->sql_type == DRIZZLE_TYPE_SET)
1733
calculate_interval_lengths(sql_field->charset,
1734
sql_field->interval, &dummy,
1736
sql_field->length= field_length +
1737
(sql_field->interval->count - 1);
1739
else /* DRIZZLE_TYPE_ENUM */
1741
calculate_interval_lengths(sql_field->charset,
1742
sql_field->interval,
1743
&field_length, &dummy);
1744
sql_field->length= field_length;
1746
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
1749
sql_field->create_length_to_internal_length();
1750
assert(sql_field->def == 0);
1751
/* Can't go wrong as sql_field->def is not defined */
1752
(void) prepare_blob_field(thd, sql_field);
1416
Ignore the name of this function... it locks :(
1421
create_table_no_lock()
1422
session Thread object
1760
mysql_create_table_no_lock()
1424
1763
table_name Table name
1425
1764
create_info Create information (like MAX_ROWS)
1426
1765
fields List of fields to create
1427
1766
keys List of keys to create
1428
1767
internal_tmp_table Set to 1 if this is an internal temporary table
1433
1772
If one creates a temporary table, this is automatically opened
1435
1774
Note that this function assumes that caller already have taken
1436
1775
name-lock on table being created or used some other way to ensure
1437
that concurrent operations won't intervene. create_table()
1776
that concurrent operations won't intervene. mysql_create_table()
1438
1777
is a wrapper that can be used for this.
1779
no_log is needed for the case of CREATE ... SELECT,
1780
as the logging will be done later in sql_insert.cc
1781
select_field_count is also used for CREATE ... SELECT,
1782
and must be zero for standard create of table.
1445
bool create_table_no_lock(Session *session,
1446
const identifier::Table &identifier,
1789
bool mysql_create_table_no_lock(THD *thd,
1790
const char *db, const char *table_name,
1447
1791
HA_CREATE_INFO *create_info,
1448
message::Table &table_proto,
1449
AlterInfo *alter_info,
1792
Alter_info *alter_info,
1450
1793
bool internal_tmp_table,
1451
uint32_t select_field_count,
1452
bool is_if_not_exists)
1794
uint select_field_count)
1796
char path[FN_REFLEN];
1454
1799
uint db_options, key_count;
1455
KeyInfo *key_info_buffer;
1800
KEY *key_info_buffer;
1456
1802
bool error= true;
1458
1803
/* Check for duplicate fields and check type of table to create */
1459
if (not alter_info->create_list.elements)
1804
if (!alter_info->create_list.elements)
1461
1806
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1465
assert(identifier.getTableName() == table_proto.name());
1810
if (check_engine(thd, table_name, create_info))
1466
1812
db_options= create_info->table_options;
1468
set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1470
/* Build a Table object to pass down to the engine, and the do the actual create. */
1471
if (not prepare_create_table(session, create_info, table_proto, alter_info,
1474
&key_info_buffer, &key_count,
1475
select_field_count))
1477
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1478
error= locked_create_event(session,
1485
db_options, key_count,
1489
session->set_proc_info("After create");
1813
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1814
db_options|=HA_OPTION_PACK_RECORD;
1815
alias= table_case_name(create_info, table_name);
1816
if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
1817
create_info->db_type)))
1819
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
1823
set_table_default_charset(thd, create_info, (char*) db);
1825
if (mysql_prepare_create_table(thd, create_info, alter_info,
1828
&key_info_buffer, &key_count,
1829
select_field_count))
1832
/* Check if table exists */
1833
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1835
path_length= build_tmptable_filename(thd, path, sizeof(path));
1836
create_info->table_options|=HA_CREATE_DELAY_KEY_WRITE;
1841
/* check if the table name contains FN_DEVCHAR when defined */
1842
if (strchr(alias, FN_DEVCHAR))
1844
my_error(ER_WRONG_TABLE_NAME, MYF(0), alias);
1848
path_length= build_table_filename(path, sizeof(path), db, alias, reg_ext,
1849
internal_tmp_table ? FN_IS_TMP : 0);
1852
/* Check if table already exists */
1853
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1854
find_temporary_table(thd, db, table_name))
1856
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1858
create_info->table_existed= 1; // Mark that table existed
1859
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1860
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1865
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
1869
VOID(pthread_mutex_lock(&LOCK_open));
1870
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1872
if (!access(path,F_OK))
1874
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1876
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1877
goto unlock_and_end;
1880
We don't assert here, but check the result, because the table could be
1881
in the table definition cache and in the same time the .frm could be
1882
missing from the disk, in case of manual intervention which deletes
1883
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1884
Then she could create the table. This case is pretty obscure and
1885
therefore we don't introduce a new error message only for it.
1887
if (get_cached_table_share(db, alias))
1889
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1890
goto unlock_and_end;
1895
Check that table with given name does not already
1896
exist in any storage engine. In such a case it should
1897
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1898
unless user specified CREATE TABLE IF EXISTS
1899
The LOCK_open mutex has been locked to make sure no
1900
one else is attempting to discover the table. Since
1901
it's not on disk as a frm file, no one could be using it!
1903
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1905
bool create_if_not_exists =
1906
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1907
int retcode = ha_table_exists_in_engine(thd, db, table_name);
1910
case HA_ERR_NO_SUCH_TABLE:
1911
/* Normal case, no table exists. we can go and create it */
1913
case HA_ERR_TABLE_EXIST:
1915
if (create_if_not_exists)
1917
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1918
goto unlock_and_end;
1921
my_error(retcode, MYF(0),table_name);
1922
goto unlock_and_end;
1926
thd_proc_info(thd, "creating table");
1927
create_info->table_existed= 0; // Mark that table is created
1929
#ifdef HAVE_READLINK
1930
if (test_if_data_home_dir(create_info->data_file_name))
1932
my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
1933
goto unlock_and_end;
1935
if (test_if_data_home_dir(create_info->index_file_name))
1937
my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
1938
goto unlock_and_end;
1942
#endif /* HAVE_READLINK */
1944
if (create_info->data_file_name)
1945
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
1946
"DATA DIRECTORY option ignored");
1947
if (create_info->index_file_name)
1948
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, 0,
1949
"INDEX DIRECTORY option ignored");
1950
create_info->data_file_name= create_info->index_file_name= 0;
1952
create_info->table_options=db_options;
1954
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
1955
if (rea_create_table(thd, path, db, table_name,
1956
create_info, alter_info->create_list,
1957
key_count, key_info_buffer, file))
1958
goto unlock_and_end;
1960
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1962
/* Open table and put in temporary table list */
1963
if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
1965
(void) rm_temporary_table(create_info->db_type, path, false);
1966
goto unlock_and_end;
1968
thd->thread_specific_used= true;
1972
Don't write statement if:
1973
- It is an internal temporary table,
1974
- Row-based logging is used and it we are creating a temporary table, or
1975
- The binary log is not open.
1976
Otherwise, the statement shall be binlogged.
1978
if (!internal_tmp_table &&
1979
(!thd->current_stmt_binlog_row_based ||
1980
(thd->current_stmt_binlog_row_based &&
1981
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1982
write_bin_log(thd, true, thd->query, thd->query_length);
1985
VOID(pthread_mutex_unlock(&LOCK_open));
1988
thd_proc_info(thd, "After create");
1994
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
1995
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1997
create_info->table_existed= 1; // Mark that table existed
1998
goto unlock_and_end;
1495
@note the following two methods implement create [temporary] table.
2003
Database locking aware wrapper for mysql_create_table_no_lock(),
1497
static bool drizzle_create_table(Session *session,
1498
const identifier::Table &identifier,
1499
HA_CREATE_INFO *create_info,
1500
message::Table &table_proto,
1501
AlterInfo *alter_info,
1502
bool internal_tmp_table,
1503
uint32_t select_field_count,
1504
bool is_if_not_exists)
2006
bool mysql_create_table(THD *thd, const char *db, const char *table_name,
2007
HA_CREATE_INFO *create_info,
2008
Alter_info *alter_info,
2009
bool internal_tmp_table,
2010
uint select_field_count)
1506
Table *name_lock= NULL;
2012
TABLE *name_lock= 0;
1509
if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1513
else if (name_lock == NULL)
1515
if (is_if_not_exists)
1517
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1518
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1519
identifier.getTableName().c_str());
1520
create_info->table_existed= 1;
1525
my_error(ER_TABLE_EXISTS_ERROR, identifier);
2015
/* Wait for any database locks */
2016
pthread_mutex_lock(&LOCK_lock_db);
2017
while (!thd->killed &&
2018
hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
2020
wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
2021
pthread_mutex_lock(&LOCK_lock_db);
2026
pthread_mutex_unlock(&LOCK_lock_db);
2030
pthread_mutex_unlock(&LOCK_lock_db);
2032
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
2034
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
1531
result= create_table_no_lock(session,
2041
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
2043
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
2044
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
2046
create_info->table_existed= 1;
2051
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
2058
result= mysql_create_table_no_lock(thd, db, table_name, create_info,
2061
select_field_count);
1543
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
1544
session->unlink_open_table(name_lock);
2066
pthread_mutex_lock(&LOCK_open);
2067
unlink_open_table(thd, name_lock, false);
2068
pthread_mutex_unlock(&LOCK_open);
2070
pthread_mutex_lock(&LOCK_lock_db);
2071
if (!--creating_table && creating_database)
2072
pthread_cond_signal(&COND_refresh);
2073
pthread_mutex_unlock(&LOCK_lock_db);
1547
2074
return(result);
1552
Database locking aware wrapper for create_table_no_lock(),
1554
bool create_table(Session *session,
1555
const identifier::Table &identifier,
1556
HA_CREATE_INFO *create_info,
1557
message::Table &table_proto,
1558
AlterInfo *alter_info,
1559
bool internal_tmp_table,
1560
uint32_t select_field_count,
1561
bool is_if_not_exists)
1563
if (identifier.isTmp())
1565
return create_table_no_lock(session,
1575
return drizzle_create_table(session,
1587
2079
** Give the key name after the first field with an optional '_#' after
1591
check_if_keyname_exists(const char *name, KeyInfo *start, KeyInfo *end)
2083
check_if_keyname_exists(const char *name, KEY *start, KEY *end)
1593
for (KeyInfo *key=start ; key != end ; key++)
2085
for (KEY *key=start ; key != end ; key++)
1594
2086
if (!my_strcasecmp(system_charset_info,name,key->name))
2103
bool create_like_table(Session* session,
2104
identifier::Table::const_reference destination_identifier,
2105
identifier::Table::const_reference source_identifier,
2106
message::Table &create_table_proto,
2107
bool is_if_not_exists,
2992
bool mysql_create_like_table(THD* thd, TABLE_LIST* table, TABLE_LIST* src_table,
2993
HA_CREATE_INFO *create_info)
2995
TABLE *name_lock= 0;
2996
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
2997
uint dst_path_length;
2998
char *db= table->db;
2999
char *table_name= table->table_name;
2110
3001
bool res= true;
2111
bool table_exists= false;
3005
/* CREATE TABLE ... LIKE is not allowed for views. */
3006
src_table->required_type= FRMTYPE_TABLE;
3009
By opening source table we guarantee that it exists and no concurrent
3010
DDL operation will mess with it. Later we also take an exclusive
3011
name-lock on target table name, which makes copying of .frm file,
3012
call to ha_create_table() and binlogging atomic against concurrent DML
3013
and DDL operations on target table. Thus by holding both these "locks"
3014
we ensure that our statement is properly isolated from all concurrent
3015
operations which matter.
3017
if (open_tables(thd, &src_table, ¬_used, 0))
3020
strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS);
2114
3023
Check that destination tables does not exist. Note that its name
2115
3024
was already checked when it was added to the table list.
2117
For temporary tables we don't aim to grab locks.
2119
if (destination_identifier.isTmp())
2121
if (session->find_temporary_table(destination_identifier))
2127
bool was_created= create_table_wrapper(*session,
2129
destination_identifier,
2132
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2134
(void) session->rm_temporary_table(destination_identifier, true);
2136
else if (not session->open_temporary_table(destination_identifier))
2138
// We created, but we can't open... also, a hack.
2139
(void) session->rm_temporary_table(destination_identifier, true);
2147
else // Standard table which will require locks.
2149
Table *name_lock= 0;
2151
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2155
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2156
session->unlink_open_table(name_lock);
2166
else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2170
else // Otherwise we create the table
2174
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2175
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2176
source_identifier, is_engine_set);
2179
// So we blew the creation of the table, and we scramble to clean up
2180
// anything that might have been created (read... it is a hack)
2181
if (not was_created)
2183
plugin::StorageEngine::dropTable(*session, destination_identifier);
3026
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
3028
if (find_temporary_table(thd, db, table_name))
3030
dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
3031
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
3035
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
3039
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
3040
db, table_name, reg_ext, 0);
3041
if (!access(dst_path, F_OK))
3046
Create a new table by copying from source table
3048
Altough exclusive name-lock on target table protects us from concurrent
3049
DML and DDL operations on it we still want to wrap .FRM creation and call
3050
to ha_create_table() in critical section protected by LOCK_open in order
3051
to provide minimal atomicity against operations which disregard name-locks,
3052
like I_S implementation, for example. This is a temporary and should not
3053
be copied. Instead we should fix our code to always honor name-locks.
3055
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
3056
during the call to ha_create_table(). See bug #28614 for more info.
3058
VOID(pthread_mutex_lock(&LOCK_open));
3059
if (src_table->schema_table)
3061
if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
3063
VOID(pthread_mutex_unlock(&LOCK_open));
3067
else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
3069
if (my_errno == ENOENT)
3070
my_error(ER_BAD_DB_ERROR,MYF(0),db);
3072
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
3073
VOID(pthread_mutex_unlock(&LOCK_open));
3078
As mysql_truncate don't work on a new table at this stage of
3079
creation, instead create the table directly (for both normal
3080
and temporary tables).
3082
dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
3083
if (thd->variables.keep_files_on_create)
3084
create_info->options|= HA_CREATE_KEEP_FILES;
3085
err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
3086
VOID(pthread_mutex_unlock(&LOCK_open));
3088
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
3090
if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
3093
(void) rm_temporary_table(create_info->db_type,
3094
dst_path, false); /* purecov: inspected */
3095
goto err; /* purecov: inspected */
3100
(void) quick_rm_table(create_info->db_type, db,
3101
table_name, 0); /* purecov: inspected */
3102
goto err; /* purecov: inspected */
3106
We have to write the query before we unlock the tables.
3108
if (thd->current_stmt_binlog_row_based)
3111
Since temporary tables are not replicated under row-based
3112
replication, CREATE TABLE ... LIKE ... needs special
3113
treatement. We have four cases to consider, according to the
3114
following decision table:
3116
==== ========= ========= ==============================
3117
Case Target Source Write to binary log
3118
==== ========= ========= ==============================
3119
1 normal normal Original statement
3120
2 normal temporary Generated statement
3121
3 temporary normal Nothing
3122
4 temporary temporary Nothing
3123
==== ========= ========= ==============================
3125
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
3127
if (src_table->table->s->tmp_table) // Case 2
3130
String query(buf, sizeof(buf), system_charset_info);
3131
query.length(0); // Have to zero it since constructor doesn't
3135
Here we open the destination table, on which we already have
3136
name-lock. This is needed for store_create_info() to work.
3137
The table will be closed by unlink_open_table() at the end
3140
table->table= name_lock;
3141
VOID(pthread_mutex_lock(&LOCK_open));
3142
if (reopen_name_locked_table(thd, table, false))
3144
VOID(pthread_mutex_unlock(&LOCK_open));
3147
VOID(pthread_mutex_unlock(&LOCK_open));
3149
int result= store_create_info(thd, table, &query,
3152
assert(result == 0); // store_create_info() always return 0
3153
write_bin_log(thd, true, query.ptr(), query.length());
3156
write_bin_log(thd, true, thd->query, thd->query_length);
3159
Case 3 and 4 does nothing under RBR
3163
write_bin_log(thd, true, thd->query, thd->query_length);
3169
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
3171
char warn_buff[MYSQL_ERRMSG_SIZE];
3172
snprintf(warn_buff, sizeof(warn_buff),
3173
ER(ER_TABLE_EXISTS_ERROR), table_name);
3174
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
3175
ER_TABLE_EXISTS_ERROR,warn_buff);
3179
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
3184
pthread_mutex_lock(&LOCK_open);
3185
unlink_open_table(thd, name_lock, false);
3186
pthread_mutex_unlock(&LOCK_open);
3192
bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
3194
thr_lock_type lock_type = TL_READ_NO_INSERT;
3196
return(mysql_admin_table(thd, tables, check_opt,
3197
"analyze", lock_type, 1, 0, 0, 0,
3198
&handler::ha_analyze));
3202
bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
3204
thr_lock_type lock_type = TL_READ_NO_INSERT;
3206
return(mysql_admin_table(thd, tables, check_opt,
3208
0, 0, HA_OPEN_FOR_REPAIR, 0,
3209
&handler::ha_check));
3213
/* table_list should contain just one table */
3215
mysql_discard_or_import_tablespace(THD *thd,
3216
TABLE_LIST *table_list,
3217
enum tablespace_op_type tablespace_op)
3224
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
3228
thd_proc_info(thd, "discard_or_import_tablespace");
3230
discard= test(tablespace_op == DISCARD_TABLESPACE);
3233
We set this flag so that ha_innobase::open and ::external_lock() do
3234
not complain when we lock the table
3236
thd->tablespace_op= true;
3237
if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
3239
thd->tablespace_op=false;
3243
error= table->file->ha_discard_or_import_tablespace(discard);
3245
thd_proc_info(thd, "end");
3250
/* The ALTER TABLE is always in its own transaction */
3251
error = ha_autocommit_or_rollback(thd, 0);
3252
if (end_active_trans(thd))
3256
write_bin_log(thd, false, thd->query, thd->query_length);
3259
ha_autocommit_or_rollback(thd, error);
3260
thd->tablespace_op=false;
3268
table->file->print_error(error, MYF(0));
3274
Copy all changes detected by parser to the HA_ALTER_FLAGS
3277
void setup_ha_alter_flags(Alter_info *alter_info, HA_ALTER_FLAGS *alter_flags)
3279
uint flags= alter_info->flags;
3281
if (ALTER_ADD_COLUMN & flags)
3282
*alter_flags|= HA_ADD_COLUMN;
3283
if (ALTER_DROP_COLUMN & flags)
3284
*alter_flags|= HA_DROP_COLUMN;
3285
if (ALTER_RENAME & flags)
3286
*alter_flags|= HA_RENAME_TABLE;
3287
if (ALTER_CHANGE_COLUMN & flags)
3288
*alter_flags|= HA_CHANGE_COLUMN;
3289
if (ALTER_COLUMN_DEFAULT & flags)
3290
*alter_flags|= HA_COLUMN_DEFAULT_VALUE;
3291
if (ALTER_COLUMN_STORAGE & flags)
3292
*alter_flags|= HA_COLUMN_STORAGE;
3293
if (ALTER_COLUMN_FORMAT & flags)
3294
*alter_flags|= HA_COLUMN_FORMAT;
3295
if (ALTER_COLUMN_ORDER & flags)
3296
*alter_flags|= HA_ALTER_COLUMN_ORDER;
3297
if (ALTER_STORAGE & flags)
3298
*alter_flags|= HA_ALTER_STORAGE;
3299
if (ALTER_ROW_FORMAT & flags)
3300
*alter_flags|= HA_ALTER_ROW_FORMAT;
3301
if (ALTER_RECREATE & flags)
3302
*alter_flags|= HA_RECREATE;
3303
if (ALTER_FOREIGN_KEY & flags)
3304
*alter_flags|= HA_ALTER_FOREIGN_KEY;
3310
@param table The original table.
3311
@param alter_info Alter options, fields and keys for the new
3313
@param create_info Create options for the new table.
3314
@param order_num Number of order list elements.
3315
@param[out] ha_alter_flags Flags that indicate what will be changed
3316
@param[out] ha_alter_info Data structures needed for on-line alter
3317
@param[out] table_changes Information about particular change
3319
First argument 'table' contains information of the original
3320
table, which includes all corresponding parts that the new
3321
table has in arguments create_list, key_list and create_info.
3323
By comparing the changes between the original and new table
3324
we can determine how much it has changed after ALTER TABLE
3325
and whether we need to make a copy of the table, or just change
3328
Mark any changes detected in the ha_alter_flags.
3330
If there are no data changes, but index changes, 'index_drop_buffer'
3331
and/or 'index_add_buffer' are populated with offsets into
3332
table->key_info or key_info_buffer respectively for the indexes
3333
that need to be dropped and/or (re-)created.
3336
@retval false success
3341
compare_tables(THD *thd,
3343
Alter_info *alter_info,
3344
HA_CREATE_INFO *create_info,
3346
HA_ALTER_FLAGS *alter_flags,
3347
HA_ALTER_INFO *ha_alter_info,
3348
uint *table_changes)
3350
Field **f_ptr, *field;
3351
uint table_changes_local= 0;
3352
List_iterator_fast<Create_field> new_field_it(alter_info->create_list);
3353
Create_field *new_field;
3354
KEY_PART_INFO *key_part;
3357
Remember if the new definition has new VARCHAR column;
3358
create_info->varchar will be reset in mysql_prepare_create_table.
3360
bool varchar= create_info->varchar;
3364
Create a copy of alter_info.
3365
To compare the new and old table definitions, we need to "prepare"
3366
the new definition - transform it from parser output to a format
3367
that describes the final table layout (all column defaults are
3368
initialized, duplicate columns are removed). This is done by
3369
mysql_prepare_create_table. Unfortunately,
3370
mysql_prepare_create_table performs its transformations
3371
"in-place", that is, modifies the argument. Since we would
3372
like to keep compare_tables() idempotent (not altering any
3373
of the arguments) we create a copy of alter_info here and
3374
pass it to mysql_prepare_create_table, then use the result
3375
to evaluate possibility of fast ALTER TABLE, and then
3378
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
3379
THD *thd= table->in_use;
3380
uint db_options= 0; /* not used */
3381
/* Create the prepared information. */
3382
if (mysql_prepare_create_table(thd, create_info,
3384
(table->s->tmp_table != NO_TMP_TABLE),
3387
&ha_alter_info->key_info_buffer,
3388
&ha_alter_info->key_count,
3389
/* select_field_count */ 0))
3391
/* Allocate result buffers. */
3392
if (! (ha_alter_info->index_drop_buffer=
3393
(uint*) thd->alloc(sizeof(uint) * table->s->keys)) ||
3394
! (ha_alter_info->index_add_buffer=
3395
(uint*) thd->alloc(sizeof(uint) *
3396
tmp_alter_info.key_list.elements)))
3400
First we setup ha_alter_flags based on what was detected
3403
setup_ha_alter_flags(alter_info, alter_flags);
3407
Some very basic checks. If number of fields changes, or the
3408
handler, we need to run full ALTER TABLE. In the future
3409
new fields can be added and old dropped without copy, but
3412
Test also that engine was not given during ALTER TABLE, or
3413
we are force to run regular alter table (copy).
3414
E.g. ALTER TABLE tbl_name ENGINE=MyISAM.
3416
For the following ones we also want to run regular alter table:
3417
ALTER TABLE tbl_name ORDER BY ..
3418
ALTER TABLE tbl_name CONVERT TO CHARACTER SET ..
3420
At the moment we can't handle altering temporary tables without a copy.
3421
We also test if OPTIMIZE TABLE was given and was mapped to alter table.
3422
In that case we always do full copy.
3424
There was a bug prior to mysql-4.0.25. Number of null fields was
3425
calculated incorrectly. As a result frm and data files gets out of
3426
sync after fast alter table. There is no way to determine by which
3427
mysql version (in 4.0 and 4.1 branches) table was created, thus we
3428
disable fast alter table for all tables created by mysql versions
3429
prior to 5.0 branch.
3432
if (table->s->fields != alter_info->create_list.elements ||
3433
table->s->db_type() != create_info->db_type ||
3434
table->s->tmp_table ||
3435
create_info->used_fields & HA_CREATE_USED_ENGINE ||
3436
create_info->used_fields & HA_CREATE_USED_CHARSET ||
3437
create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET ||
3438
create_info->used_fields & HA_CREATE_USED_ROW_FORMAT ||
3439
(alter_info->flags & (ALTER_RECREATE | ALTER_FOREIGN_KEY)) ||
3441
!table->s->mysql_version ||
3442
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3444
*table_changes= IS_EQUAL_NO;
3446
Check what has changed and set alter_flags
3448
if (table->s->fields < alter_info->create_list.elements)
3449
*alter_flags|= HA_ADD_COLUMN;
3450
else if (table->s->fields > alter_info->create_list.elements)
3451
*alter_flags|= HA_DROP_COLUMN;
3452
if (create_info->db_type != table->s->db_type() ||
3453
create_info->used_fields & HA_CREATE_USED_ENGINE)
3454
*alter_flags|= HA_ALTER_STORAGE_ENGINE;
3455
if (create_info->used_fields & HA_CREATE_USED_CHARSET)
3456
*alter_flags|= HA_CHANGE_CHARACTER_SET;
3457
if (create_info->used_fields & HA_CREATE_USED_DEFAULT_CHARSET)
3458
*alter_flags|= HA_SET_DEFAULT_CHARACTER_SET;
3459
if (alter_info->flags & ALTER_RECREATE)
3460
*alter_flags|= HA_RECREATE;
3461
/* TODO check for ADD/DROP FOREIGN KEY */
3462
if (alter_info->flags & ALTER_FOREIGN_KEY)
3463
*alter_flags|= HA_ALTER_FOREIGN_KEY;
3464
if (!table->s->mysql_version ||
3465
(table->s->frm_version < FRM_VER_TRUE_VARCHAR && varchar))
3466
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3469
Go through fields and check if the original ones are compatible
3472
for (f_ptr= table->field, new_field= new_field_it++;
3473
(new_field && (field= *f_ptr));
3474
f_ptr++, new_field= new_field_it++)
3476
/* Make sure we have at least the default charset in use. */
3477
if (!new_field->charset)
3478
new_field->charset= create_info->default_table_charset;
3480
/* Don't pack rows in old tables if the user has requested this. */
3481
if (create_info->row_type == ROW_TYPE_DYNAMIC ||
3482
(new_field->flags & BLOB_FLAG) ||
3483
(new_field->sql_type == DRIZZLE_TYPE_VARCHAR && create_info->row_type != ROW_TYPE_FIXED))
3484
create_info->table_options|= HA_OPTION_PACK_RECORD;
3486
/* Check how fields have been modified */
3487
if (alter_info->flags & ALTER_CHANGE_COLUMN)
3489
/* Evaluate changes bitmap and send to check_if_incompatible_data() */
3490
if (!(table_changes_local= field->is_equal(new_field)))
3491
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3493
/* Check if field was renamed */
3494
field->flags&= ~FIELD_IS_RENAMED;
3495
if (my_strcasecmp(system_charset_info,
3497
new_field->field_name))
3499
field->flags|= FIELD_IS_RENAMED;
3500
*alter_flags|= HA_ALTER_COLUMN_NAME;
3503
*table_changes&= table_changes_local;
3504
if (table_changes_local == IS_EQUAL_PACK_LENGTH)
3505
*alter_flags|= HA_ALTER_COLUMN_TYPE;
3507
/* Check that NULL behavior is same for old and new fields */
3508
if ((new_field->flags & NOT_NULL_FLAG) !=
3509
(uint) (field->flags & NOT_NULL_FLAG))
3511
*table_changes= IS_EQUAL_NO;
3512
*alter_flags|= HA_ALTER_COLUMN_NULLABLE;
3516
/* Clear indexed marker */
3517
field->flags&= ~FIELD_IN_ADD_INDEX;
3521
Go through keys and check if the original ones are compatible
3525
KEY *table_key_end= table->key_info + table->s->keys;
3528
ha_alter_info->key_info_buffer + ha_alter_info->key_count;
3531
Step through all keys of the old table and search matching new keys.
3533
ha_alter_info->index_drop_count= 0;
3534
ha_alter_info->index_add_count= 0;
3535
for (table_key= table->key_info; table_key < table_key_end; table_key++)
3537
KEY_PART_INFO *table_part;
3538
KEY_PART_INFO *table_part_end= table_key->key_part + table_key->key_parts;
3539
KEY_PART_INFO *new_part;
3541
/* Search a new key with the same name. */
3542
for (new_key= ha_alter_info->key_info_buffer;
3543
new_key < new_key_end;
3546
if (! strcmp(table_key->name, new_key->name))
3549
if (new_key >= new_key_end)
3551
/* Key not found. Add the offset of the key to the drop buffer. */
3552
ha_alter_info->index_drop_buffer
3553
[ha_alter_info->index_drop_count++]=
3554
table_key - table->key_info;
3555
if (table_key->flags & HA_NOSAME)
3557
/* Unique key. Check for "PRIMARY". */
3558
if (! my_strcasecmp(system_charset_info,
3559
table_key->name, primary_key_name))
3560
*alter_flags|= HA_DROP_PK_INDEX;
3562
*alter_flags|= HA_DROP_UNIQUE_INDEX;
3565
*alter_flags|= HA_DROP_INDEX;
3566
*table_changes= IS_EQUAL_NO;
3570
/* Check that the key types are compatible between old and new tables. */
3571
if ((table_key->algorithm != new_key->algorithm) ||
3572
((table_key->flags & HA_KEYFLAG_MASK) !=
3573
(new_key->flags & HA_KEYFLAG_MASK)) ||
3574
(table_key->key_parts != new_key->key_parts))
3576
if (table_key->flags & HA_NOSAME)
3578
// Unique key. Check for "PRIMARY".
3579
if (! my_strcasecmp(system_charset_info,
3580
table_key->name, primary_key_name))
3581
*alter_flags|= HA_ALTER_PK_INDEX;
3583
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
3586
*alter_flags|= HA_ALTER_INDEX;
3591
Check that the key parts remain compatible between the old and
3594
for (table_part= table_key->key_part, new_part= new_key->key_part;
3595
table_part < table_part_end;
3596
table_part++, new_part++)
3599
Key definition has changed if we are using a different field or
3600
if the used key part length is different. We know that the fields
3601
did not change. Comparing field numbers is sufficient.
3603
if ((table_part->length != new_part->length) ||
3604
(table_part->fieldnr - 1 != new_part->fieldnr))
3606
if (table_key->flags & HA_NOSAME)
3608
/* Unique key. Check for "PRIMARY" */
3609
if (! my_strcasecmp(system_charset_info,
3610
table_key->name, primary_key_name))
3611
*alter_flags|= HA_ALTER_PK_INDEX;
3613
*alter_flags|= HA_ALTER_UNIQUE_INDEX;
3616
*alter_flags|= HA_ALTER_INDEX;
3623
/* Key modified. Add the offset of the key to both buffers. */
3624
ha_alter_info->index_drop_buffer
3625
[ha_alter_info->index_drop_count++]=
3626
table_key - table->key_info;
3627
ha_alter_info->index_add_buffer
3628
[ha_alter_info->index_add_count++]=
3629
new_key - ha_alter_info->key_info_buffer;
3630
key_part= new_key->key_part;
3631
end= key_part + new_key->key_parts;
3632
for(; key_part != end; key_part++)
3634
/* Mark field to be part of new key */
3635
if ((field= table->field[key_part->fieldnr]))
3636
field->flags|= FIELD_IN_ADD_INDEX;
3638
*table_changes= IS_EQUAL_NO;
3640
/*end of for (; table_key < table_key_end;) */
3643
Step through all keys of the new table and find matching old keys.
3645
for (new_key= ha_alter_info->key_info_buffer;
3646
new_key < new_key_end;
3649
/* Search an old key with the same name. */
3650
for (table_key= table->key_info; table_key < table_key_end; table_key++)
3652
if (! strcmp(table_key->name, new_key->name))
3655
if (table_key >= table_key_end)
3657
/* Key not found. Add the offset of the key to the add buffer. */
3658
ha_alter_info->index_add_buffer
3659
[ha_alter_info->index_add_count++]=
3660
new_key - ha_alter_info->key_info_buffer;
3661
key_part= new_key->key_part;
3662
end= key_part + new_key->key_parts;
3663
for(; key_part != end; key_part++)
3665
/* Mark field to be part of new key */
3666
if ((field= table->field[key_part->fieldnr]))
3667
field->flags|= FIELD_IN_ADD_INDEX;
3669
if (new_key->flags & HA_NOSAME)
3671
/* Unique key. Check for "PRIMARY" */
3672
if (! my_strcasecmp(system_charset_info,
3673
new_key->name, primary_key_name))
3674
*alter_flags|= HA_ADD_PK_INDEX;
3676
*alter_flags|= HA_ADD_UNIQUE_INDEX;
3679
*alter_flags|= HA_ADD_INDEX;
3680
*table_changes= IS_EQUAL_NO;
3689
Manages enabling/disabling of indexes for ALTER TABLE
3692
alter_table_manage_keys()
3694
indexes_were_disabled Whether the indexes of the from table
3696
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
3704
bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
3705
enum enum_enable_or_disable keys_onoff)
3708
switch (keys_onoff) {
3710
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3713
if (!indexes_were_disabled)
3715
/* fall-through: disabled indexes */
3717
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3720
if (error == HA_ERR_WRONG_COMMAND)
3722
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
3723
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3724
table->s->table_name.str);
3727
table->file->print_error(error, MYF(0));
3732
int create_temporary_table(THD *thd,
3736
HA_CREATE_INFO *create_info,
3737
Alter_info *alter_info,
3741
char index_file[FN_REFLEN], data_file[FN_REFLEN];
3742
handlerton *old_db_type, *new_db_type;
3743
old_db_type= table->s->db_type();
3744
new_db_type= create_info->db_type;
3746
Handling of symlinked tables:
3748
Create new data file and index file on the same disk as the
3749
old data and index files.
3751
Rename new data file over old data file and new index file over
3753
Symlinks are not changed.
3756
Create new data file and index file on the same disk as the
3757
old data and index files. Create also symlinks to point at
3760
At end, rename intermediate tables, and symlinks to intermediate
3761
table, to final table name.
3762
Remove old table and old symlinks
3764
If rename is made to another database:
3765
Create new tables in new database.
3767
Remove old table and symlinks.
3769
if (db_changed) // Ignore symlink if db changed
3771
if (create_info->index_file_name)
3773
/* Fix index_file_name to have 'tmp_name' as basename */
3774
strmov(index_file, tmp_name);
3775
create_info->index_file_name=fn_same(index_file,
3776
create_info->index_file_name,
3779
if (create_info->data_file_name)
3781
/* Fix data_file_name to have 'tmp_name' as basename */
3782
strmov(data_file, tmp_name);
3783
create_info->data_file_name=fn_same(data_file,
3784
create_info->data_file_name,
3789
create_info->data_file_name=create_info->index_file_name=0;
3792
Create a table with a temporary name.
3793
With create_info->frm_only == 1 this creates a .frm file only.
3794
We don't log the statement, it will be logged later.
3796
tmp_disable_binlog(thd);
3797
error= mysql_create_table(thd, new_db, tmp_name,
3798
create_info, alter_info, 1, 0);
3799
reenable_binlog(thd);
3805
Create a temporary table that reflects what an alter table operation
3809
create_altered_table()
3811
table The original table
3812
create_info Information from the parsing phase about new
3814
alter_info Lists of fields, keys to be changed, added
3816
db_change Specifies if the table is moved to another database
3818
A temporary table with all changes
3821
The temporary table is created without storing it in any storage engine
3822
and is opened only to get the table struct and frm file reference.
3824
TABLE *create_altered_table(THD *thd,
3827
HA_CREATE_INFO *create_info,
3828
Alter_info *alter_info,
3832
HA_CREATE_INFO altered_create_info(*create_info);
3833
TABLE *altered_table;
3835
char path[FN_REFLEN];
3837
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
3838
tmp_file_prefix, current_pid, thd->thread_id);
3839
/* Safety fix for InnoDB */
3840
if (lower_case_table_names)
3841
my_casedn_str(files_charset_info, tmp_name);
3842
altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
3843
altered_create_info.frm_only= 1;
3844
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
3845
&altered_create_info,
3846
alter_info, db_change)))
3851
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
3853
altered_table= open_temporary_table(thd, path, new_db, tmp_name, 1,
3855
return(altered_table);
3862
Perform a fast or on-line alter table
3865
mysql_fast_or_online_alter_table()
3867
table The original table
3868
altered_table A temporary table showing how we will change table
3869
create_info Information from the parsing phase about new
3871
alter_info Storage place for data used during different phases
3872
ha_alter_flags Bitmask that shows what will be changed
3873
keys_onoff Specifies if keys are to be enabled/disabled
3876
>0 An error occured during the on-line alter table operation
3877
-1 Error when re-opening table
3879
If mysql_alter_table does not need to copy the table, it is
3880
either a fast alter table where the storage engine does not
3881
need to know about the change, only the frm will change,
3882
or the storage engine supports performing the alter table
3883
operation directly, on-line without mysql having to copy
3886
int mysql_fast_or_online_alter_table(THD *thd,
3888
TABLE *altered_table,
3889
HA_CREATE_INFO *create_info,
3890
HA_ALTER_INFO *alter_info,
3891
HA_ALTER_FLAGS *ha_alter_flags,
3892
enum enum_enable_or_disable keys_onoff)
3895
bool online= (table->file->ha_table_flags() & HA_ONLINE_ALTER)?true:false;
3901
Tell the handler to prepare for the online alter
3903
if ((error= table->file->alter_table_phase1(thd,
3913
Tell the storage engine to perform the online alter table
3915
if check_if_supported_alter() returned HA_ALTER_SUPPORTED_WAIT_LOCK
3916
we need to wrap the next call with a DDL lock.
3918
if ((error= table->file->alter_table_phase2(thd,
3928
The final .frm file is already created as a temporary file
3929
and will be renamed to the original table name.
3931
VOID(pthread_mutex_lock(&LOCK_open));
3932
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
3933
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
3935
close_data_files_and_morph_locks(thd,
3936
table->pos_in_table_list->db,
3937
table->pos_in_table_list->table_name);
3938
if (mysql_rename_table(NULL,
3939
altered_table->s->db.str,
3940
altered_table->s->table_name.str,
3942
table->s->table_name.str, FN_FROM_IS_TMP))
3945
VOID(pthread_mutex_unlock(&LOCK_open));
3948
broadcast_refresh();
3949
VOID(pthread_mutex_unlock(&LOCK_open));
3952
The ALTER TABLE is always in its own transaction.
3953
Commit must not be called while LOCK_open is locked. It could call
3954
wait_if_global_read_lock(), which could create a deadlock if called
3957
error= ha_autocommit_or_rollback(thd, 0);
3965
VOID(pthread_mutex_lock(&LOCK_open));
3966
if (reopen_table(table))
3971
VOID(pthread_mutex_unlock(&LOCK_open));
3975
Tell the handler that the changed frm is on disk and table
3978
if ((error= t_table->file->alter_table_phase3(thd, t_table)))
3984
We are going to reopen table down on the road, so we have to restore
3985
state of the TABLE object which we used for obtaining of handler
3986
object to make it suitable for reopening.
3988
assert(t_table == table);
3989
table->open_placeholder= 1;
3990
VOID(pthread_mutex_lock(&LOCK_open));
3991
close_handle_and_leave_table_as_lock(table);
3992
VOID(pthread_mutex_unlock(&LOCK_open));
4003
Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
4005
This function transforms parse output of ALTER TABLE - lists of
4006
columns and keys to add, drop or modify into, essentially,
4007
CREATE TABLE definition - a list of columns and keys of the new
4008
table. While doing so, it also performs some (bug not all)
4011
This function is invoked when we know that we're going to
4012
perform ALTER TABLE via a temporary table -- i.e. fast ALTER TABLE
4013
is not possible, perhaps because the ALTER statement contains
4014
instructions that require change in table data, not only in
4015
table definition or indexes.
4017
@param[in,out] thd thread handle. Used as a memory pool
4018
and source of environment information.
4019
@param[in] table the source table, open and locked
4020
Used as an interface to the storage engine
4021
to acquire additional information about
4023
@param[in,out] create_info A blob with CREATE/ALTER TABLE
4025
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
4026
Originally create_info was used only in
4027
CREATE TABLE and alter_info only in ALTER TABLE.
4028
But since ALTER might end-up doing CREATE,
4029
this distinction is gone and we just carry
4030
around two structures.
4033
Fills various create_info members based on information retrieved
4034
from the storage engine.
4035
Sets create_info->varchar if the table has a VARCHAR column.
4036
Prepares alter_info->create_list and alter_info->key_list with
4037
columns and keys of the new table.
4038
@retval true error, out of memory or a semantical error in ALTER
4040
@retval false success
4044
mysql_prepare_alter_table(THD *thd, TABLE *table,
4045
HA_CREATE_INFO *create_info,
4046
Alter_info *alter_info)
4048
/* New column definitions are added here */
4049
List<Create_field> new_create_list;
4050
/* New key definitions are added here */
4051
List<Key> new_key_list;
4052
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
4053
List_iterator<Create_field> def_it(alter_info->create_list);
4054
List_iterator<Alter_column> alter_it(alter_info->alter_list);
4055
List_iterator<Key> key_it(alter_info->key_list);
4056
List_iterator<Create_field> find_it(new_create_list);
4057
List_iterator<Create_field> field_it(new_create_list);
4058
List<Key_part_spec> key_parts;
4059
uint db_create_options= (table->s->db_create_options
4060
& ~(HA_OPTION_PACK_RECORD));
4061
uint used_fields= create_info->used_fields;
4062
KEY *key_info=table->key_info;
4066
create_info->varchar= false;
4067
/* Let new create options override the old ones */
4068
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
4069
create_info->min_rows= table->s->min_rows;
4070
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
4071
create_info->max_rows= table->s->max_rows;
4072
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
4073
create_info->avg_row_length= table->s->avg_row_length;
4074
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
4075
create_info->default_table_charset= table->s->table_charset;
4076
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
4078
/* Table has an autoincrement, copy value to new table */
4079
table->file->info(HA_STATUS_AUTO);
4080
create_info->auto_increment_value= table->file->stats.auto_increment_value;
4082
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
4083
create_info->key_block_size= table->s->key_block_size;
4084
if (!(used_fields & HA_CREATE_USED_TRANSACTIONAL))
4085
create_info->transactional= table->s->transactional;
4087
restore_record(table, s->default_values); // Empty record for DEFAULT
4091
First collect all fields from table which isn't in drop_list
4093
Field **f_ptr,*field;
4094
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
4096
/* Check if field should be dropped */
4099
while ((drop=drop_it++))
4101
if (drop->type == Alter_drop::COLUMN &&
4102
!my_strcasecmp(system_charset_info,field->field_name, drop->name))
4104
/* Reset auto_increment value if it was dropped */
4105
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
4106
!(used_fields & HA_CREATE_USED_AUTO))
4108
create_info->auto_increment_value=0;
4109
create_info->used_fields|=HA_CREATE_USED_AUTO;
4119
/* Check if field is changed */
4121
while ((def=def_it++))
4124
!my_strcasecmp(system_charset_info,field->field_name, def->change))
4128
{ // Field is changed
4132
new_create_list.push_back(def);
4139
This field was not dropped and not changed, add it to the list
4142
def= new Create_field(field, field);
4143
new_create_list.push_back(def);
4144
alter_it.rewind(); // Change default if ALTER
4145
Alter_column *alter;
4146
while ((alter=alter_it++))
4148
if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
4153
if (def->sql_type == DRIZZLE_TYPE_BLOB)
4155
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
4158
if ((def->def=alter->def)) // Use new default
4159
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
4161
def->flags|= NO_DEFAULT_VALUE_FLAG;
4167
while ((def=def_it++)) // Add new columns
4169
if (def->change && ! def->field)
4171
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
4175
Check that the DATE/DATETIME not null field we are going to add is
4176
either has a default value or the '0000-00-00' is allowed by the
4178
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
4179
flag to allow ALTER TABLE only if the table to be altered is empty.
4181
if ((def->sql_type == DRIZZLE_TYPE_NEWDATE ||
4182
def->sql_type == DRIZZLE_TYPE_DATETIME) &&
4183
!alter_info->datetime_field &&
4184
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
4185
thd->variables.sql_mode & MODE_NO_ZERO_DATE)
4187
alter_info->datetime_field= def;
4188
alter_info->error_if_not_empty= true;
4191
new_create_list.push_back(def);
4192
else if (def->after == first_keyword)
4193
new_create_list.push_front(def);
4198
while ((find=find_it++)) // Add new columns
4200
if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
4205
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
4208
find_it.after(def); // Put element after this
4210
XXX: hack for Bug#28427.
4211
If column order has changed, force OFFLINE ALTER TABLE
4212
without querying engine capabilities. If we ever have an
4213
engine that supports online ALTER TABLE CHANGE COLUMN
4214
<name> AFTER <name1> (Falcon?), this fix will effectively
4215
disable the capability.
4216
TODO: detect the situation in compare_tables, behave based
4217
on engine capabilities.
4219
if (alter_info->build_method == HA_BUILD_ONLINE)
4221
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4224
alter_info->build_method= HA_BUILD_OFFLINE;
4227
if (alter_info->alter_list.elements)
4229
my_error(ER_BAD_FIELD_ERROR, MYF(0),
4230
alter_info->alter_list.head()->name, table->s->table_name.str);
4233
if (!new_create_list.elements)
4235
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
4241
Collect all keys which isn't in drop list. Add only those
4242
for which some fields exists.
4245
for (uint i=0 ; i < table->s->keys ; i++,key_info++)
4247
char *key_name= key_info->name;
4250
while ((drop=drop_it++))
4252
if (drop->type == Alter_drop::KEY &&
4253
!my_strcasecmp(system_charset_info,key_name, drop->name))
4262
KEY_PART_INFO *key_part= key_info->key_part;
4264
for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
4266
if (!key_part->field)
4267
continue; // Wrong field (from UNIREG)
4268
const char *key_part_name=key_part->field->field_name;
4269
Create_field *cfield;
4271
while ((cfield=field_it++))
4275
if (!my_strcasecmp(system_charset_info, key_part_name,
4279
else if (!my_strcasecmp(system_charset_info,
4280
key_part_name, cfield->field_name))
4284
continue; // Field is removed
4285
uint key_part_length=key_part->length;
4286
if (cfield->field) // Not new field
4289
If the field can't have only a part used in a key according to its
4290
new type, or should not be used partially according to its
4291
previous type, or the field length is less than the key part
4292
length, unset the key part length.
4294
We also unset the key part length if it is the same as the
4295
old field's length, so the whole new field will be used.
4297
BLOBs may have cfield->length == 0, which is why we test it before
4298
checking whether cfield->length < key_part_length (in chars).
4300
if (!Field::type_can_have_key_part(cfield->field->type()) ||
4301
!Field::type_can_have_key_part(cfield->sql_type) ||
4302
(cfield->field->field_length == key_part_length &&
4303
!f_is_blob(key_part->key_type)) ||
4304
(cfield->length && (cfield->length < key_part_length /
4305
key_part->field->charset()->mbmaxlen)))
4306
key_part_length= 0; // Use whole field
4308
key_part_length /= key_part->field->charset()->mbmaxlen;
4309
key_parts.push_back(new Key_part_spec(cfield->field_name,
4310
strlen(cfield->field_name),
4313
if (key_parts.elements)
4315
KEY_CREATE_INFO key_create_info;
4317
enum Key::Keytype key_type;
4318
memset((char*) &key_create_info, 0, sizeof(key_create_info));
4320
key_create_info.algorithm= key_info->algorithm;
4321
if (key_info->flags & HA_USES_BLOCK_SIZE)
4322
key_create_info.block_size= key_info->block_size;
4323
if (key_info->flags & HA_USES_COMMENT)
4324
key_create_info.comment= key_info->comment;
4326
if (key_info->flags & HA_NOSAME)
4328
if (! my_strcasecmp(system_charset_info, key_name, primary_key_name))
4329
key_type= Key::PRIMARY;
4331
key_type= Key::UNIQUE;
4334
key_type= Key::MULTIPLE;
4336
key= new Key(key_type, key_name, strlen(key_name),
4338
test(key_info->flags & HA_GENERATED_KEY),
4340
new_key_list.push_back(key);
4345
while ((key=key_it++)) // Add new keys
4347
if (key->type != Key::FOREIGN_KEY)
4348
new_key_list.push_back(key);
4349
if (key->name.str &&
4350
!my_strcasecmp(system_charset_info, key->name.str, primary_key_name))
4352
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
4358
if (alter_info->drop_list.elements)
4360
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4361
alter_info->drop_list.head()->name);
4364
if (alter_info->alter_list.elements)
4366
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
4367
alter_info->alter_list.head()->name);
4371
if (!create_info->comment.str)
4373
create_info->comment.str= table->s->comment.str;
4374
create_info->comment.length= table->s->comment.length;
4377
table->file->update_create_info(create_info);
4378
if ((create_info->table_options &
4379
(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
4380
(used_fields & HA_CREATE_USED_PACK_KEYS))
4381
db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
4382
if (create_info->table_options &
4383
(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
4384
db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
4385
if (create_info->table_options &
4386
(HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_NO_DELAY_KEY_WRITE))
4387
db_create_options&= ~(HA_OPTION_DELAY_KEY_WRITE |
4388
HA_OPTION_NO_DELAY_KEY_WRITE);
4389
create_info->table_options|= db_create_options;
4391
if (table->s->tmp_table)
4392
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
4395
alter_info->create_list.swap(new_create_list);
4396
alter_info->key_list.swap(new_key_list);
4408
new_db If there is a RENAME clause
4409
new_name If there is a RENAME clause
4410
create_info Information from the parsing phase about new
4412
table_list The table to change.
4413
alter_info Lists of fields, keys to be changed, added
4415
order_num How many ORDER BY fields has been specified.
4416
order List of fields to ORDER BY.
4417
ignore Whether we have ALTER IGNORE TABLE
4420
This is a veery long function and is everything but the kitchen sink :)
4421
It is used to alter a table and not only by ALTER TABLE but also
4422
CREATE|DROP INDEX are mapped on this function.
4424
When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
4425
or both, then this function short cuts its operation by renaming
4426
the table and/or enabling/disabling the keys. In this case, the FRM is
4427
not changed, directly by mysql_alter_table. However, if there is a
4428
RENAME + change of a field, or an index, the short cut is not used.
4429
See how `create_list` is used to generate the new FRM regarding the
4430
structure of the fields. The same is done for the indices of the table.
4432
Important is the fact, that this function tries to do as little work as
4433
possible, by finding out whether a intermediate table is needed to copy
4434
data into and when finishing the altering to use it as the original table.
4435
For this reason the function compare_tables() is called, which decides
4436
based on all kind of data how similar are the new and the original
4444
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
4445
HA_CREATE_INFO *create_info,
4446
TABLE_LIST *table_list,
4447
Alter_info *alter_info,
4448
uint order_num, ORDER *order, bool ignore)
4450
TABLE *table, *new_table=0, *name_lock= 0;;
4452
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
4453
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
4454
char path[FN_REFLEN];
4455
ha_rows copied= 0,deleted= 0;
4456
handlerton *old_db_type, *new_db_type, *save_old_db_type;
4457
legacy_db_type table_type;
4458
frm_type_enum frm_type;
4460
if (table_list && table_list->schema_table)
4462
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
4467
Assign variables table_name, new_name, db, new_db, path
4468
to simplify further comparisons: we want to see if it's a RENAME
4469
later just by comparing the pointers, avoiding the need for strcmp.
4471
thd_proc_info(thd, "init");
4472
table_name=table_list->table_name;
4473
alias= (lower_case_table_names == 2) ? table_list->alias : table_name;
4475
if (!new_db || !my_strcasecmp(table_alias_charset, new_db, db))
4477
build_table_filename(path, sizeof(path), db, table_name, "", 0);
4479
mysql_ha_rm_tables(thd, table_list, false);
4481
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
4482
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
4483
/* Conditionally writes to binlog. */
4484
return(mysql_discard_or_import_tablespace(thd,table_list,
4485
alter_info->tablespace_op));
4486
strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
4487
"/", table_name, reg_ext, NullS);
4488
(void) unpack_filename(new_name_buff, new_name_buff);
4490
If this is just a rename of a view, short cut to the
4491
following scenario: 1) lock LOCK_open 2) do a RENAME
4492
2) unlock LOCK_open.
4493
This is a copy-paste added to make sure
4494
ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
4495
as an independent branch in mysql_execute_command. The need
4496
for a copy-paste arose because the main code flow of ALTER TABLE
4497
... RENAME tries to use open_ltable, which does not work for views
4498
(open_ltable was never modified to merge table lists of child tables
4499
into the main table list, like open_tables does).
4500
This code is wrong and will be removed, please do not copy.
4502
frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
4504
if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
4506
table->use_all_columns();
4509
Prohibit changing of the UNION list of a non-temporary MERGE table
4510
under LOCK tables. It would be quite difficult to reuse a shrinked
4511
set of tables from the old table or to open a new TABLE object for
4512
an extended list and verify that they belong to locked tables.
4514
if (thd->locked_tables &&
4515
(create_info->used_fields & HA_CREATE_USED_UNION) &&
4516
(table->s->tmp_table == NO_TMP_TABLE))
4518
my_error(ER_LOCK_OR_ACTIVE_TRANSACTION, MYF(0));
4522
/* Check that we are not trying to rename to an existing table */
4525
strmov(new_name_buff,new_name);
4526
strmov(new_alias= new_alias_buff, new_name);
4527
if (lower_case_table_names)
4529
if (lower_case_table_names != 2)
4531
my_casedn_str(files_charset_info, new_name_buff);
4532
new_alias= new_name; // Create lower case table name
4534
my_casedn_str(files_charset_info, new_name);
4537
!my_strcasecmp(table_alias_charset, new_name_buff, table_name))
4540
Source and destination table names are equal: make later check
4543
new_alias= new_name= table_name;
4547
if (table->s->tmp_table != NO_TMP_TABLE)
4549
if (find_temporary_table(thd,new_db,new_name_buff))
4551
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
4557
if (lock_table_name_if_not_cached(thd, new_db, new_name, &name_lock))
4561
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
4565
build_table_filename(new_name_buff, sizeof(new_name_buff),
4566
new_db, new_name_buff, reg_ext, 0);
4567
if (!access(new_name_buff, F_OK))
4569
/* Table will be closed in do_command() */
4570
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
4578
new_alias= (lower_case_table_names == 2) ? alias : table_name;
4579
new_name= table_name;
4582
old_db_type= table->s->db_type();
4583
if (!create_info->db_type)
4585
create_info->db_type= old_db_type;
4588
if (check_engine(thd, new_name, create_info))
4590
new_db_type= create_info->db_type;
4592
if (new_db_type != old_db_type &&
4593
!table->file->can_switch_engines())
4596
my_error(ER_ROW_IS_REFERENCED, MYF(0));
4600
if (create_info->row_type == ROW_TYPE_NOT_USED)
4601
create_info->row_type= table->s->row_type;
4603
if (ha_check_storage_engine_flag(old_db_type, HTON_ALTER_NOT_SUPPORTED) ||
4604
ha_check_storage_engine_flag(new_db_type, HTON_ALTER_NOT_SUPPORTED))
4606
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
4610
thd_proc_info(thd, "setup");
4611
if (!(alter_info->flags & ~(ALTER_RENAME | ALTER_KEYS_ONOFF)) &&
4612
!table->s->tmp_table) // no need to touch frm
4614
switch (alter_info->keys_onoff) {
4619
wait_while_table_is_used() ensures that table being altered is
4620
opened only by this thread and that TABLE::TABLE_SHARE::version
4621
of TABLE object corresponding to this table is 0.
4622
The latter guarantees that no DML statement will open this table
4623
until ALTER TABLE finishes (i.e. until close_thread_tables())
4624
while the fact that the table is still open gives us protection
4625
from concurrent DDL statements.
4627
VOID(pthread_mutex_lock(&LOCK_open));
4628
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4629
VOID(pthread_mutex_unlock(&LOCK_open));
4630
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4631
/* COND_refresh will be signaled in close_thread_tables() */
4634
VOID(pthread_mutex_lock(&LOCK_open));
4635
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4636
VOID(pthread_mutex_unlock(&LOCK_open));
4637
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4638
/* COND_refresh will be signaled in close_thread_tables() */
4645
if (error == HA_ERR_WRONG_COMMAND)
4648
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
4649
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4653
VOID(pthread_mutex_lock(&LOCK_open));
4655
Unlike to the above case close_cached_table() below will remove ALL
4656
instances of TABLE from table cache (it will also remove table lock
4657
held by this thread). So to make actual table renaming and writing
4658
to binlog atomic we have to put them into the same critical section
4659
protected by LOCK_open mutex. This also removes gap for races between
4660
access() and mysql_rename_table() calls.
4663
if (!error && (new_name != table_name || new_db != db))
4665
thd_proc_info(thd, "rename");
4667
Then do a 'simple' rename of the table. First we need to close all
4668
instances of 'source' table.
4670
close_cached_table(thd, table);
4672
Then, we want check once again that target table does not exist.
4673
Actually the order of these two steps does not matter since
4674
earlier we took name-lock on the target table, so we do them
4675
in this particular order only to be consistent with 5.0, in which
4676
we don't take this name-lock and where this order really matters.
4677
TODO: Investigate if we need this access() check at all.
4679
if (!access(new_name_buff,F_OK))
4681
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
4686
*fn_ext(new_name)=0;
4687
if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias, 0))
4691
VOID(mysql_rename_table(old_db_type, new_db, new_alias, db,
4698
if (error == HA_ERR_WRONG_COMMAND)
4701
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
4702
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
4708
write_bin_log(thd, true, thd->query, thd->query_length);
4713
table->file->print_error(error, MYF(0));
2193
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2194
session->unlink_open_table(name_lock);
2200
if (is_if_not_exists)
2202
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2203
snprintf(warn_buff, sizeof(warn_buff),
2204
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2205
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2206
ER_TABLE_EXISTS_ERROR, warn_buff);
2210
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
4717
unlink_open_table(thd, name_lock, false);
4718
VOID(pthread_mutex_unlock(&LOCK_open));
4719
table_list->table= NULL; // For query cache
4723
/* We have to do full alter table. */
4726
If the old table had partitions and we are doing ALTER TABLE ...
4727
engine= <new_engine>, the new table must preserve the original
4728
partitioning. That means that the new engine is still the
4729
partitioning engine, not the engine specified in the parser.
4730
This is discovered in prep_alter_part_table, which in such case
4731
updates create_info->db_type.
4732
Now we need to update the stack copy of create_info->db_type,
4733
as otherwise we won't be able to correctly move the files of the
4734
temporary table to the result table files.
4736
new_db_type= create_info->db_type;
4738
if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
4741
set_table_default_charset(thd, create_info, db);
4744
if (thd->variables.old_alter_table
4745
|| (table->s->db_type() != create_info->db_type)
4748
if (alter_info->build_method == HA_BUILD_ONLINE)
4750
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4753
alter_info->build_method= HA_BUILD_OFFLINE;
4756
if (alter_info->build_method != HA_BUILD_OFFLINE)
4758
TABLE *altered_table= 0;
4759
HA_ALTER_INFO ha_alter_info;
4760
HA_ALTER_FLAGS ha_alter_flags;
4761
uint table_changes= IS_EQUAL_YES;
4762
bool need_copy_table= true;
4763
/* Check how much the tables differ. */
4764
if (compare_tables(thd, table, alter_info,
4765
create_info, order_num,
4774
Check if storage engine supports altering the table
4780
If table is not renamed, changed database and
4781
some change was detected then check if engine
4782
can do the change on-line
4784
if (new_name == table_name && new_db == db &&
4785
ha_alter_flags.is_set())
4787
Alter_info tmp_alter_info(*alter_info, thd->mem_root);
4791
check if table can be altered on-line
4793
if (!(altered_table= create_altered_table(thd,
4798
!strcmp(db, new_db))))
4801
switch (table->file->check_if_supported_alter(altered_table,
4805
case HA_ALTER_SUPPORTED_WAIT_LOCK:
4806
case HA_ALTER_SUPPORTED_NO_LOCK:
4808
@todo: Currently we always acquire an exclusive name
4809
lock on the table metadata when performing fast or online
4810
ALTER TABLE. In future we may consider this unnecessary,
4811
and narrow the scope of the exclusive name lock to only
4812
cover manipulation with .frms. Storage engine API
4813
call check_if_supported_alter has provision for this
4816
need_copy_table= false;
4818
case HA_ALTER_NOT_SUPPORTED:
4819
if (alter_info->build_method == HA_BUILD_ONLINE)
4821
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4822
close_temporary_table(thd, altered_table, 1, 1);
4825
need_copy_table= true;
4827
case HA_ALTER_ERROR:
4829
close_temporary_table(thd, altered_table, 1, 1);
4834
/* TODO need to check if changes can be handled as fast ALTER TABLE */
4836
need_copy_table= true;
4838
if (!need_copy_table)
4840
error= mysql_fast_or_online_alter_table(thd,
4846
alter_info->keys_onoff);
4849
mysql_unlock_tables(thd, thd->lock);
4852
close_temporary_table(thd, altered_table, 1, 1);
4858
goto err_with_placeholders;
4865
pthread_mutex_lock(&LOCK_open);
4871
close_temporary_table(thd, altered_table, 1, 1);
4874
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
4875
current_pid, thd->thread_id);
4876
/* Safety fix for innodb */
4877
if (lower_case_table_names)
4878
my_casedn_str(files_charset_info, tmp_name);
4881
/* Create a temporary table with the new format */
4882
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
4883
create_info, alter_info,
4884
!strcmp(db, new_db))))
4889
/* Open the table so we need to copy the data to it. */
4890
if (table->s->tmp_table)
4893
memset((void*) &tbl, 0, sizeof(tbl));
4895
tbl.table_name= tbl.alias= tmp_name;
4896
/* Table is in thd->temporary_tables */
4897
new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
4898
MYSQL_LOCK_IGNORE_FLUSH);
4902
char path[FN_REFLEN];
4903
/* table is a normal table: Create temporary table in same directory */
4904
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
4906
/* Open our intermediate table */
4907
new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
4912
/* Copy the data if necessary. */
4913
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
4914
thd->cuted_fields=0L;
4915
thd_proc_info(thd, "copy to tmp table");
4918
We do not copy data for MERGE tables. Only the children have data.
4919
MERGE tables have HA_NO_COPY_ON_ALTER set.
4921
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
4923
/* We don't want update TIMESTAMP fields during ALTER TABLE. */
4924
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
4925
new_table->next_number_field=new_table->found_next_number_field;
4926
error= copy_data_between_tables(table, new_table,
4927
alter_info->create_list, ignore,
4928
order_num, order, &copied, &deleted,
4929
alter_info->keys_onoff,
4930
alter_info->error_if_not_empty);
4934
VOID(pthread_mutex_lock(&LOCK_open));
4935
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4936
VOID(pthread_mutex_unlock(&LOCK_open));
4937
alter_table_manage_keys(table, table->file->indexes_are_disabled(),
4938
alter_info->keys_onoff);
4939
error= ha_autocommit_or_rollback(thd, 0);
4940
if (end_active_trans(thd))
4943
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
4945
if (table->s->tmp_table != NO_TMP_TABLE)
4947
/* We changed a temporary table */
4950
/* Close lock if this is a transactional table */
4953
mysql_unlock_tables(thd, thd->lock);
4956
/* Remove link to old table and rename the new one */
4957
close_temporary_table(thd, table, 1, 1);
4958
/* Should pass the 'new_name' as we store table name in the cache */
4959
if (rename_temporary_table(thd, new_table, new_db, new_name))
4961
/* We don't replicate alter table statement on temporary tables */
4962
if (!thd->current_stmt_binlog_row_based)
4963
write_bin_log(thd, true, thd->query, thd->query_length);
4970
Close the intermediate table that will be the new table.
4971
Note that MERGE tables do not have their children attached here.
4973
intern_close_table(new_table);
4974
my_free(new_table,MYF(0));
4976
VOID(pthread_mutex_lock(&LOCK_open));
4979
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4980
VOID(pthread_mutex_unlock(&LOCK_open));
4985
Data is copied. Now we:
4986
1) Wait until all other threads close old version of table.
4987
2) Close instances of table open by this thread and replace them
4988
with exclusive name-locks.
4989
3) Rename the old table to a temp name, rename the new one to the
4991
4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
4992
we reopen new version of table.
4993
5) Write statement to the binary log.
4994
6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
4995
remove name-locks from list of open tables and table cache.
4996
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
4997
call to remove name-locks from table cache and list of open table.
5000
thd_proc_info(thd, "rename result table");
5001
snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
5002
current_pid, thd->thread_id);
5003
if (lower_case_table_names)
5004
my_casedn_str(files_charset_info, old_name);
5006
wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
5007
close_data_files_and_morph_locks(thd, db, table_name);
5010
save_old_db_type= old_db_type;
5013
This leads to the storage engine (SE) not being notified for renames in
5014
mysql_rename_table(), because we just juggle with the FRM and nothing
5015
more. If we have an intermediate table, then we notify the SE that
5016
it should become the actual table. Later, we will recycle the old table.
5017
However, in case of ALTER TABLE RENAME there might be no intermediate
5018
table. This is when the old and new tables are compatible, according to
5019
compare_table(). Then, we need one additional call to
5020
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
5021
actual rename in the SE and the FRM is not touched. Note that, if the
5022
table is renamed and the SE is also changed, then an intermediate table
5023
is created and the additional call will not take place.
5025
if (mysql_rename_table(old_db_type, db, table_name, db, old_name,
5029
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5031
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
5032
new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
5034
/* Try to get everything back. */
5036
VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
5037
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5038
VOID(mysql_rename_table(old_db_type, db, old_name, db, alias,
5044
/* This shouldn't happen. But let us play it safe. */
5045
goto err_with_placeholders;
5048
VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
5051
if (thd->locked_tables && new_name == table_name && new_db == db)
5053
thd->in_lock_tables= 1;
5054
error= reopen_tables(thd, 1, 1);
5055
thd->in_lock_tables= 0;
5057
goto err_with_placeholders;
5059
VOID(pthread_mutex_unlock(&LOCK_open));
5061
thd_proc_info(thd, "end");
5063
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
5064
thd->query, thd->query_length,
5067
assert(!(mysql_bin_log.is_open() &&
5068
thd->current_stmt_binlog_row_based &&
5069
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
5070
write_bin_log(thd, true, thd->query, thd->query_length);
5072
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
5075
For the alter table to be properly flushed to the logs, we
5076
have to open the new table. If not, we get a problem on server
5077
shutdown. But we do not need to attach MERGE children.
5079
char path[FN_REFLEN];
5081
build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
5082
t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
5085
intern_close_table(t_table);
5086
my_free(t_table, MYF(0));
5089
sql_print_warning("Could not open table %s.%s after rename\n",
5091
ha_flush_logs(old_db_type);
5093
table_list->table=0; // For query cache
5095
if (thd->locked_tables && (new_name != table_name || new_db != db))
5098
If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
5099
to remove placeholders for the old table and for the target table
5100
from the list of open tables and table cache. If we are not under
5101
LOCK TABLES we can rely on close_thread_tables() doing this job.
5103
pthread_mutex_lock(&LOCK_open);
5104
unlink_open_table(thd, table, false);
5105
unlink_open_table(thd, name_lock, false);
5106
pthread_mutex_unlock(&LOCK_open);
5110
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
5111
(ulong) (copied + deleted), (ulong) deleted,
5112
(ulong) thd->cuted_fields);
5113
my_ok(thd, copied + deleted, 0L, tmp_name);
5114
thd->some_tables_deleted=0;
5120
/* close_temporary_table() frees the new_table pointer. */
5121
close_temporary_table(thd, new_table, 1, 1);
5124
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5128
No default value was provided for a DATE/DATETIME field, the
5129
current sql_mode doesn't allow the '0000-00-00' value and
5130
the table to be altered isn't empty.
5133
if (alter_info->error_if_not_empty && thd->row_count)
5135
const char *f_val= 0;
5136
enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
5137
switch (alter_info->datetime_field->sql_type)
5139
case DRIZZLE_TYPE_NEWDATE:
5140
f_val= "0000-00-00";
5141
t_type= DRIZZLE_TIMESTAMP_DATE;
5143
case DRIZZLE_TYPE_DATETIME:
5144
f_val= "0000-00-00 00:00:00";
5145
t_type= DRIZZLE_TIMESTAMP_DATETIME;
5148
/* Shouldn't get here. */
5151
bool save_abort_on_warning= thd->abort_on_warning;
5152
thd->abort_on_warning= true;
5153
make_truncated_value_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
5154
f_val, strlength(f_val), t_type,
5155
alter_info->datetime_field->field_name);
5156
thd->abort_on_warning= save_abort_on_warning;
5160
pthread_mutex_lock(&LOCK_open);
5161
unlink_open_table(thd, name_lock, false);
5162
pthread_mutex_unlock(&LOCK_open);
5166
err_with_placeholders:
5168
An error happened while we were holding exclusive name-lock on table
5169
being altered. To be safe under LOCK TABLES we should remove placeholders
5170
from list of open tables list and table cache.
5172
unlink_open_table(thd, table, false);
5174
unlink_open_table(thd, name_lock, false);
5175
VOID(pthread_mutex_unlock(&LOCK_open));
5178
/* mysql_alter_table */
5181
copy_data_between_tables(TABLE *from,TABLE *to,
5182
List<Create_field> &create,
5184
uint order_num, ORDER *order,
5187
enum enum_enable_or_disable keys_onoff,
5188
bool error_if_not_empty)
5191
Copy_field *copy,*copy_end;
5192
ulong found_count,delete_count;
5193
THD *thd= current_thd;
5195
SORT_FIELD *sortorder;
5199
List<Item> all_fields;
5200
ha_rows examined_rows;
5201
bool auto_increment_field_copied= 0;
5202
ulong save_sql_mode;
5203
uint64_t prev_insert_id;
5206
Turn off recovery logging since rollback of an alter table is to
5207
delete the new table so there is no need to log the changes to it.
5209
This needs to be done before external_lock
5211
error= ha_enable_transaction(thd, false);
5215
if (!(copy= new Copy_field[to->s->fields]))
5216
return(-1); /* purecov: inspected */
5218
if (to->file->ha_external_lock(thd, F_WRLCK))
5221
/* We need external lock before we can disable/enable keys */
5222
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
5224
/* We can abort alter table for any table type */
5225
thd->abort_on_warning= !ignore;
5227
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
5228
to->file->ha_start_bulk_insert(from->file->stats.records);
5230
save_sql_mode= thd->variables.sql_mode;
5232
List_iterator<Create_field> it(create);
5235
for (Field **ptr=to->field ; *ptr ; ptr++)
5240
if (*ptr == to->next_number_field)
5242
auto_increment_field_copied= true;
5244
If we are going to copy contents of one auto_increment column to
5245
another auto_increment column it is sensible to preserve zeroes.
5246
This condition also covers case when we are don't actually alter
5247
auto_increment column.
5249
if (def->field == from->found_next_number_field)
5250
thd->variables.sql_mode|= MODE_NO_AUTO_VALUE_ON_ZERO;
5252
(copy_end++)->set(*ptr,def->field,0);
5257
found_count=delete_count=0;
5261
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
5263
char warn_buff[MYSQL_ERRMSG_SIZE];
5264
snprintf(warn_buff, sizeof(warn_buff),
5265
"ORDER BY ignored as there is a user-defined clustered index"
5266
" in the table '%-.192s'", from->s->table_name.str);
5267
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
5272
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
5273
MYF(MY_FAE | MY_ZEROFILL));
5274
memset((char *) &tables, 0, sizeof(tables));
5276
tables.alias= tables.table_name= from->s->table_name.str;
5277
tables.db= from->s->db.str;
5280
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
5281
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
5282
&tables, fields, all_fields, order) ||
5283
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
5284
(from->sort.found_records= filesort(thd, from, sortorder, length,
5285
(SQL_SELECT *) 0, HA_POS_ERROR,
5286
1, &examined_rows)) ==
5292
/* Tell handler that we have values for all columns in the to table */
5293
to->use_all_columns();
5294
init_read_record(&info, thd, from, (SQL_SELECT *) 0, 1,1);
5296
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
5298
restore_record(to, s->default_values); // Create empty record
5299
while (!(error=info.read_record(&info)))
5303
thd->send_kill_message();
5308
/* Return error if source table isn't empty. */
5309
if (error_if_not_empty)
5314
if (to->next_number_field)
5316
if (auto_increment_field_copied)
5317
to->auto_increment_field_not_null= true;
5319
to->next_number_field->reset();
5322
for (Copy_field *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
5324
copy_ptr->do_copy(copy_ptr);
5326
prev_insert_id= to->file->next_insert_id;
5327
error=to->file->ha_write_row(to->record[0]);
5328
to->auto_increment_field_not_null= false;
5332
to->file->is_fatal_error(error, HA_CHECK_DUP))
5334
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
5336
uint key_nr= to->file->get_dup_key(error);
5337
if ((int) key_nr >= 0)
5339
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
5341
(to->key_info[0].key_part[0].field->flags &
5342
AUTO_INCREMENT_FLAG))
5343
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
5344
to->file->print_keydup_error(key_nr, err_msg);
5349
to->file->print_error(error,MYF(0));
5352
to->file->restore_auto_increment(prev_insert_id);
5358
end_read_record(&info);
5359
free_io_cache(from);
5360
delete [] copy; // This is never 0
5362
if (to->file->ha_end_bulk_insert() && error <= 0)
5364
to->file->print_error(my_errno,MYF(0));
5367
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
5369
if (ha_enable_transaction(thd, true))
5376
Ensure that the new table is saved properly to disk so that we
5379
if (ha_autocommit_or_rollback(thd, 0))
5381
if (end_active_trans(thd))
5385
thd->variables.sql_mode= save_sql_mode;
5386
thd->abort_on_warning= 0;
5387
free_io_cache(from);
5388
*copied= found_count;
5389
*deleted=delete_count;
5390
to->file->ha_release_auto_increment();
5391
if (to->file->ha_external_lock(thd,F_UNLCK))
5393
return(error > 0 ? -1 : 0);
5398
Recreates tables by calling mysql_alter_table().
5401
mysql_recreate_table()
5403
tables Tables to recreate
5406
Like mysql_alter_table().
5408
bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list)
5410
HA_CREATE_INFO create_info;
5411
Alter_info alter_info;
5413
assert(!table_list->next_global);
5415
table_list->table has been closed and freed. Do not reference
5416
uninitialized data. open_tables() could fail.
5418
table_list->table= NULL;
5420
memset((char*) &create_info, 0, sizeof(create_info));
5421
create_info.row_type=ROW_TYPE_NOT_USED;
5422
create_info.default_table_charset=default_charset_info;
5423
/* Force alter table to recreate table */
5424
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
5425
return(mysql_alter_table(thd, NullS, NullS, &create_info,
5426
table_list, &alter_info, 0,
5431
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
5432
HA_CHECK_OPT *check_opt)
5435
List<Item> field_list;
5437
Protocol *protocol= thd->protocol;
5439
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
5440
item->maybe_null= 1;
5441
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
5442
MY_INT64_NUM_DECIMAL_DIGITS));
5443
item->maybe_null= 1;
5444
if (protocol->send_fields(&field_list,
5445
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
5448
/* Open one table after the other to keep lock time as short as possible. */
5449
for (table= tables; table; table= table->next_local)
5451
char table_name[NAME_LEN*2+2];
5454
strxmov(table_name, table->db ,".", table->table_name, NullS);
5456
t= table->table= open_n_lock_single_table(thd, table, TL_READ);
5457
thd->clear_error(); // these errors shouldn't get client
5459
protocol->prepare_for_resend();
5460
protocol->store(table_name, system_charset_info);
5464
/* Table didn't exist */
5465
protocol->store_null();
5470
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
5471
!(check_opt->flags & T_EXTEND))
5472
protocol->store((uint64_t)t->file->checksum());
5473
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
5474
(check_opt->flags & T_QUICK))
5475
protocol->store_null();
5478
/* calculating table's checksum */
5480
uchar null_mask=256 - (1 << t->s->last_null_bit_pos);
5482
t->use_all_columns();
5484
if (t->file->ha_rnd_init(1))
5485
protocol->store_null();
5490
ha_checksum row_crc= 0;
5491
int error= t->file->rnd_next(t->record[0]);
5492
if (unlikely(error))
5494
if (error == HA_ERR_RECORD_DELETED)
5498
if (t->s->null_bytes)
5500
/* fix undefined null bits */
5501
t->record[0][t->s->null_bytes-1] |= null_mask;
5502
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
5503
t->record[0][0] |= 1;
5505
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
5508
for (uint i= 0; i < t->s->fields; i++ )
5510
Field *f= t->field[i];
5511
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
5512
(f->type() == DRIZZLE_TYPE_VARCHAR))
5516
row_crc= my_checksum(row_crc, (uchar*) tmp.ptr(), tmp.length());
5519
row_crc= my_checksum(row_crc, f->ptr,
5525
protocol->store((uint64_t)crc);
5526
t->file->ha_rnd_end();
5530
close_thread_tables(thd);
5531
table->table=0; // For query cache
5533
if (protocol->write())
5541
close_thread_tables(thd); // Shouldn't be needed
5547
static bool check_engine(THD *thd, const char *table_name,
5548
HA_CREATE_INFO *create_info)
5550
handlerton **new_engine= &create_info->db_type;
5551
handlerton *req_engine= *new_engine;
5552
bool no_substitution= 1;
5553
if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
5554
no_substitution, 1)))
2219
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2221
thr_lock_type lock_type = TL_READ_NO_INSERT;
2223
return(admin_table(session, tables, check_opt,
2224
"analyze", lock_type, true,
2225
&Cursor::ha_analyze));
2229
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2231
thr_lock_type lock_type = TL_READ_NO_INSERT;
2233
return(admin_table(session, tables, check_opt,
2236
&Cursor::ha_check));
2239
} /* namespace drizzled */
5557
if (req_engine && req_engine != *new_engine)
5559
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
5560
ER_WARN_USING_OTHER_HANDLER,
5561
ER(ER_WARN_USING_OTHER_HANDLER),
5562
ha_resolve_storage_engine_name(*new_engine),
5565
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
5566
ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
5568
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
5570
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
5571
ha_resolve_storage_engine_name(*new_engine), "TEMPORARY");
5575
*new_engine= myisam_hton;