1429
bool create_table_no_lock(Session *session,
1430
const identifier::Table &identifier,
1711
bool mysql_create_table_no_lock(Session *session,
1712
const char *db, const char *table_name,
1431
1713
HA_CREATE_INFO *create_info,
1432
message::Table &table_proto,
1433
AlterInfo *alter_info,
1714
drizzled::message::Table *table_proto,
1715
Alter_info *alter_info,
1434
1716
bool internal_tmp_table,
1435
uint32_t select_field_count,
1436
bool is_if_not_exists)
1717
uint32_t select_field_count)
1719
char path[FN_REFLEN];
1720
uint32_t path_length;
1438
1721
uint db_options, key_count;
1439
KeyInfo *key_info_buffer;
1722
KEY *key_info_buffer;
1440
1724
bool error= true;
1442
1725
/* Check for duplicate fields and check type of table to create */
1443
if (not alter_info->create_list.elements)
1726
if (!alter_info->create_list.elements)
1445
1728
my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
1449
assert(identifier.getTableName() == table_proto.name());
1732
assert(strcmp(table_name,table_proto->name().c_str())==0);
1733
if (check_engine(session, table_name, create_info))
1450
1735
db_options= create_info->table_options;
1452
set_table_default_charset(create_info, identifier.getSchemaName().c_str());
1454
/* Build a Table object to pass down to the engine, and the do the actual create. */
1455
if (not prepare_create_table(session, create_info, table_proto, alter_info,
1458
&key_info_buffer, &key_count,
1459
select_field_count))
1461
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* CREATE TABLE (some confussion on naming, double check) */
1462
error= locked_create_event(session,
1469
db_options, key_count,
1736
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1737
db_options|=HA_OPTION_PACK_RECORD;
1738
if (!(file= get_new_handler((TableShare*) 0, session->mem_root,
1739
create_info->db_type)))
1741
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
1745
set_table_default_charset(create_info, (char*) db);
1747
if (mysql_prepare_create_table(session, create_info, alter_info,
1750
&key_info_buffer, &key_count,
1751
select_field_count))
1754
/* Check if table exists */
1755
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1757
path_length= build_tmptable_filename(session, path, sizeof(path));
1762
/* check if the table name contains FN_DEVCHAR when defined */
1763
if (strchr(table_name, FN_DEVCHAR))
1765
my_error(ER_WRONG_TABLE_NAME, MYF(0), table_name);
1769
path_length= build_table_filename(path, sizeof(path), db, table_name, internal_tmp_table);
1773
* If the DATA DIRECTORY or INDEX DIRECTORY options are specified in the
1774
* create table statement, check whether the storage engine supports those
1775
* options. If not, return an appropriate error.
1777
if (create_info->data_file_name &&
1778
! create_info->db_type->check_flag(HTON_BIT_DATA_DIR))
1780
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
1781
create_info->db_type->getName().c_str(),
1786
if (create_info->index_file_name &&
1787
! create_info->db_type->check_flag(HTON_BIT_INDEX_DIR))
1789
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
1790
create_info->db_type->getName().c_str(),
1795
/* Check if table already exists */
1796
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
1797
session->find_temporary_table(db, table_name))
1799
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1801
create_info->table_existed= 1; // Mark that table existed
1802
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1803
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1808
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1812
pthread_mutex_lock(&LOCK_open); /* CREATE TABLE (some confussion on naming, double check) */
1813
if (!internal_tmp_table && !(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1815
if (StorageEngine::getTableProto(path, NULL)==EEXIST)
1817
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1820
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1821
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1823
create_info->table_existed= 1; // Mark that table existed
1826
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1828
goto unlock_and_end;
1831
We don't assert here, but check the result, because the table could be
1832
in the table definition cache and in the same time the .frm could be
1833
missing from the disk, in case of manual intervention which deletes
1834
the .frm file. The user has to use FLUSH TABLES; to clear the cache.
1835
Then she could create the table. This case is pretty obscure and
1836
therefore we don't introduce a new error message only for it.
1838
if (TableShare::getShare(db, table_name))
1840
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
1841
goto unlock_and_end;
1846
Check that table with given name does not already
1847
exist in any storage engine. In such a case it should
1848
be discovered and the error ER_TABLE_EXISTS_ERROR be returned
1849
unless user specified CREATE TABLE IF EXISTS
1850
The LOCK_open mutex has been locked to make sure no
1851
one else is attempting to discover the table. Since
1852
it's not on disk as a frm file, no one could be using it!
1854
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1856
bool create_if_not_exists =
1857
create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS;
1859
char table_path[FN_REFLEN];
1860
uint32_t table_path_length;
1862
table_path_length= build_table_filename(table_path, sizeof(table_path),
1863
db, table_name, false);
1865
int retcode= StorageEngine::getTableProto(table_path, NULL);
1869
/* Normal case, no table exists. we can go and create it */
1872
if (create_if_not_exists)
1875
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1876
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1878
create_info->table_existed= 1; // Mark that table existed
1879
goto unlock_and_end;
1881
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1882
goto unlock_and_end;
1884
my_error(retcode, MYF(0),table_name);
1885
goto unlock_and_end;
1889
session->set_proc_info("creating table");
1890
create_info->table_existed= 0; // Mark that table is created
1892
#ifdef HAVE_READLINK
1893
if (test_if_data_home_dir(create_info->data_file_name))
1895
my_error(ER_WRONG_ARGUMENTS, MYF(0), "DATA DIRECTORY");
1896
goto unlock_and_end;
1898
if (test_if_data_home_dir(create_info->index_file_name))
1900
my_error(ER_WRONG_ARGUMENTS, MYF(0), "INDEX DIRECTORY");
1901
goto unlock_and_end;
1905
#endif /* HAVE_READLINK */
1907
if (create_info->data_file_name)
1908
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
1909
"DATA DIRECTORY option ignored");
1910
if (create_info->index_file_name)
1911
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
1912
"INDEX DIRECTORY option ignored");
1913
create_info->data_file_name= create_info->index_file_name= 0;
1915
create_info->table_options=db_options;
1917
if (rea_create_table(session, path, db, table_name,
1919
create_info, alter_info->create_list,
1920
key_count, key_info_buffer))
1921
goto unlock_and_end;
1923
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1925
/* Open table and put in temporary table list */
1926
if (!(session->open_temporary_table(path, db, table_name, 1, OTM_OPEN)))
1928
(void) session->rm_temporary_table(create_info->db_type, path);
1929
goto unlock_and_end;
1934
Don't write statement if:
1935
- It is an internal temporary table,
1936
- Row-based logging is used and it we are creating a temporary table, or
1937
- The binary log is not open.
1938
Otherwise, the statement shall be binlogged.
1940
if (!internal_tmp_table &&
1941
((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1942
write_bin_log(session, true, session->query, session->query_length);
1945
pthread_mutex_unlock(&LOCK_open);
1473
1948
session->set_proc_info("After create");
1479
@note the following two methods implement create [temporary] table.
1955
Database locking aware wrapper for mysql_create_table_no_lock(),
1481
static bool drizzle_create_table(Session *session,
1482
const identifier::Table &identifier,
1483
HA_CREATE_INFO *create_info,
1484
message::Table &table_proto,
1485
AlterInfo *alter_info,
1486
bool internal_tmp_table,
1487
uint32_t select_field_count,
1488
bool is_if_not_exists)
1958
bool mysql_create_table(Session *session, const char *db, const char *table_name,
1959
HA_CREATE_INFO *create_info,
1960
drizzled::message::Table *table_proto,
1961
Alter_info *alter_info,
1962
bool internal_tmp_table,
1963
uint32_t select_field_count)
1490
1965
Table *name_lock= NULL;
1493
if (session->lock_table_name_if_not_cached(identifier, &name_lock))
1497
else if (name_lock == NULL)
1499
if (is_if_not_exists)
1501
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1502
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1503
identifier.getTableName().c_str());
1504
create_info->table_existed= 1;
1509
my_error(ER_TABLE_EXISTS_ERROR, identifier);
1968
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
1970
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
1515
result= create_table_no_lock(session,
1975
if (name_lock == NULL)
1977
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
1979
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1980
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1982
create_info->table_existed= 1;
1987
my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
1994
result= mysql_create_table_no_lock(session, db, table_name, create_info,
1998
select_field_count);
1527
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* Lock for removing name_lock during table create */
2003
pthread_mutex_lock(&LOCK_open); /* Lock for removing name_lock during table create */
1528
2004
session->unlink_open_table(name_lock);
2005
pthread_mutex_unlock(&LOCK_open);
1531
2008
return(result);
2086
bool create_like_table(Session* session,
2087
identifier::Table::const_reference destination_identifier,
2088
identifier::Table::const_reference source_identifier,
2089
message::Table &create_table_proto,
2090
bool is_if_not_exists,
2614
bool mysql_create_like_table(Session* session, TableList* table, TableList* src_table,
2615
HA_CREATE_INFO *create_info)
2617
Table *name_lock= 0;
2618
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
2619
uint32_t dst_path_length;
2620
char *db= table->db;
2621
char *table_name= table->table_name;
2093
2623
bool res= true;
2094
bool table_exists= false;
2625
drizzled::message::Table src_proto;
2628
By opening source table we guarantee that it exists and no concurrent
2629
DDL operation will mess with it. Later we also take an exclusive
2630
name-lock on target table name, which makes copying of .frm file,
2631
call to ha_create_table() and binlogging atomic against concurrent DML
2632
and DDL operations on target table. Thus by holding both these "locks"
2633
we ensure that our statement is properly isolated from all concurrent
2634
operations which matter.
2636
if (session->open_tables_from_list(&src_table, ¬_used))
2639
strncpy(src_path, src_table->table->s->path.str, sizeof(src_path));
2097
2642
Check that destination tables does not exist. Note that its name
2098
2643
was already checked when it was added to the table list.
2100
For temporary tables we don't aim to grab locks.
2102
if (destination_identifier.isTmp())
2104
if (session->find_temporary_table(destination_identifier))
2110
bool was_created= create_table_wrapper(*session,
2112
destination_identifier,
2115
if (not was_created) // This is pretty paranoid, but we assume something might not clean up after itself
2117
(void) session->rm_temporary_table(destination_identifier, true);
2119
else if (not session->open_temporary_table(destination_identifier))
2121
// We created, but we can't open... also, a hack.
2122
(void) session->rm_temporary_table(destination_identifier, true);
2130
else // Standard table which will require locks.
2132
Table *name_lock= 0;
2134
if (session->lock_table_name_if_not_cached(destination_identifier, &name_lock))
2138
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2139
session->unlink_open_table(name_lock);
2149
else if (plugin::StorageEngine::doesTableExist(*session, destination_identifier))
2153
else // Otherwise we create the table
2157
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* We lock for CREATE TABLE LIKE to copy table definition */
2158
was_created= create_table_wrapper(*session, create_table_proto, destination_identifier,
2159
source_identifier, is_engine_set);
2162
// So we blew the creation of the table, and we scramble to clean up
2163
// anything that might have been created (read... it is a hack)
2164
if (not was_created)
2166
plugin::StorageEngine::dropTable(*session, destination_identifier);
2645
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2647
if (session->find_temporary_table(db, table_name))
2649
dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
2653
if (session->lock_table_name_if_not_cached(db, table_name, &name_lock))
2657
dst_path_length= build_table_filename(dst_path, sizeof(dst_path),
2658
db, table_name, false);
2659
if (StorageEngine::getTableProto(dst_path, NULL)==EEXIST)
2664
Create a new table by copying from source table
2666
Altough exclusive name-lock on target table protects us from concurrent
2667
DML and DDL operations on it we still want to wrap .FRM creation and call
2668
to ha_create_table() in critical section protected by LOCK_open in order
2669
to provide minimal atomicity against operations which disregard name-locks,
2670
like I_S implementation, for example. This is a temporary and should not
2671
be copied. Instead we should fix our code to always honor name-locks.
2673
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2674
during the call to ha_create_table(). See bug #28614 for more info.
2676
pthread_mutex_lock(&LOCK_open); /* We lock for CREATE TABLE LIKE to copy table definition */
2679
int protoerr= EEXIST;
2681
if (src_table->schema_table)
2683
if (mysql_create_like_schema_frm(session, src_table, create_info,
2686
pthread_mutex_unlock(&LOCK_open);
2692
protoerr= StorageEngine::getTableProto(src_path, &src_proto);
2695
string dst_proto_path(dst_path);
2696
string file_ext = ".dfe";
2698
dst_proto_path.append(file_ext);
2700
if (protoerr == EEXIST)
2702
StorageEngine* engine= ha_resolve_by_name(session,
2703
src_proto.engine().name());
2705
if (engine->check_flag(HTON_BIT_HAS_DATA_DICTIONARY) == false)
2706
protoerr= drizzle_write_proto_file(dst_proto_path.c_str(), &src_proto);
2713
if (my_errno == ENOENT)
2714
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2716
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
2717
pthread_mutex_unlock(&LOCK_open);
2723
As mysql_truncate don't work on a new table at this stage of
2724
creation, instead create the table directly (for both normal
2725
and temporary tables).
2728
err= ha_create_table(session, dst_path, db, table_name, create_info, 1,
2730
pthread_mutex_unlock(&LOCK_open);
2732
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2734
if (err || !session->open_temporary_table(dst_path, db, table_name, 1, OTM_OPEN))
2736
(void) session->rm_temporary_table(create_info->db_type, dst_path);
2737
goto err; /* purecov: inspected */
2742
(void) quick_rm_table(create_info->db_type, db,
2743
table_name, false); /* purecov: inspected */
2744
goto err; /* purecov: inspected */
2748
We have to write the query before we unlock the tables.
2752
Since temporary tables are not replicated under row-based
2753
replication, CREATE TABLE ... LIKE ... needs special
2754
treatement. We have four cases to consider, according to the
2755
following decision table:
2757
==== ========= ========= ==============================
2758
Case Target Source Write to binary log
2759
==== ========= ========= ==============================
2760
1 normal normal Original statement
2761
2 normal temporary Generated statement
2762
3 temporary normal Nothing
2763
4 temporary temporary Nothing
2764
==== ========= ========= ==============================
2766
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
2768
if (src_table->table->s->tmp_table) // Case 2
2771
String query(buf, sizeof(buf), system_charset_info);
2772
query.length(0); // Have to zero it since constructor doesn't
2776
Here we open the destination table, on which we already have
2777
name-lock. This is needed for store_create_info() to work.
2778
The table will be closed by unlink_open_table() at the end
2781
table->table= name_lock;
2782
pthread_mutex_lock(&LOCK_open); /* Open new table we have just acquired */
2783
if (session->reopen_name_locked_table(table, false))
2785
pthread_mutex_unlock(&LOCK_open);
2788
pthread_mutex_unlock(&LOCK_open);
2790
int result= store_create_info(table, &query, create_info);
2792
assert(result == 0); // store_create_info() always return 0
2793
write_bin_log(session, true, query.ptr(), query.length());
2796
write_bin_log(session, true, session->query, session->query_length);
2804
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
2806
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2807
snprintf(warn_buff, sizeof(warn_buff),
2808
ER(ER_TABLE_EXISTS_ERROR), table_name);
2809
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2810
ER_TABLE_EXISTS_ERROR,warn_buff);
2814
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
2819
pthread_mutex_lock(&LOCK_open); /* unlink open tables for create table like*/
2820
session->unlink_open_table(name_lock);
2821
pthread_mutex_unlock(&LOCK_open);
2827
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2829
thr_lock_type lock_type = TL_READ_NO_INSERT;
2831
return(mysql_admin_table(session, tables, check_opt,
2832
"analyze", lock_type, 1, 0, 0, 0,
2833
&handler::ha_analyze));
2837
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2839
thr_lock_type lock_type = TL_READ_NO_INSERT;
2841
return(mysql_admin_table(session, tables, check_opt,
2843
0, 0, HA_OPEN_FOR_REPAIR, 0,
2844
&handler::ha_check));
2848
/* table_list should contain just one table */
2850
mysql_discard_or_import_tablespace(Session *session,
2851
TableList *table_list,
2852
enum tablespace_op_type tablespace_op)
2859
Note that DISCARD/IMPORT TABLESPACE always is the only operation in an
2863
session->set_proc_info("discard_or_import_tablespace");
2865
discard= test(tablespace_op == DISCARD_TABLESPACE);
2868
We set this flag so that ha_innobase::open and ::external_lock() do
2869
not complain when we lock the table
2871
session->tablespace_op= true;
2872
if (!(table= session->openTableLock(table_list, TL_WRITE)))
2874
session->tablespace_op= false;
2878
error= table->file->ha_discard_or_import_tablespace(discard);
2880
session->set_proc_info("end");
2885
/* The ALTER Table is always in its own transaction */
2886
error = ha_autocommit_or_rollback(session, 0);
2887
if (! session->endActiveTransaction())
2891
write_bin_log(session, false, session->query, session->query_length);
2894
ha_autocommit_or_rollback(session, error);
2895
session->tablespace_op=false;
2903
table->file->print_error(error, MYF(0));
2910
Manages enabling/disabling of indexes for ALTER Table
2913
alter_table_manage_keys()
2915
indexes_were_disabled Whether the indexes of the from table
2917
keys_onoff ENABLE | DISABLE | LEAVE_AS_IS
2925
bool alter_table_manage_keys(Table *table, int indexes_were_disabled,
2926
enum enum_enable_or_disable keys_onoff)
2929
switch (keys_onoff) {
2931
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
2934
if (!indexes_were_disabled)
2936
/* fall-through: disabled indexes */
2938
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
2941
if (error == HA_ERR_WRONG_COMMAND)
2943
push_warning_printf(current_session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2944
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
2945
table->s->table_name.str);
2948
table->file->print_error(error, MYF(0));
2954
create_temporary_table(Session *session,
2958
HA_CREATE_INFO *create_info,
2959
Alter_info *alter_info,
2963
char index_file[FN_REFLEN], data_file[FN_REFLEN];
2964
StorageEngine *old_db_type, *new_db_type;
2965
old_db_type= table->s->db_type();
2966
new_db_type= create_info->db_type;
2968
Handling of symlinked tables:
2970
Create new data file and index file on the same disk as the
2971
old data and index files.
2973
Rename new data file over old data file and new index file over
2975
Symlinks are not changed.
2978
Create new data file and index file on the same disk as the
2979
old data and index files. Create also symlinks to point at
2982
At end, rename intermediate tables, and symlinks to intermediate
2983
table, to final table name.
2984
Remove old table and old symlinks
2986
If rename is made to another database:
2987
Create new tables in new database.
2989
Remove old table and symlinks.
2991
if (db_changed) // Ignore symlink if db changed
2993
if (create_info->index_file_name)
2995
/* Fix index_file_name to have 'tmp_name' as basename */
2996
strcpy(index_file, tmp_name);
2997
create_info->index_file_name=fn_same(index_file,
2998
create_info->index_file_name,
3001
if (create_info->data_file_name)
3003
/* Fix data_file_name to have 'tmp_name' as basename */
3004
strcpy(data_file, tmp_name);
3005
create_info->data_file_name=fn_same(data_file,
3006
create_info->data_file_name,
3011
create_info->data_file_name=create_info->index_file_name=0;
3014
Create a table with a temporary name.
3015
We don't log the statement, it will be logged later.
3017
drizzled::message::Table table_proto;
3018
table_proto.set_name(tmp_name);
3019
table_proto.set_type(drizzled::message::Table::TEMPORARY);
3021
drizzled::message::Table::StorageEngine *protoengine;
3022
protoengine= table_proto.mutable_engine();
3023
protoengine->set_name(new_db_type->getName());
3025
error= mysql_create_table(session, new_db, tmp_name,
3026
create_info, &table_proto, alter_info, 1, 0);
3033
Prepare column and key definitions for CREATE TABLE in ALTER Table.
3035
This function transforms parse output of ALTER Table - lists of
3036
columns and keys to add, drop or modify into, essentially,
3037
CREATE TABLE definition - a list of columns and keys of the new
3038
table. While doing so, it also performs some (bug not all)
3041
This function is invoked when we know that we're going to
3042
perform ALTER Table via a temporary table -- i.e. fast ALTER Table
3043
is not possible, perhaps because the ALTER statement contains
3044
instructions that require change in table data, not only in
3045
table definition or indexes.
3047
@param[in,out] session thread handle. Used as a memory pool
3048
and source of environment information.
3049
@param[in] table the source table, open and locked
3050
Used as an interface to the storage engine
3051
to acquire additional information about
3053
@param[in,out] create_info A blob with CREATE/ALTER Table
3055
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
3056
Originally create_info was used only in
3057
CREATE TABLE and alter_info only in ALTER Table.
3058
But since ALTER might end-up doing CREATE,
3059
this distinction is gone and we just carry
3060
around two structures.
3063
Fills various create_info members based on information retrieved
3064
from the storage engine.
3065
Sets create_info->varchar if the table has a VARCHAR column.
3066
Prepares alter_info->create_list and alter_info->key_list with
3067
columns and keys of the new table.
3068
@retval true error, out of memory or a semantical error in ALTER
3070
@retval false success
3074
mysql_prepare_alter_table(Session *session, Table *table,
3075
HA_CREATE_INFO *create_info,
3076
Alter_info *alter_info)
3078
/* New column definitions are added here */
3079
List<CreateField> new_create_list;
3080
/* New key definitions are added here */
3081
List<Key> new_key_list;
3082
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
3083
List_iterator<CreateField> def_it(alter_info->create_list);
3084
List_iterator<Alter_column> alter_it(alter_info->alter_list);
3085
List_iterator<Key> key_it(alter_info->key_list);
3086
List_iterator<CreateField> find_it(new_create_list);
3087
List_iterator<CreateField> field_it(new_create_list);
3088
List<Key_part_spec> key_parts;
3089
uint32_t db_create_options= (table->s->db_create_options
3090
& ~(HA_OPTION_PACK_RECORD));
3091
uint32_t used_fields= create_info->used_fields;
3092
KEY *key_info=table->key_info;
3096
create_info->varchar= false;
3097
/* Let new create options override the old ones */
3098
if (!(used_fields & HA_CREATE_USED_MIN_ROWS))
3099
create_info->min_rows= table->s->min_rows;
3100
if (!(used_fields & HA_CREATE_USED_MAX_ROWS))
3101
create_info->max_rows= table->s->max_rows;
3102
if (!(used_fields & HA_CREATE_USED_AVG_ROW_LENGTH))
3103
create_info->avg_row_length= table->s->avg_row_length;
3104
if (!(used_fields & HA_CREATE_USED_BLOCK_SIZE))
3105
create_info->block_size= table->s->block_size;
3106
if (!(used_fields & HA_CREATE_USED_DEFAULT_CHARSET))
3107
create_info->default_table_charset= table->s->table_charset;
3108
if (!(used_fields & HA_CREATE_USED_AUTO) && table->found_next_number_field)
3110
/* Table has an autoincrement, copy value to new table */
3111
table->file->info(HA_STATUS_AUTO);
3112
create_info->auto_increment_value= table->file->stats.auto_increment_value;
3114
if (!(used_fields & HA_CREATE_USED_KEY_BLOCK_SIZE))
3115
create_info->key_block_size= table->s->key_block_size;
3117
table->restoreRecordAsDefault(); // Empty record for DEFAULT
3121
First collect all fields from table which isn't in drop_list
3123
Field **f_ptr,*field;
3124
for (f_ptr=table->field ; (field= *f_ptr) ; f_ptr++)
3126
/* Check if field should be dropped */
3129
while ((drop=drop_it++))
3131
if (drop->type == Alter_drop::COLUMN &&
3132
!my_strcasecmp(system_charset_info,field->field_name, drop->name))
3134
/* Reset auto_increment value if it was dropped */
3135
if (MTYP_TYPENR(field->unireg_check) == Field::NEXT_NUMBER &&
3136
!(used_fields & HA_CREATE_USED_AUTO))
3138
create_info->auto_increment_value=0;
3139
create_info->used_fields|=HA_CREATE_USED_AUTO;
3150
/* Mark that we will read the field */
3151
field->setReadSet();
3153
/* Check if field is changed */
3155
while ((def=def_it++))
3158
!my_strcasecmp(system_charset_info,field->field_name, def->change))
3162
{ // Field is changed
3166
new_create_list.push_back(def);
3173
This field was not dropped and not changed, add it to the list
3176
def= new CreateField(field, field);
3177
new_create_list.push_back(def);
3178
alter_it.rewind(); // Change default if ALTER
3179
Alter_column *alter;
3180
while ((alter=alter_it++))
3182
if (!my_strcasecmp(system_charset_info,field->field_name, alter->name))
3187
if (def->sql_type == DRIZZLE_TYPE_BLOB)
3189
my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
3192
if ((def->def=alter->def)) // Use new default
3193
def->flags&= ~NO_DEFAULT_VALUE_FLAG;
3195
def->flags|= NO_DEFAULT_VALUE_FLAG;
3201
while ((def=def_it++)) // Add new columns
3203
if (def->change && ! def->field)
3205
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table->s->table_name.str);
3209
Check that the DATE/DATETIME not null field we are going to add is
3210
either has a default value or the '0000-00-00' is allowed by the
3212
If the '0000-00-00' value isn't allowed then raise the error_if_not_empty
3213
flag to allow ALTER Table only if the table to be altered is empty.
3215
if ((def->sql_type == DRIZZLE_TYPE_DATE ||
3216
def->sql_type == DRIZZLE_TYPE_DATETIME) &&
3217
!alter_info->datetime_field &&
3218
!(~def->flags & (NO_DEFAULT_VALUE_FLAG | NOT_NULL_FLAG)) &&
3219
session->variables.sql_mode & MODE_NO_ZERO_DATE)
3221
alter_info->datetime_field= def;
3222
alter_info->error_if_not_empty= true;
3225
new_create_list.push_back(def);
3226
else if (def->after == first_keyword)
3227
new_create_list.push_front(def);
3232
while ((find=find_it++)) // Add new columns
3234
if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
3239
my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
3242
find_it.after(def); // Put element after this
3244
XXX: hack for Bug#28427.
3245
If column order has changed, force OFFLINE ALTER Table
3246
without querying engine capabilities. If we ever have an
3247
engine that supports online ALTER Table CHANGE COLUMN
3248
<name> AFTER <name1> (Falcon?), this fix will effectively
3249
disable the capability.
3250
TODO: detect the situation in compare_tables, behave based
3251
on engine capabilities.
3253
if (alter_info->build_method == HA_BUILD_ONLINE)
3255
my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
3258
alter_info->build_method= HA_BUILD_OFFLINE;
3261
if (alter_info->alter_list.elements)
3263
my_error(ER_BAD_FIELD_ERROR, MYF(0),
3264
alter_info->alter_list.head()->name, table->s->table_name.str);
3267
if (!new_create_list.elements)
3269
my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
3275
Collect all keys which isn't in drop list. Add only those
3276
for which some fields exists.
3279
for (uint32_t i=0 ; i < table->s->keys ; i++,key_info++)
3281
char *key_name= key_info->name;
3284
while ((drop=drop_it++))
3286
if (drop->type == Alter_drop::KEY &&
3287
!my_strcasecmp(system_charset_info,key_name, drop->name))
3296
KEY_PART_INFO *key_part= key_info->key_part;
3298
for (uint32_t j=0 ; j < key_info->key_parts ; j++,key_part++)
3300
if (!key_part->field)
3301
continue; // Wrong field (from UNIREG)
3302
const char *key_part_name=key_part->field->field_name;
3303
CreateField *cfield;
3305
while ((cfield=field_it++))
3309
if (!my_strcasecmp(system_charset_info, key_part_name,
3313
else if (!my_strcasecmp(system_charset_info,
3314
key_part_name, cfield->field_name))
3318
continue; // Field is removed
3319
uint32_t key_part_length=key_part->length;
3320
if (cfield->field) // Not new field
3323
If the field can't have only a part used in a key according to its
3324
new type, or should not be used partially according to its
3325
previous type, or the field length is less than the key part
3326
length, unset the key part length.
3328
We also unset the key part length if it is the same as the
3329
old field's length, so the whole new field will be used.
3331
BLOBs may have cfield->length == 0, which is why we test it before
3332
checking whether cfield->length < key_part_length (in chars).
3334
if (!Field::type_can_have_key_part(cfield->field->type()) ||
3335
!Field::type_can_have_key_part(cfield->sql_type) ||
3336
(cfield->field->field_length == key_part_length &&
3337
!f_is_blob(key_part->key_type)) ||
3338
(cfield->length && (cfield->length < key_part_length /
3339
key_part->field->charset()->mbmaxlen)))
3340
key_part_length= 0; // Use whole field
3342
key_part_length /= key_part->field->charset()->mbmaxlen;
3343
key_parts.push_back(new Key_part_spec(cfield->field_name,
3344
strlen(cfield->field_name),
3347
if (key_parts.elements)
3349
KEY_CREATE_INFO key_create_info;
3351
enum Key::Keytype key_type;
3352
memset(&key_create_info, 0, sizeof(key_create_info));
3354
key_create_info.algorithm= key_info->algorithm;
3355
if (key_info->flags & HA_USES_BLOCK_SIZE)
3356
key_create_info.block_size= key_info->block_size;
3357
if (key_info->flags & HA_USES_COMMENT)
3358
key_create_info.comment= key_info->comment;
3360
if (key_info->flags & HA_NOSAME)
3362
if (is_primary_key_name(key_name))
3363
key_type= Key::PRIMARY;
3365
key_type= Key::UNIQUE;
3368
key_type= Key::MULTIPLE;
3370
key= new Key(key_type, key_name, strlen(key_name),
3372
test(key_info->flags & HA_GENERATED_KEY),
3374
new_key_list.push_back(key);
3379
while ((key=key_it++)) // Add new keys
3381
if (key->type == Key::FOREIGN_KEY &&
3382
((Foreign_key *)key)->validate(new_create_list))
3384
if (key->type != Key::FOREIGN_KEY)
3385
new_key_list.push_back(key);
3386
if (key->name.str && is_primary_key_name(key->name.str))
3388
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name.str);
3394
if (alter_info->drop_list.elements)
3396
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
3397
alter_info->drop_list.head()->name);
3400
if (alter_info->alter_list.elements)
3402
my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
3403
alter_info->alter_list.head()->name);
3407
if (!create_info->comment.str)
3409
create_info->comment.str= table->s->comment.str;
3410
create_info->comment.length= table->s->comment.length;
3413
table->file->update_create_info(create_info);
3414
if ((create_info->table_options &
3415
(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS)) ||
3416
(used_fields & HA_CREATE_USED_PACK_KEYS))
3417
db_create_options&= ~(HA_OPTION_PACK_KEYS | HA_OPTION_NO_PACK_KEYS);
3418
if (create_info->table_options &
3419
(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM))
3420
db_create_options&= ~(HA_OPTION_CHECKSUM | HA_OPTION_NO_CHECKSUM);
3421
create_info->table_options|= db_create_options;
3423
if (table->s->tmp_table)
3424
create_info->options|=HA_LEX_CREATE_TMP_TABLE;
3427
alter_info->create_list.swap(new_create_list);
3428
alter_info->key_list.swap(new_key_list);
3439
session Thread handle
3440
new_db If there is a RENAME clause
3441
new_name If there is a RENAME clause
3442
create_info Information from the parsing phase about new
3444
table_list The table to change.
3445
alter_info Lists of fields, keys to be changed, added
3447
order_num How many order_st BY fields has been specified.
3448
order List of fields to order_st BY.
3449
ignore Whether we have ALTER IGNORE Table
3452
This is a veery long function and is everything but the kitchen sink :)
3453
It is used to alter a table and not only by ALTER Table but also
3454
CREATE|DROP INDEX are mapped on this function.
3456
When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
3457
or both, then this function short cuts its operation by renaming
3458
the table and/or enabling/disabling the keys. In this case, the FRM is
3459
not changed, directly by mysql_alter_table. However, if there is a
3460
RENAME + change of a field, or an index, the short cut is not used.
3461
See how `create_list` is used to generate the new FRM regarding the
3462
structure of the fields. The same is done for the indices of the table.
3464
Important is the fact, that this function tries to do as little work as
3465
possible, by finding out whether a intermediate table is needed to copy
3466
data into and when finishing the altering to use it as the original table.
3467
For this reason the function compare_tables() is called, which decides
3468
based on all kind of data how similar are the new and the original
3476
bool mysql_alter_table(Session *session,
3479
HA_CREATE_INFO *create_info,
3480
TableList *table_list,
3481
Alter_info *alter_info,
3487
Table *new_table= NULL;
3488
Table *name_lock= NULL;
3489
string new_name_str;
3493
char new_name_buff[FN_REFLEN];
3494
char new_alias_buff[FN_REFLEN];
3497
const char *new_alias;
3498
char path[FN_REFLEN];
3501
StorageEngine *old_db_type;
3502
StorageEngine *new_db_type;
3503
StorageEngine *save_old_db_type;
3506
new_name_buff[0]= '\0';
3508
if (table_list && table_list->schema_table)
3510
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
3514
session->set_proc_info("init");
3517
Assign variables table_name, new_name, db, new_db, path
3518
to simplify further comparisons: we want to see if it's a RENAME
3519
later just by comparing the pointers, avoiding the need for strcmp.
3521
table_name= table_list->table_name;
3523
if (! new_db || ! my_strcasecmp(table_alias_charset, new_db, db))
3526
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
3528
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
3529
return mysql_discard_or_import_tablespace(session, table_list, alter_info->tablespace_op);
3532
build_table_filename(path, sizeof(path), db, table_name, false);
3535
oss << drizzle_data_home << "/" << db << "/" << table_name;
3537
(void) unpack_filename(new_name_buff, oss.str().c_str());
3540
If this is just a rename of a view, short cut to the
3541
following scenario: 1) lock LOCK_open 2) do a RENAME
3542
2) unlock LOCK_open.
3543
This is a copy-paste added to make sure
3544
ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
3545
as an independent branch in mysql_execute_command. The need
3546
for a copy-paste arose because the main code flow of ALTER Table
3547
... RENAME tries to use openTableLock, which does not work for views
3548
(openTableLock was never modified to merge table lists of child tables
3549
into the main table list, like open_tables does).
3550
This code is wrong and will be removed, please do not copy.
3553
if (!(table= session->openTableLock(table_list, TL_WRITE_ALLOW_READ)))
3556
table->use_all_columns();
3558
/* Check that we are not trying to rename to an existing table */
3561
strcpy(new_name_buff, new_name);
3562
strcpy(new_alias_buff, new_name);
3563
new_alias= new_alias_buff;
3565
my_casedn_str(files_charset_info, new_name_buff);
3566
new_alias= new_name; // Create lower case table name
3567
my_casedn_str(files_charset_info, new_name);
3570
! my_strcasecmp(table_alias_charset, new_name_buff, table_name))
3573
Source and destination table names are equal: make later check
3576
new_alias= new_name= table_name;
3580
if (table->s->tmp_table != NO_TMP_TABLE)
3582
if (session->find_temporary_table(new_db, new_name_buff))
3584
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
3590
if (session->lock_table_name_if_not_cached(new_db, new_name, &name_lock))
3595
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3599
build_table_filename(new_name_buff, sizeof(new_name_buff), new_db, new_name_buff, false);
3601
if (StorageEngine::getTableProto(new_name_buff, NULL) == EEXIST)
3603
/* Table will be closed by Session::executeCommand() */
3604
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
3612
new_alias= table_name;
3613
new_name= table_name;
3616
old_db_type= table->s->db_type();
3617
if (! create_info->db_type)
3619
create_info->db_type= old_db_type;
3622
if (table->s->tmp_table != NO_TMP_TABLE)
3623
create_info->options|= HA_LEX_CREATE_TMP_TABLE;
3625
if (check_engine(session, new_name, create_info))
3628
new_db_type= create_info->db_type;
3630
if (new_db_type != old_db_type &&
3631
!table->file->can_switch_engines())
3634
my_error(ER_ROW_IS_REFERENCED, MYF(0));
3638
if (create_info->row_type == ROW_TYPE_NOT_USED)
3639
create_info->row_type= table->s->row_type;
3641
if (old_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED) ||
3642
new_db_type->check_flag(HTON_BIT_ALTER_NOT_SUPPORTED))
3644
my_error(ER_ILLEGAL_HA, MYF(0), table_name);
3648
session->set_proc_info("setup");
3651
* test if no other bits except ALTER_RENAME and ALTER_KEYS_ONOFF are set
3654
tmp.reset(ALTER_RENAME);
3655
tmp.reset(ALTER_KEYS_ONOFF);
3656
tmp&= alter_info->flags;
3657
if (! (tmp.any()) &&
3658
! table->s->tmp_table) // no need to touch frm
3660
switch (alter_info->keys_onoff)
3666
wait_while_table_is_used() ensures that table being altered is
3667
opened only by this thread and that Table::TableShare::version
3668
of Table object corresponding to this table is 0.
3669
The latter guarantees that no DML statement will open this table
3670
until ALTER Table finishes (i.e. until close_thread_tables())
3671
while the fact that the table is still open gives us protection
3672
from concurrent DDL statements.
3674
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
3675
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
3676
pthread_mutex_unlock(&LOCK_open);
3677
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3678
/* COND_refresh will be signaled in close_thread_tables() */
3681
pthread_mutex_lock(&LOCK_open); /* DDL wait for/blocker */
3682
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
3683
pthread_mutex_unlock(&LOCK_open);
3684
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
3685
/* COND_refresh will be signaled in close_thread_tables() */
3693
if (error == HA_ERR_WRONG_COMMAND)
3696
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3697
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3701
pthread_mutex_lock(&LOCK_open); /* Lock to remove all instances of table from table cache before ALTER */
3703
Unlike to the above case close_cached_table() below will remove ALL
3704
instances of Table from table cache (it will also remove table lock
3705
held by this thread). So to make actual table renaming and writing
3706
to binlog atomic we have to put them into the same critical section
3707
protected by LOCK_open mutex. This also removes gap for races between
3708
access() and mysql_rename_table() calls.
3712
(new_name != table_name || new_db != db))
3714
session->set_proc_info("rename");
3716
Then do a 'simple' rename of the table. First we need to close all
3717
instances of 'source' table.
3719
session->close_cached_table(table);
3721
Then, we want check once again that target table does not exist.
3722
Actually the order of these two steps does not matter since
3723
earlier we took name-lock on the target table, so we do them
3724
in this particular order only to be consistent with 5.0, in which
3725
we don't take this name-lock and where this order really matters.
3726
TODO: Investigate if we need this access() check at all.
3728
if (StorageEngine::getTableProto(new_name, NULL) == EEXIST)
3730
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
3735
*fn_ext(new_name)= 0;
3736
if (mysql_rename_table(old_db_type, db, table_name, new_db, new_alias, 0))
3741
if (error == HA_ERR_WRONG_COMMAND)
3744
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
3745
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
3751
write_bin_log(session, true, session->query, session->query_length);
3756
table->file->print_error(error, MYF(0));
2176
boost_unique_lock_t lock(table::Cache::singleton().mutex()); /* unlink open tables for create table like*/
2177
3761
session->unlink_open_table(name_lock);
2183
if (is_if_not_exists)
3763
pthread_mutex_unlock(&LOCK_open);
3764
table_list->table= NULL;
3768
/* We have to do full alter table. */
3771
If the old table had partitions and we are doing ALTER Table ...
3772
engine= <new_engine>, the new table must preserve the original
3773
partitioning. That means that the new engine is still the
3774
partitioning engine, not the engine specified in the parser.
3775
This is discovered in prep_alter_part_table, which in such case
3776
updates create_info->db_type.
3777
Now we need to update the stack copy of create_info->db_type,
3778
as otherwise we won't be able to correctly move the files of the
3779
temporary table to the result table files.
3781
new_db_type= create_info->db_type;
3783
if (mysql_prepare_alter_table(session, table, create_info, alter_info))
3786
set_table_default_charset(create_info, db);
3788
alter_info->build_method= HA_BUILD_OFFLINE;
3790
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
3792
/* Safety fix for innodb */
3793
my_casedn_str(files_charset_info, tmp_name);
3795
/* Create a temporary table with the new format */
3796
error= create_temporary_table(session, table, new_db, tmp_name, create_info, alter_info, ! strcmp(db, new_db));
3801
/* Open the table so we need to copy the data to it. */
3802
if (table->s->tmp_table)
3806
tbl.alias= tmp_name;
3807
tbl.table_name= tmp_name;
3809
/* Table is in session->temporary_tables */
3810
new_table= session->openTable(&tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
3814
char tmp_path[FN_REFLEN];
3815
/* table is a normal table: Create temporary table in same directory */
3816
build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, true);
3817
/* Open our intermediate table */
3818
new_table= session->open_temporary_table(tmp_path, new_db, tmp_name, 0, OTM_OPEN);
3821
if (new_table == NULL)
3824
/* Copy the data if necessary. */
3825
session->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
3826
session->cuted_fields= 0L;
3827
session->set_proc_info("copy to tmp table");
3832
/* We don't want update TIMESTAMP fields during ALTER Table. */
3833
new_table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
3834
new_table->next_number_field= new_table->found_next_number_field;
3835
error= copy_data_between_tables(table,
3837
alter_info->create_list,
3843
alter_info->keys_onoff,
3844
alter_info->error_if_not_empty);
3846
/* We must not ignore bad input! */
3847
session->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL;
3849
if (table->s->tmp_table != NO_TMP_TABLE)
3851
/* We changed a temporary table */
3855
/* Close lock if this is a transactional table */
3858
mysql_unlock_tables(session, session->lock);
3862
/* Remove link to old table and rename the new one */
3863
session->close_temporary_table(table, true, true);
3865
/* Should pass the 'new_name' as we store table name in the cache */
3866
if (new_table->rename_temporary_table(new_db, new_name))
3875
Close the intermediate table that will be the new table.
3876
Note that MERGE tables do not have their children attached here.
3878
new_table->intern_close_table();
3882
pthread_mutex_lock(&LOCK_open); /* ALTER TABLE */
3886
quick_rm_table(new_db_type, new_db, tmp_name, true);
3887
pthread_mutex_unlock(&LOCK_open);
3892
Data is copied. Now we:
3893
1) Wait until all other threads close old version of table.
3894
2) Close instances of table open by this thread and replace them
3895
with exclusive name-locks.
3896
3) Rename the old table to a temp name, rename the new one to the
3898
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
3899
we reopen new version of table.
3900
5) Write statement to the binary log.
3901
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
3902
remove name-locks from list of open tables and table cache.
3903
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
3904
call to remove name-locks from table cache and list of open table.
3907
session->set_proc_info("rename result table");
3909
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX, (unsigned long) current_pid, session->thread_id);
3911
my_casedn_str(files_charset_info, old_name);
3913
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
3914
session->close_data_files_and_morph_locks(db, table_name);
3917
save_old_db_type= old_db_type;
3920
This leads to the storage engine (SE) not being notified for renames in
3921
mysql_rename_table(), because we just juggle with the FRM and nothing
3922
more. If we have an intermediate table, then we notify the SE that
3923
it should become the actual table. Later, we will recycle the old table.
3924
However, in case of ALTER Table RENAME there might be no intermediate
3925
table. This is when the old and new tables are compatible, according to
3926
compare_table(). Then, we need one additional call to
3927
mysql_rename_table() with flag NO_FRM_RENAME, which does nothing else but
3928
actual rename in the SE and the FRM is not touched. Note that, if the
3929
table is renamed and the SE is also changed, then an intermediate table
3930
is created and the additional call will not take place.
3932
if (mysql_rename_table(old_db_type, db, table_name, db, old_name, FN_TO_IS_TMP))
3935
quick_rm_table(new_db_type, new_db, tmp_name, true);
3939
if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db, new_alias, FN_FROM_IS_TMP) != 0)
3941
/* Try to get everything back. */
3943
quick_rm_table(new_db_type, new_db, new_alias, false);
3944
quick_rm_table(new_db_type, new_db, tmp_name, true);
3945
mysql_rename_table(old_db_type, db, old_name, db, table_name, FN_FROM_IS_TMP);
3951
/* This shouldn't happen. But let us play it safe. */
3952
goto err_with_placeholders;
3955
quick_rm_table(old_db_type, db, old_name, true);
3957
pthread_mutex_unlock(&LOCK_open);
3959
session->set_proc_info("end");
3961
write_bin_log(session, true, session->query, session->query_length);
3963
if (old_db_type->check_flag(HTON_BIT_FLUSH_AFTER_RENAME))
3966
For the alter table to be properly flushed to the logs, we
3967
have to open the new table. If not, we get a problem on server
3968
shutdown. But we do not need to attach MERGE children.
3970
char table_path[FN_REFLEN];
3972
build_table_filename(table_path, sizeof(table_path), new_db, table_name, false);
3973
t_table= session->open_temporary_table(table_path, new_db, tmp_name, false, OTM_OPEN);
3976
t_table->intern_close_table();
3980
errmsg_printf(ERRMSG_LVL_WARN, _("Could not open table %s.%s after rename\n"), new_db, table_name);
3982
ha_flush_logs(old_db_type);
3984
table_list->table= NULL;
3988
* Field::store() may have called my_error(). If this is
3989
* the case, we must not send an ok packet, since
3990
* Diagnostics_area::is_set() will fail an assert.
3992
if (! session->is_error())
3994
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
3995
(ulong) (copied + deleted), (ulong) deleted,
3996
(ulong) session->cuted_fields);
3997
session->my_ok(copied + deleted, 0, 0L, tmp_name);
3998
session->some_tables_deleted=0;
4003
/* my_error() was called. Return true (which means error...) */
4010
/* close_temporary_table() frees the new_table pointer. */
4011
session->close_temporary_table(new_table, true, true);
4014
quick_rm_table(new_db_type, new_db, tmp_name, true);
4018
No default value was provided for a DATE/DATETIME field, the
4019
current sql_mode doesn't allow the '0000-00-00' value and
4020
the table to be altered isn't empty.
4023
if (alter_info->error_if_not_empty && session->row_count)
4025
const char *f_val= 0;
4026
enum enum_drizzle_timestamp_type t_type= DRIZZLE_TIMESTAMP_DATE;
4027
switch (alter_info->datetime_field->sql_type)
4029
case DRIZZLE_TYPE_DATE:
4030
f_val= "0000-00-00";
4031
t_type= DRIZZLE_TIMESTAMP_DATE;
4033
case DRIZZLE_TYPE_DATETIME:
4034
f_val= "0000-00-00 00:00:00";
4035
t_type= DRIZZLE_TIMESTAMP_DATETIME;
4038
/* Shouldn't get here. */
4041
bool save_abort_on_warning= session->abort_on_warning;
4042
session->abort_on_warning= true;
4043
make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
4044
f_val, strlength(f_val), t_type,
4045
alter_info->datetime_field->field_name);
4046
session->abort_on_warning= save_abort_on_warning;
4050
pthread_mutex_lock(&LOCK_open); /* ALTER TABLe */
4051
session->unlink_open_table(name_lock);
4052
pthread_mutex_unlock(&LOCK_open);
4056
err_with_placeholders:
4058
An error happened while we were holding exclusive name-lock on table
4059
being altered. To be safe under LOCK TABLES we should remove placeholders
4060
from list of open tables list and table cache.
4062
session->unlink_open_table(table);
4064
session->unlink_open_table(name_lock);
4065
pthread_mutex_unlock(&LOCK_open);
4068
/* mysql_alter_table */
4071
copy_data_between_tables(Table *from,Table *to,
4072
List<CreateField> &create,
4074
uint32_t order_num, order_st *order,
4077
enum enum_enable_or_disable keys_onoff,
4078
bool error_if_not_empty)
4081
CopyField *copy,*copy_end;
4082
ulong found_count,delete_count;
4083
Session *session= current_session;
4085
SORT_FIELD *sortorder;
4089
List<Item> all_fields;
4090
ha_rows examined_rows;
4091
bool auto_increment_field_copied= 0;
4092
uint64_t prev_insert_id;
4095
Turn off recovery logging since rollback of an alter table is to
4096
delete the new table so there is no need to log the changes to it.
4098
This needs to be done before external_lock
4100
error= ha_enable_transaction(session, false);
4104
if (!(copy= new CopyField[to->s->fields]))
4105
return -1; /* purecov: inspected */
4107
if (to->file->ha_external_lock(session, F_WRLCK))
4110
/* We need external lock before we can disable/enable keys */
4111
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
4113
/* We can abort alter table for any table type */
4114
session->abort_on_warning= !ignore;
4116
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
4117
to->file->ha_start_bulk_insert(from->file->stats.records);
4119
List_iterator<CreateField> it(create);
4122
for (Field **ptr=to->field ; *ptr ; ptr++)
4127
if (*ptr == to->next_number_field)
4128
auto_increment_field_copied= true;
4130
(copy_end++)->set(*ptr,def->field,0);
4135
found_count=delete_count=0;
4139
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
2185
4141
char warn_buff[DRIZZLE_ERRMSG_SIZE];
2186
4142
snprintf(warn_buff, sizeof(warn_buff),
2187
ER(ER_TABLE_EXISTS_ERROR), destination_identifier.getTableName().c_str());
2188
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
2189
ER_TABLE_EXISTS_ERROR, warn_buff);
2193
my_error(ER_TABLE_EXISTS_ERROR, destination_identifier);
2202
bool analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2204
thr_lock_type lock_type = TL_READ_NO_INSERT;
2206
return(admin_table(session, tables, check_opt,
2207
"analyze", lock_type, true,
2208
&Cursor::ha_analyze));
2212
bool check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
2214
thr_lock_type lock_type = TL_READ_NO_INSERT;
2216
return(admin_table(session, tables, check_opt,
2219
&Cursor::ha_check));
2222
} /* namespace drizzled */
4143
_("order_st BY ignored because there is a user-defined clustered "
4144
"index in the table '%-.192s'"),
4145
from->s->table_name.str);
4146
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
4151
from->sort.io_cache= new IO_CACHE;
4152
memset(from->sort.io_cache, 0, sizeof(IO_CACHE));
4154
memset(&tables, 0, sizeof(tables));
4156
tables.alias= tables.table_name= from->s->table_name.str;
4157
tables.db= from->s->db.str;
4160
if (session->lex->select_lex.setup_ref_array(session, order_num) ||
4161
setup_order(session, session->lex->select_lex.ref_pointer_array,
4162
&tables, fields, all_fields, order) ||
4163
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
4164
(from->sort.found_records= filesort(session, from, sortorder, length,
4165
(SQL_SELECT *) 0, HA_POS_ERROR,
4166
1, &examined_rows)) ==
4172
/* Tell handler that we have values for all columns in the to table */
4173
to->use_all_columns();
4174
init_read_record(&info, session, from, (SQL_SELECT *) 0, 1,1);
4176
to->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
4177
session->row_count= 0;
4178
to->restoreRecordAsDefault(); // Create empty record
4179
while (!(error=info.read_record(&info)))
4181
if (session->killed)
4183
session->send_kill_message();
4187
session->row_count++;
4188
/* Return error if source table isn't empty. */
4189
if (error_if_not_empty)
4194
if (to->next_number_field)
4196
if (auto_increment_field_copied)
4197
to->auto_increment_field_not_null= true;
4199
to->next_number_field->reset();
4202
for (CopyField *copy_ptr=copy ; copy_ptr != copy_end ; copy_ptr++)
4204
copy_ptr->do_copy(copy_ptr);
4206
prev_insert_id= to->file->next_insert_id;
4207
error=to->file->ha_write_row(to->record[0]);
4208
to->auto_increment_field_not_null= false;
4212
to->file->is_fatal_error(error, HA_CHECK_DUP))
4214
if (!to->file->is_fatal_error(error, HA_CHECK_DUP))
4216
uint32_t key_nr= to->file->get_dup_key(error);
4217
if ((int) key_nr >= 0)
4219
const char *err_msg= ER(ER_DUP_ENTRY_WITH_KEY_NAME);
4221
(to->key_info[0].key_part[0].field->flags &
4222
AUTO_INCREMENT_FLAG))
4223
err_msg= ER(ER_DUP_ENTRY_AUTOINCREMENT_CASE);
4224
to->file->print_keydup_error(key_nr, err_msg);
4229
to->file->print_error(error,MYF(0));
4232
to->file->restore_auto_increment(prev_insert_id);
4238
end_read_record(&info);
4239
from->free_io_cache();
4240
delete [] copy; // This is never 0
4242
if (to->file->ha_end_bulk_insert() && error <= 0)
4244
to->file->print_error(my_errno,MYF(0));
4247
to->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
4249
if (ha_enable_transaction(session, true))
4256
Ensure that the new table is saved properly to disk so that we
4259
if (ha_autocommit_or_rollback(session, 0))
4261
if (! session->endActiveTransaction())
4265
session->abort_on_warning= 0;
4266
from->free_io_cache();
4267
*copied= found_count;
4268
*deleted=delete_count;
4269
to->file->ha_release_auto_increment();
4270
if (to->file->ha_external_lock(session,F_UNLCK))
4272
return(error > 0 ? -1 : 0);
4277
Recreates tables by calling mysql_alter_table().
4280
mysql_recreate_table()
4281
session Thread handler
4282
tables Tables to recreate
4285
Like mysql_alter_table().
4287
bool mysql_recreate_table(Session *session, TableList *table_list)
4289
HA_CREATE_INFO create_info;
4290
Alter_info alter_info;
4292
assert(!table_list->next_global);
4294
table_list->table has been closed and freed. Do not reference
4295
uninitialized data. open_tables() could fail.
4297
table_list->table= NULL;
4299
memset(&create_info, 0, sizeof(create_info));
4300
create_info.row_type=ROW_TYPE_NOT_USED;
4301
create_info.default_table_charset=default_charset_info;
4302
/* Force alter table to recreate table */
4303
alter_info.flags.set(ALTER_CHANGE_COLUMN);
4304
alter_info.flags.set(ALTER_RECREATE);
4305
return(mysql_alter_table(session, NULL, NULL, &create_info,
4306
table_list, &alter_info, 0,
4307
(order_st *) 0, 0));
4311
bool mysql_checksum_table(Session *session, TableList *tables,
4312
HA_CHECK_OPT *check_opt)
4315
List<Item> field_list;
4317
plugin::Protocol *protocol= session->protocol;
4319
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
4320
item->maybe_null= 1;
4321
field_list.push_back(item= new Item_int("Checksum", (int64_t) 1,
4322
MY_INT64_NUM_DECIMAL_DIGITS));
4323
item->maybe_null= 1;
4324
if (protocol->sendFields(&field_list))
4327
/* Open one table after the other to keep lock time as short as possible. */
4328
for (table= tables; table; table= table->next_local)
4330
char table_name[NAME_LEN*2+2];
4333
sprintf(table_name,"%s.%s",table->db,table->table_name);
4335
t= table->table= session->openTableLock(table, TL_READ);
4336
session->clear_error(); // these errors shouldn't get client
4338
protocol->prepareForResend();
4339
protocol->store(table_name);
4343
/* Table didn't exist */
4345
session->clear_error();
4349
if (t->file->ha_table_flags() & HA_HAS_CHECKSUM &&
4350
!(check_opt->flags & T_EXTEND))
4351
protocol->store((uint64_t)t->file->checksum());
4352
else if (!(t->file->ha_table_flags() & HA_HAS_CHECKSUM) &&
4353
(check_opt->flags & T_QUICK))
4357
/* calculating table's checksum */
4359
unsigned char null_mask=256 - (1 << t->s->last_null_bit_pos);
4361
t->use_all_columns();
4363
if (t->file->ha_rnd_init(1))
4369
ha_checksum row_crc= 0;
4370
int error= t->file->rnd_next(t->record[0]);
4371
if (unlikely(error))
4373
if (error == HA_ERR_RECORD_DELETED)
4377
if (t->s->null_bytes)
4379
/* fix undefined null bits */
4380
t->record[0][t->s->null_bytes-1] |= null_mask;
4381
if (!(t->s->db_create_options & HA_OPTION_PACK_RECORD))
4382
t->record[0][0] |= 1;
4384
row_crc= my_checksum(row_crc, t->record[0], t->s->null_bytes);
4387
for (uint32_t i= 0; i < t->s->fields; i++ )
4389
Field *f= t->field[i];
4390
if ((f->type() == DRIZZLE_TYPE_BLOB) ||
4391
(f->type() == DRIZZLE_TYPE_VARCHAR))
4395
row_crc= my_checksum(row_crc, (unsigned char*) tmp.ptr(), tmp.length());
4398
row_crc= my_checksum(row_crc, f->ptr,
4404
protocol->store((uint64_t)crc);
4405
t->file->ha_rnd_end();
4408
session->clear_error();
4409
session->close_thread_tables();
4410
table->table=0; // For query cache
4412
if (protocol->write())
4420
session->close_thread_tables(); // Shouldn't be needed
4426
static bool check_engine(Session *session, const char *table_name,
4427
HA_CREATE_INFO *create_info)
4429
StorageEngine **new_engine= &create_info->db_type;
4430
StorageEngine *req_engine= *new_engine;
4431
if (!req_engine->is_enabled())
4433
string engine_name= req_engine->getName();
4434
my_error(ER_FEATURE_DISABLED,MYF(0),
4435
engine_name.c_str(), engine_name.c_str());
4440
if (req_engine && req_engine != *new_engine)
4442
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
4443
ER_WARN_USING_OTHER_HANDLER,
4444
ER(ER_WARN_USING_OTHER_HANDLER),
4445
ha_resolve_storage_engine_name(*new_engine).c_str(),
4448
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
4449
(*new_engine)->check_flag(HTON_BIT_TEMPORARY_NOT_SUPPORTED))
4451
if (create_info->used_fields & HA_CREATE_USED_ENGINE)
4453
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
4454
ha_resolve_storage_engine_name(*new_engine).c_str(),
4459
*new_engine= myisam_engine;
4461
if(!(create_info->options & HA_LEX_CREATE_TMP_TABLE)
4462
&& (*new_engine)->check_flag(HTON_BIT_TEMPORARY_ONLY))
4464
my_error(ER_ILLEGAL_HA_CREATE_OPTION, MYF(0),
4465
ha_resolve_storage_engine_name(*new_engine).c_str(),