18
18
#include <drizzled/server_includes.h>
19
19
#include <storage/myisam/myisam.h>
20
#include <drizzled/sql_show.h>
21
#include <drizzled/drizzled_error_messages.h>
20
#include <drizzled/show.h>
21
#include <drizzled/error.h>
22
#include <drizzled/gettext.h>
23
#include <drizzled/data_home.h>
24
#include <drizzled/sql_parse.h>
25
#include <mysys/hash.h>
26
#include <drizzled/sql_lex.h>
27
#include <drizzled/session.h>
28
#include <drizzled/sql_base.h>
29
#include <drizzled/db.h>
30
#include <drizzled/lock.h>
31
#include <drizzled/unireg.h>
32
#include <drizzled/item/int.h>
33
#include <drizzled/item/empty_string.h>
34
#include <drizzled/replicator.h>
38
extern HASH lock_db_cache;
23
40
int creating_table= 0; // How many mysql_create_table are running
25
const char *primary_key_name="PRIMARY";
43
bool is_primary_key(KEY *key_info)
45
static const char * primary_key_name="PRIMARY";
46
return (strcmp(key_info->name, primary_key_name)==0);
49
const char* is_primary_key_name(const char* key_name)
51
static const char * primary_key_name="PRIMARY";
52
if (strcmp(key_name, primary_key_name)==0)
27
58
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
28
59
static char *make_unique_key_name(const char *field_name,KEY *start,KEY *end);
29
static int copy_data_between_tables(TABLE *from,TABLE *to,
60
static int copy_data_between_tables(Table *from,Table *to,
30
61
List<Create_field> &create, bool ignore,
31
uint order_num, ORDER *order,
62
uint32_t order_num, order_st *order,
32
63
ha_rows *copied,ha_rows *deleted,
33
64
enum enum_enable_or_disable keys_onoff,
34
65
bool error_if_not_empty);
36
static bool prepare_blob_field(THD *thd, Create_field *sql_field);
37
static bool check_engine(THD *, const char *, HA_CREATE_INFO *);
67
static bool prepare_blob_field(Session *session, Create_field *sql_field);
68
static bool check_engine(Session *, const char *, HA_CREATE_INFO *);
39
mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
70
mysql_prepare_create_table(Session *session, HA_CREATE_INFO *create_info,
40
71
Alter_info *alter_info,
43
74
handler *file, KEY **key_info_buffer,
44
uint *key_count, int select_field_count);
75
uint32_t *key_count, int select_field_count);
46
mysql_prepare_alter_table(THD *thd, TABLE *table,
77
mysql_prepare_alter_table(Session *session, Table *table,
47
78
HA_CREATE_INFO *create_info,
48
79
Alter_info *alter_info);
81
static void set_table_default_charset(Session *session,
82
HA_CREATE_INFO *create_info, char *db)
85
If the table character set was not given explicitly,
86
let's fetch the database default character set and
87
apply it to the table.
89
if (!create_info->default_table_charset)
91
HA_CREATE_INFO db_info;
93
load_db_opt_by_name(session, db, &db_info);
95
create_info->default_table_charset= db_info.default_table_charset;
51
100
Translate a file name to a table name (WL #1324).
102
148
File name length.
105
uint tablename_to_filename(const char *from, char *to, uint to_length)
150
uint32_t tablename_to_filename(const char *from, char *to, uint32_t to_length)
152
uint32_t errors, length;
109
154
if (from[0] == '#' && !strncmp(from, MYSQL50_TABLE_NAME_PREFIX,
110
155
MYSQL50_TABLE_NAME_PREFIX_LENGTH))
111
return((uint) (strmake(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH,
113
(from + MYSQL50_TABLE_NAME_PREFIX_LENGTH)));
156
return((uint) (strncpy(to, from+MYSQL50_TABLE_NAME_PREFIX_LENGTH,
158
(from + MYSQL50_TABLE_NAME_PREFIX_LENGTH)));
114
159
length= strconvert(system_charset_info, from,
115
160
&my_charset_filename, to, to_length, &errors);
116
161
if (check_if_legal_tablename(to) &&
142
187
Uses database and table name, and extension to create
143
a file name in mysql_data_dir. Database and table
188
a file name in drizzle_data_dir. Database and table
144
189
names are converted from system_charset_info into "fscs".
145
190
Unless flags indicate a temporary table name.
146
191
'db' is always converted.
147
192
'ext' is not converted.
149
The conversion suppression is required for ALTER TABLE. This
194
The conversion suppression is required for ALTER Table. This
150
195
statement creates intermediate tables. These are regular
151
196
(non-temporary) tables with a temporary name. Their path names must
152
197
be derivable from the table name. So we cannot use
153
198
build_tmptable_filename() for them.
201
path length on success, 0 on failure
159
uint build_table_filename(char *buff, size_t bufflen, const char *db,
160
const char *table_name, const char *ext, uint flags)
204
uint32_t build_table_filename(char *buff, size_t bufflen, const char *db,
205
const char *table_name, const char *ext, uint32_t flags)
162
208
char dbbuff[FN_REFLEN];
163
209
char tbbuff[FN_REFLEN];
210
int rootdir_len= strlen(FN_ROOTDIR);
165
212
if (flags & FN_IS_TMP) // FN_FROM_IS_TMP | FN_TO_IS_TMP
166
stpncpy(tbbuff, table_name, sizeof(tbbuff));
213
strncpy(tbbuff, table_name, sizeof(tbbuff));
168
VOID(tablename_to_filename(table_name, tbbuff, sizeof(tbbuff)));
170
VOID(tablename_to_filename(db, dbbuff, sizeof(dbbuff)));
172
char *end = buff + bufflen;
173
/* Don't add FN_ROOTDIR if mysql_data_home already includes it */
174
char *pos = stpncpy(buff, mysql_data_home, bufflen);
175
int rootdir_len= strlen(FN_ROOTDIR);
176
if (pos - rootdir_len >= buff &&
177
memcmp(pos - rootdir_len, FN_ROOTDIR, rootdir_len) != 0)
178
pos= stpncpy(pos, FN_ROOTDIR, end - pos);
179
pos= strxnmov(pos, end - pos, dbbuff, FN_ROOTDIR, NullS);
215
tablename_to_filename(table_name, tbbuff, sizeof(tbbuff));
217
tablename_to_filename(db, dbbuff, sizeof(dbbuff));
218
table_path= drizzle_data_home;
219
int without_rootdir= table_path.length()-rootdir_len;
221
/* Don't add FN_ROOTDIR if dirzzle_data_home already includes it */
222
if (without_rootdir >= 0)
224
char *tmp= (char*)table_path.c_str()+without_rootdir;
225
if (memcmp(tmp, FN_ROOTDIR, rootdir_len) != 0)
226
table_path.append(FN_ROOTDIR);
229
table_path.append(dbbuff);
230
table_path.append(FN_ROOTDIR);
180
231
#ifdef USE_SYMDIR
181
unpack_dirname(buff, buff);
184
pos= strxnmov(pos, end - pos, tbbuff, ext, NullS);
234
table_path.append(tbbuff);
235
table_path.append(ext);
237
if (bufflen < table_path.length())
240
strcpy(buff, table_path.c_str());
241
return table_path.length();
191
Creates path to a file: mysql_tmpdir/#sql1234_12_1.ext
246
Creates path to a file: drizzle_tmpdir/#sql1234_12_1.ext
194
249
build_tmptable_filename()
195
thd The thread handle.
250
session The thread handle.
196
251
buff Where to write result in my_charset_filename.
197
252
bufflen buff size
201
256
Uses current_pid, thread_id, and tmp_table counter to create
202
a file name in mysql_tmpdir.
257
a file name in drizzle_tmpdir.
260
path length on success, 0 on failure
208
uint build_tmptable_filename(THD* thd, char *buff, size_t bufflen)
263
uint32_t build_tmptable_filename(Session* session, char *buff, size_t bufflen)
266
ostringstream path_str, post_tmpdir_str;
211
char *p= stpncpy(buff, mysql_tmpdir, bufflen);
212
snprintf(p, bufflen - (p - buff), "/%s%lx_%lx_%x%s",
213
tmp_file_prefix, current_pid,
214
thd->thread_id, thd->tmp_table++, reg_ext);
269
path_str << drizzle_tmpdir;
270
post_tmpdir_str << "/" << TMP_FILE_PREFIX << current_pid;
271
post_tmpdir_str << session->thread_id << session->tmp_table++ << reg_ext;
272
tmp= post_tmpdir_str.str();
216
274
if (lower_case_table_names)
218
/* Convert all except tmpdir to lower case */
219
my_casedn_str(files_charset_info, p);
222
uint length= unpack_filename(buff, buff);
275
transform(tmp.begin(), tmp.end(), tmp.begin(), ::tolower);
279
if (bufflen < path_str.str().length())
282
length= unpack_filename(buff, path_str.str().c_str());
290
session Thread object
230
291
clear_error is clear_error to be called
231
292
query Query to log
232
293
query_length Length of query
341
396
-1 Thread was killed
344
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
345
bool drop_temporary, bool drop_view,
399
int mysql_rm_table_part2(Session *session, TableList *tables, bool if_exists,
400
bool drop_temporary, bool dont_log_query)
349
403
char path[FN_REFLEN], *alias;
404
uint32_t path_length= 0;
351
405
String wrong_tables;
353
407
int non_temp_tables_count= 0;
354
408
bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
355
409
String built_query;
357
if (thd->current_stmt_binlog_row_based && !dont_log_query)
359
413
built_query.set_charset(system_charset_info);
361
built_query.append("DROP TABLE IF EXISTS ");
415
built_query.append("DROP Table IF EXISTS ");
363
built_query.append("DROP TABLE ");
417
built_query.append("DROP Table ");
366
mysql_ha_rm_tables(thd, tables, false);
420
mysql_ha_rm_tables(session, tables, false);
368
422
pthread_mutex_lock(&LOCK_open);
440
491
table_type= table->db_type;
441
492
if (!drop_temporary)
444
abort_locked_tables(thd, db, table->table_name);
445
remove_table_from_cache(thd, db, table->table_name,
495
abort_locked_tables(session, db, table->table_name);
496
remove_table_from_cache(session, db, table->table_name,
446
497
RTFC_WAIT_OTHER_THREAD_FLAG |
447
498
RTFC_CHECK_KILLED_FLAG);
449
500
If the table was used in lock tables, remember it so that
450
501
unlock_table_names can free it
452
if ((locked_table= drop_locked_tables(thd, db, table->table_name)))
503
if ((locked_table= drop_locked_tables(session, db, table->table_name)))
453
504
table->table= locked_table;
458
509
goto err_with_placeholders;
610
bool quick_rm_table(handlerton *base,const char *db,
611
const char *table_name, uint flags)
659
bool quick_rm_table(handlerton *,const char *db,
660
const char *table_name, uint32_t flags)
613
662
char path[FN_REFLEN];
616
uint path_length= build_table_filename(path, sizeof(path),
665
uint32_t path_length= build_table_filename(path, sizeof(path),
617
666
db, table_name, reg_ext, flags);
618
667
if (my_delete(path,MYF(0)))
619
668
error= 1; /* purecov: inspected */
620
670
path[path_length - reg_ext_length]= '\0'; // Remove reg_ext
621
return(ha_delete_table(current_thd, base, path, db, table_name, 0) ||
672
error|= delete_table_proto_file(path);
674
return(ha_delete_table(current_session, path, db, table_name, 0) ||
981
1037
occupied memory at the same time when we free this
982
1038
sql_field -- at the end of execution.
984
interval= sql_field->interval= typelib(thd->mem_root,
1040
interval= sql_field->interval= typelib(session->mem_root,
985
1041
sql_field->interval_list);
986
1042
List_iterator<String> int_it(sql_field->interval_list);
987
1043
String conv, *tmp;
988
1044
char comma_buf[4];
989
int comma_length= cs->cset->wc_mb(cs, ',', (uchar*) comma_buf,
1045
int comma_length= cs->cset->wc_mb(cs, ',', (unsigned char*) comma_buf,
1046
(unsigned char*) comma_buf +
991
1047
sizeof(comma_buf));
992
1048
assert(comma_length > 0);
993
for (uint i= 0; (tmp= int_it++); i++)
1049
for (uint32_t i= 0; (tmp= int_it++); i++)
996
1052
if (String::needs_conversion(tmp->length(), tmp->charset(),
1000
1056
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
1001
interval->type_names[i]= strmake_root(thd->mem_root, conv.ptr(),
1057
interval->type_names[i]= strmake_root(session->mem_root, conv.ptr(),
1002
1058
conv.length());
1003
1059
interval->type_lengths[i]= conv.length();
1645
Preparation of Create_field for SP function return values.
1646
Based on code used in the inner loop of mysql_prepare_create_table()
1650
sp_prepare_create_field()
1652
sql_field Field to prepare
1655
Prepares the field structures for field creation.
1659
void sp_prepare_create_field(THD *thd, Create_field *sql_field)
1661
if (sql_field->sql_type == DRIZZLE_TYPE_ENUM)
1663
uint32_t field_length, dummy;
1664
/* DRIZZLE_TYPE_ENUM */
1666
calculate_interval_lengths(sql_field->charset,
1667
sql_field->interval,
1668
&field_length, &dummy);
1669
sql_field->length= field_length;
1671
set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
1674
sql_field->create_length_to_internal_length();
1675
assert(sql_field->def == 0);
1676
/* Can't go wrong as sql_field->def is not defined */
1677
(void) prepare_blob_field(thd, sql_field);
1685
1703
mysql_create_table_no_lock()
1704
session Thread object
1688
1706
table_name Table name
1689
1707
create_info Create information (like MAX_ROWS)
1690
1708
fields List of fields to create
1691
1709
keys List of keys to create
1692
1710
internal_tmp_table Set to 1 if this is an internal temporary table
1697
1715
If one creates a temporary table, this is automatically opened
1735
if (check_engine(thd, table_name, create_info))
1754
if (check_engine(session, table_name, create_info))
1737
1756
db_options= create_info->table_options;
1738
1757
if (create_info->row_type == ROW_TYPE_DYNAMIC)
1739
1758
db_options|=HA_OPTION_PACK_RECORD;
1740
1759
alias= table_case_name(create_info, table_name);
1741
if (!(file= get_new_handler((TABLE_SHARE*) 0, thd->mem_root,
1760
if (!(file= get_new_handler((TABLE_SHARE*) 0, session->mem_root,
1742
1761
create_info->db_type)))
1744
1763
my_error(ER_OUTOFMEMORY, MYF(0), sizeof(handler));
1748
set_table_default_charset(thd, create_info, (char*) db);
1767
set_table_default_charset(session, create_info, (char*) db);
1750
if (mysql_prepare_create_table(thd, create_info, alter_info,
1769
if (mysql_prepare_create_table(session, create_info, alter_info,
1751
1770
internal_tmp_table,
1752
1771
&db_options, file,
1753
1772
&key_info_buffer, &key_count,
1867
1887
#endif /* HAVE_READLINK */
1869
1889
if (create_info->data_file_name)
1870
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
1890
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
1871
1891
"DATA DIRECTORY option ignored");
1872
1892
if (create_info->index_file_name)
1873
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
1893
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, 0,
1874
1894
"INDEX DIRECTORY option ignored");
1875
1895
create_info->data_file_name= create_info->index_file_name= 0;
1877
1897
create_info->table_options=db_options;
1879
1899
path[path_length - reg_ext_length]= '\0'; // Remove .frm extension
1880
if (rea_create_table(thd, path, db, table_name,
1900
if (rea_create_table(session, path, db, table_name,
1881
1901
create_info, alter_info->create_list,
1882
key_count, key_info_buffer, file))
1902
key_count, key_info_buffer, file, false))
1883
1903
goto unlock_and_end;
1885
1905
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
1887
1907
/* Open table and put in temporary table list */
1888
if (!(open_temporary_table(thd, path, db, table_name, 1, OTM_OPEN)))
1908
if (!(open_temporary_table(session, path, db, table_name, 1, OTM_OPEN)))
1890
(void) rm_temporary_table(create_info->db_type, path, false);
1910
(void) rm_temporary_table(create_info->db_type, path);
1891
1911
goto unlock_and_end;
1893
thd->thread_specific_used= true;
1913
session->thread_specific_used= true;
1901
1921
Otherwise, the statement shall be binlogged.
1903
1923
if (!internal_tmp_table &&
1904
(!thd->current_stmt_binlog_row_based ||
1905
(thd->current_stmt_binlog_row_based &&
1906
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1907
write_bin_log(thd, true, thd->query, thd->query_length);
1924
((!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
1925
write_bin_log(session, true, session->query, session->query_length);
1909
1927
unlock_and_end:
1910
VOID(pthread_mutex_unlock(&LOCK_open));
1929
pthread_mutex_unlock(&LOCK_open);
1913
thd_proc_info(thd, "After create");
1932
session->set_proc_info("After create");
1919
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1938
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
1920
1939
ER_TABLE_EXISTS_ERROR, ER(ER_TABLE_EXISTS_ERROR),
1922
1941
create_info->table_existed= 1; // Mark that table existed
1928
1947
Database locking aware wrapper for mysql_create_table_no_lock(),
1931
bool mysql_create_table(THD *thd, const char *db, const char *table_name,
1950
bool mysql_create_table(Session *session, const char *db, const char *table_name,
1932
1951
HA_CREATE_INFO *create_info,
1933
1952
Alter_info *alter_info,
1934
1953
bool internal_tmp_table,
1935
uint select_field_count)
1954
uint32_t select_field_count)
1937
TABLE *name_lock= 0;
1956
Table *name_lock= 0;
1940
1959
/* Wait for any database locks */
1941
1960
pthread_mutex_lock(&LOCK_lock_db);
1942
while (!thd->killed &&
1943
hash_search(&lock_db_cache,(uchar*) db, strlen(db)))
1961
while (!session->killed &&
1962
hash_search(&lock_db_cache,(unsigned char*) db, strlen(db)))
1945
wait_for_condition(thd, &LOCK_lock_db, &COND_refresh);
1964
wait_for_condition(session, &LOCK_lock_db, &COND_refresh);
1946
1965
pthread_mutex_lock(&LOCK_lock_db);
1968
if (session->killed)
1951
1970
pthread_mutex_unlock(&LOCK_lock_db);
2143
2173
Win32 clients must also have a WRITE LOCK on the table !
2146
void wait_while_table_is_used(THD *thd, TABLE *table,
2176
void wait_while_table_is_used(Session *session, Table *table,
2147
2177
enum ha_extra_function function)
2150
2180
safe_mutex_assert_owner(&LOCK_open);
2152
VOID(table->file->extra(function));
2182
table->file->extra(function);
2153
2183
/* Mark all tables that are in use as 'old' */
2154
mysql_lock_abort(thd, table, true); /* end threads waiting on lock */
2184
mysql_lock_abort(session, table, true); /* end threads waiting on lock */
2156
2186
/* Wait until all there are no other threads that has this table open */
2157
remove_table_from_cache(thd, table->s->db.str,
2187
remove_table_from_cache(session, table->s->db.str,
2158
2188
table->s->table_name.str,
2159
2189
RTFC_WAIT_OTHER_THREAD_FLAG);
2177
2207
Win32 clients must also have a WRITE LOCK on the table !
2180
void close_cached_table(THD *thd, TABLE *table)
2210
void close_cached_table(Session *session, Table *table)
2183
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
2213
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
2184
2214
/* Close lock if this is not got with LOCK TABLES */
2187
mysql_unlock_tables(thd, thd->lock);
2188
thd->lock=0; // Start locked threads
2217
mysql_unlock_tables(session, session->lock);
2218
session->lock=0; // Start locked threads
2190
2220
/* Close all copies of 'table'. This also frees all LOCK TABLES lock */
2191
unlink_open_table(thd, table, true);
2221
unlink_open_table(session, table, true);
2193
2223
/* When lock on LOCK_open is freed other threads can continue */
2194
2224
broadcast_refresh();
2198
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
2228
static int send_check_errmsg(Session *session, TableList* table,
2199
2229
const char* operator_name, const char* errmsg)
2202
Protocol *protocol= thd->protocol;
2232
Protocol *protocol= session->protocol;
2203
2233
protocol->prepare_for_resend();
2204
2234
protocol->store(table->alias, system_charset_info);
2205
2235
protocol->store((char*) operator_name, system_charset_info);
2206
2236
protocol->store(STRING_WITH_LEN("error"), system_charset_info);
2207
2237
protocol->store(errmsg, system_charset_info);
2238
session->clear_error();
2209
2239
if (protocol->write())
2215
static int prepare_for_repair(THD *thd, TABLE_LIST *table_list,
2245
static int prepare_for_repair(Session *session, TableList *table_list,
2216
2246
HA_CHECK_OPT *check_opt)
2219
TABLE tmp_table, *table;
2249
Table tmp_table, *table;
2220
2250
TABLE_SHARE *share;
2221
2251
char from[FN_REFLEN],tmp[FN_REFLEN+32];
2222
2252
const char **ext;
2223
2253
struct stat stat_info;
2225
if (!(check_opt->sql_flags & TT_USEFRM))
2255
if (!(check_opt->use_frm))
2228
2258
if (!(table= table_list->table)) /* if open_ltable failed */
2230
2260
char key[MAX_DBKEY_LENGTH];
2261
uint32_t key_length;
2233
key_length= create_table_def_key(thd, key, table_list, 0);
2263
key_length= create_table_def_key(session, key, table_list, 0);
2234
2264
pthread_mutex_lock(&LOCK_open);
2235
if (!(share= (get_table_share(thd, table_list, key, key_length, 0,
2265
if (!(share= (get_table_share(session, table_list, key, key_length, 0,
2238
2268
pthread_mutex_unlock(&LOCK_open);
2239
2269
return(0); // Can't open frm file
2242
if (open_table_from_share(thd, share, "", 0, 0, 0, &tmp_table, OTM_OPEN))
2272
if (open_table_from_share(session, share, "", 0, 0, 0, &tmp_table, OTM_OPEN))
2244
2274
release_table_share(share, RELEASE_NORMAL);
2245
2275
pthread_mutex_unlock(&LOCK_open);
2273
2303
Check if this is a table type that stores index and data separately,
2274
2304
like ISAM or MyISAM. We assume fixed order of engine file name
2275
2305
extentions array. First element of engine file name extentions array
2276
is meta/index file extention. Second element - data file extention.
2306
is meta/index file extention. Second element - data file extention.
2278
2308
ext= table->file->bas_ext();
2279
2309
if (!ext[0] || !ext[1])
2280
2310
goto end; // No data file
2282
2312
// Name of data file
2283
strxmov(from, table->s->normalized_path.str, ext[1], NullS);
2313
sprintf(from,"%s%s", table->s->normalized_path.str, ext[1]);
2284
2314
if (stat(from, &stat_info))
2285
2315
goto end; // Can't use USE_FRM flag
2287
snprintf(tmp, sizeof(tmp), "%s-%lx_%lx",
2288
from, current_pid, thd->thread_id);
2317
snprintf(tmp, sizeof(tmp), "%s-%lx_%"PRIx64,
2318
from, (unsigned long)current_pid, session->thread_id);
2290
2320
/* If we could open the table, close it */
2291
2321
if (table_list->table)
2293
2323
pthread_mutex_lock(&LOCK_open);
2294
close_cached_table(thd, table);
2324
close_cached_table(session, table);
2295
2325
pthread_mutex_unlock(&LOCK_open);
2297
if (lock_and_wait_for_table_name(thd,table_list))
2327
if (lock_and_wait_for_table_name(session,table_list))
2302
2332
if (my_rename(from, tmp, MYF(MY_WME)))
2304
2334
pthread_mutex_lock(&LOCK_open);
2305
unlock_table_name(thd, table_list);
2335
unlock_table_name(session, table_list);
2306
2336
pthread_mutex_unlock(&LOCK_open);
2307
error= send_check_errmsg(thd, table_list, "repair",
2337
error= send_check_errmsg(session, table_list, "repair",
2308
2338
"Failed renaming data file");
2311
if (mysql_truncate(thd, table_list, 1))
2341
if (mysql_truncate(session, table_list, 1))
2313
2343
pthread_mutex_lock(&LOCK_open);
2314
unlock_table_name(thd, table_list);
2344
unlock_table_name(session, table_list);
2315
2345
pthread_mutex_unlock(&LOCK_open);
2316
error= send_check_errmsg(thd, table_list, "repair",
2346
error= send_check_errmsg(session, table_list, "repair",
2317
2347
"Failed generating table from .frm file");
2320
2350
if (my_rename(tmp, from, MYF(MY_WME)))
2322
2352
pthread_mutex_lock(&LOCK_open);
2323
unlock_table_name(thd, table_list);
2353
unlock_table_name(session, table_list);
2324
2354
pthread_mutex_unlock(&LOCK_open);
2325
error= send_check_errmsg(thd, table_list, "repair",
2355
error= send_check_errmsg(session, table_list, "repair",
2326
2356
"Failed restoring .MYD file");
2359
2389
false Message sent to net (admin operation went ok)
2360
true Message should be sent by caller
2390
true Message should be sent by caller
2361
2391
(admin operation or network communication failed)
2363
static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
2393
static bool mysql_admin_table(Session* session, TableList* tables,
2364
2394
HA_CHECK_OPT* check_opt,
2365
2395
const char *operator_name,
2366
2396
thr_lock_type lock_type,
2367
2397
bool open_for_modify,
2368
2398
bool no_warnings_for_error,
2369
uint extra_open_options,
2370
int (*prepare_func)(THD *, TABLE_LIST *,
2399
uint32_t extra_open_options,
2400
int (*prepare_func)(Session *, TableList *,
2371
2401
HA_CHECK_OPT *),
2372
int (handler::*operator_func)(THD *,
2402
int (handler::*operator_func)(Session *,
2373
2403
HA_CHECK_OPT *))
2376
SELECT_LEX *select= &thd->lex->select_lex;
2406
SELECT_LEX *select= &session->lex->select_lex;
2377
2407
List<Item> field_list;
2379
Protocol *protocol= thd->protocol;
2409
Protocol *protocol= session->protocol;
2410
LEX *lex= session->lex;
2381
2411
int result_code= 0;
2382
2412
const CHARSET_INFO * const cs= system_charset_info;
2384
if (end_active_trans(thd))
2414
if (end_active_trans(session))
2386
2416
field_list.push_back(item = new Item_empty_string("Table",
2387
2417
NAME_CHAR_LEN * 2,
2405
2435
char* db = table->db;
2406
2436
bool fatal_error=0;
2408
strxmov(table_name, db, ".", table->table_name, NullS);
2409
thd->open_options|= extra_open_options;
2438
sprintf(table_name,"%s.%s",db,table->table_name);
2439
session->open_options|= extra_open_options;
2410
2440
table->lock_type= lock_type;
2411
2441
/* open only one table from local list of command */
2413
TABLE_LIST *save_next_global, *save_next_local;
2443
TableList *save_next_global, *save_next_local;
2414
2444
save_next_global= table->next_global;
2415
2445
table->next_global= 0;
2416
2446
save_next_local= table->next_local;
2417
2447
table->next_local= 0;
2418
select->table_list.first= (uchar*)table;
2448
select->table_list.first= (unsigned char*)table;
2420
2450
Time zone tables and SP tables can be add to lex->query_tables list,
2421
2451
so it have to be prepared.
2425
2455
lex->query_tables= table;
2426
2456
lex->query_tables_last= &table->next_global;
2427
2457
lex->query_tables_own_last= 0;
2428
thd->no_warnings_for_error= no_warnings_for_error;
2429
table->required_type=FRMTYPE_TABLE;
2458
session->no_warnings_for_error= no_warnings_for_error;
2431
open_and_lock_tables(thd, table);
2432
thd->no_warnings_for_error= 0;
2460
open_and_lock_tables(session, table);
2461
session->no_warnings_for_error= 0;
2433
2462
table->next_global= save_next_global;
2434
2463
table->next_local= save_next_local;
2435
thd->open_options&= ~extra_open_options;
2464
session->open_options&= ~extra_open_options;
2438
2467
if (prepare_func)
2440
switch ((*prepare_func)(thd, table, check_opt)) {
2469
switch ((*prepare_func)(session, table, check_opt)) {
2441
2470
case 1: // error, message written to net
2442
ha_autocommit_or_rollback(thd, 1);
2443
end_trans(thd, ROLLBACK);
2444
close_thread_tables(thd);
2471
ha_autocommit_or_rollback(session, 1);
2472
end_trans(session, ROLLBACK);
2473
close_thread_tables(session);
2446
2475
case -1: // error, message could be written to net
2447
2476
/* purecov: begin inspected */
2495
2524
if (lock_type == TL_WRITE && table->table->s->version)
2497
2526
pthread_mutex_lock(&LOCK_open);
2498
const char *old_message=thd->enter_cond(&COND_refresh, &LOCK_open,
2527
const char *old_message=session->enter_cond(&COND_refresh, &LOCK_open,
2499
2528
"Waiting to get writelock");
2500
mysql_lock_abort(thd,table->table, true);
2501
remove_table_from_cache(thd, table->table->s->db.str,
2529
mysql_lock_abort(session,table->table, true);
2530
remove_table_from_cache(session, table->table->s->db.str,
2502
2531
table->table->s->table_name.str,
2503
2532
RTFC_WAIT_OTHER_THREAD_FLAG |
2504
2533
RTFC_CHECK_KILLED_FLAG);
2505
thd->exit_cond(old_message);
2534
session->exit_cond(old_message);
2535
if (session->killed)
2508
2537
open_for_modify= 0;
2522
2551
/* purecov: end */
2525
if (operator_func == &handler::ha_repair &&
2526
!(check_opt->sql_flags & TT_USEFRM))
2554
if (operator_func == &handler::ha_repair && !(check_opt->use_frm))
2528
2556
if ((table->table->file->check_old_types() == HA_ADMIN_NEEDS_ALTER) ||
2529
2557
(table->table->file->ha_check_for_upgrade(check_opt) ==
2530
2558
HA_ADMIN_NEEDS_ALTER))
2532
ha_autocommit_or_rollback(thd, 1);
2533
close_thread_tables(thd);
2534
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
2535
result_code= mysql_recreate_table(thd, table);
2536
reenable_binlog(thd);
2560
ha_autocommit_or_rollback(session, 1);
2561
close_thread_tables(session);
2562
result_code= mysql_recreate_table(session, table);
2538
2564
mysql_recreate_table() can push OK or ERROR.
2539
2565
Clear 'OK' status. If there is an error, keep it:
2540
we will store the error message in a result set row
2566
we will store the error message in a result set row
2541
2567
and then clear.
2543
if (thd->main_da.is_ok())
2544
thd->main_da.reset_diagnostics_area();
2569
if (session->main_da.is_ok())
2570
session->main_da.reset_diagnostics_area();
2545
2571
goto send_result;
2549
result_code = (table->table->file->*operator_func)(thd, check_opt);
2575
result_code = (table->table->file->*operator_func)(session, check_opt);
2553
2579
lex->cleanup_after_one_table_open();
2554
thd->clear_error(); // these errors shouldn't get client
2580
session->clear_error(); // these errors shouldn't get client
2556
List_iterator_fast<DRIZZLE_ERROR> it(thd->warn_list);
2582
List_iterator_fast<DRIZZLE_ERROR> it(session->warn_list);
2557
2583
DRIZZLE_ERROR *err;
2558
2584
while ((err= it++))
2579
2605
case HA_ADMIN_NOT_IMPLEMENTED:
2581
2607
char buf[ERRMSGSIZE+20];
2582
uint length=snprintf(buf, ERRMSGSIZE,
2608
uint32_t length=snprintf(buf, ERRMSGSIZE,
2583
2609
ER(ER_CHECK_NOT_IMPLEMENTED), operator_name);
2584
2610
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
2585
2611
protocol->store(buf, length, system_charset_info);
2589
case HA_ADMIN_NOT_BASE_TABLE:
2591
char buf[ERRMSGSIZE+20];
2592
uint length= snprintf(buf, ERRMSGSIZE,
2593
ER(ER_BAD_TABLE_ERROR), table_name);
2594
protocol->store(STRING_WITH_LEN("note"), system_charset_info);
2595
protocol->store(buf, length, system_charset_info);
2599
2615
case HA_ADMIN_OK:
2600
2616
protocol->store(STRING_WITH_LEN("status"), system_charset_info);
2601
2617
protocol->store(STRING_WITH_LEN("OK"), system_charset_info);
2638
2654
This is currently used only by InnoDB. ha_innobase::optimize() answers
2639
"try with alter", so here we close the table, do an ALTER TABLE,
2655
"try with alter", so here we close the table, do an ALTER Table,
2640
2656
reopen the table and do ha_innobase::analyze() on it.
2642
ha_autocommit_or_rollback(thd, 0);
2643
close_thread_tables(thd);
2644
TABLE_LIST *save_next_local= table->next_local,
2658
ha_autocommit_or_rollback(session, 0);
2659
close_thread_tables(session);
2660
TableList *save_next_local= table->next_local,
2645
2661
*save_next_global= table->next_global;
2646
2662
table->next_local= table->next_global= 0;
2647
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
2648
result_code= mysql_recreate_table(thd, table);
2649
reenable_binlog(thd);
2663
result_code= mysql_recreate_table(session, table);
2651
2665
mysql_recreate_table() can push OK or ERROR.
2652
2666
Clear 'OK' status. If there is an error, keep it:
2653
we will store the error message in a result set row
2667
we will store the error message in a result set row
2654
2668
and then clear.
2656
if (thd->main_da.is_ok())
2657
thd->main_da.reset_diagnostics_area();
2658
ha_autocommit_or_rollback(thd, 0);
2659
close_thread_tables(thd);
2670
if (session->main_da.is_ok())
2671
session->main_da.reset_diagnostics_area();
2672
ha_autocommit_or_rollback(session, 0);
2673
close_thread_tables(session);
2660
2674
if (!result_code) // recreation went ok
2662
if ((table->table= open_ltable(thd, table, lock_type, 0)) &&
2663
((result_code= table->table->file->ha_analyze(thd, check_opt)) > 0))
2676
if ((table->table= open_ltable(session, table, lock_type, 0)) &&
2677
((result_code= table->table->file->ha_analyze(session, check_opt)) > 0))
2664
2678
result_code= 0; // analyze went ok
2666
2680
if (result_code) // either mysql_recreate_table or analyze failed
2668
assert(thd->is_error());
2669
if (thd->is_error())
2682
assert(session->is_error());
2683
if (session->is_error())
2671
const char *err_msg= thd->main_da.message();
2685
const char *err_msg= session->main_da.message();
2686
if (!session->vio_ok())
2674
sql_print_error(err_msg);
2688
errmsg_printf(ERRMSG_LVL_ERROR, "%s", err_msg);
2738
2744
pthread_mutex_lock(&LOCK_open);
2739
remove_table_from_cache(thd, table->table->s->db.str,
2745
remove_table_from_cache(session, table->table->s->db.str,
2740
2746
table->table->s->table_name.str, RTFC_NO_FLAG);
2741
2747
pthread_mutex_unlock(&LOCK_open);
2745
ha_autocommit_or_rollback(thd, 0);
2746
end_trans(thd, COMMIT);
2747
close_thread_tables(thd);
2751
ha_autocommit_or_rollback(session, 0);
2752
end_trans(session, COMMIT);
2753
close_thread_tables(session);
2748
2754
table->table=0; // For query cache
2749
2755
if (protocol->write())
2757
ha_autocommit_or_rollback(thd, 1);
2758
end_trans(thd, ROLLBACK);
2759
close_thread_tables(thd); // Shouldn't be needed
2763
ha_autocommit_or_rollback(session, 1);
2764
end_trans(session, ROLLBACK);
2765
close_thread_tables(session); // Shouldn't be needed
2761
2767
table->table=0;
2766
bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
2772
bool mysql_repair_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2768
return(mysql_admin_table(thd, tables, check_opt,
2769
"repair", TL_WRITE, 1,
2770
test(check_opt->sql_flags & TT_USEFRM),
2772
&prepare_for_repair,
2773
&handler::ha_repair));
2774
return(mysql_admin_table(session, tables, check_opt,
2775
"repair", TL_WRITE, 1,
2778
&prepare_for_repair,
2779
&handler::ha_repair));
2777
bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
2783
bool mysql_optimize_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
2779
return(mysql_admin_table(thd, tables, check_opt,
2780
"optimize", TL_WRITE, 1,0,0,0,
2781
&handler::ha_optimize));
2785
return(mysql_admin_table(session, tables, check_opt,
2786
"optimize", TL_WRITE, 1,0,0,0,
2787
&handler::ha_optimize));
2881
2887
local_create_info.default_table_charset=default_charset_info;
2882
2888
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
2883
2889
schema_table->table->use_all_columns();
2884
if (mysql_prepare_alter_table(thd, schema_table->table,
2890
if (mysql_prepare_alter_table(session, schema_table->table,
2885
2891
&local_create_info, &alter_info))
2887
if (mysql_prepare_create_table(thd, &local_create_info, &alter_info,
2894
if (mysql_prepare_create_table(session, &local_create_info, &alter_info,
2888
2895
tmp_table, &db_options,
2889
2896
schema_table->table->file,
2890
2897
&schema_table->table->s->key_info, &keys, 0))
2892
2900
local_create_info.max_rows= 0;
2893
if (mysql_create_frm(thd, dst_path, NullS, NullS,
2901
if (rea_create_table(session, dst_path, "system_tmp", "system_stupid_i_s_fix_nonsense",
2894
2902
&local_create_info, alter_info.create_list,
2895
2903
keys, schema_table->table->s->key_info,
2896
schema_table->table->file))
2904
schema_table->table->file, true))
2903
2911
Create a table identical to the specified table
2906
2914
mysql_create_like_table()
2915
session Thread object
2908
2916
table Table list element for target table
2909
2917
src_table Table list element for source table
2910
2918
create_info Create info
2939
2943
we ensure that our statement is properly isolated from all concurrent
2940
2944
operations which matter.
2942
if (open_tables(thd, &src_table, ¬_used, 0))
2946
if (open_tables(session, &src_table, ¬_used, 0))
2945
strxmov(src_path, src_table->table->s->path.str, reg_ext, NullS);
2949
sprintf(src_path,"%s%s",src_table->table->s->path.str, reg_ext);
2948
2952
Check that destination tables does not exist. Note that its name
2949
2953
was already checked when it was added to the table list.
2951
2955
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
2953
if (find_temporary_table(thd, db, table_name))
2957
if (find_temporary_table(session, db, table_name))
2954
2958
goto table_exists;
2955
dst_path_length= build_tmptable_filename(thd, dst_path, sizeof(dst_path));
2959
dst_path_length= build_tmptable_filename(session, dst_path, sizeof(dst_path));
2956
2960
create_info->table_options|= HA_CREATE_DELAY_KEY_WRITE;
2960
if (lock_table_name_if_not_cached(thd, db, table_name, &name_lock))
2964
if (lock_table_name_if_not_cached(session, db, table_name, &name_lock))
2962
2966
if (!name_lock)
2963
2967
goto table_exists;
2980
2984
Also some engines (e.g. NDB cluster) require that LOCK_open should be held
2981
2985
during the call to ha_create_table(). See bug #28614 for more info.
2983
VOID(pthread_mutex_lock(&LOCK_open));
2987
pthread_mutex_lock(&LOCK_open);
2984
2988
if (src_table->schema_table)
2986
if (mysql_create_like_schema_frm(thd, src_table, dst_path, create_info))
2990
if (mysql_create_like_schema_frm(session, src_table, dst_path, create_info))
2988
VOID(pthread_mutex_unlock(&LOCK_open));
2992
pthread_mutex_unlock(&LOCK_open);
2992
else if (my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE)))
2994
if (my_errno == ENOENT)
2995
my_error(ER_BAD_DB_ERROR,MYF(0),db);
2997
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
2998
VOID(pthread_mutex_unlock(&LOCK_open));
2998
int frmcopyr= my_copy(src_path, dst_path, MYF(MY_DONT_OVERWRITE_FILE));
3000
string dfesrc(src_path);
3001
string dfedst(dst_path);
3003
dfesrc.replace(dfesrc.find(".frm"), 4, ".dfe" );
3004
dfedst.replace(dfedst.find(".frm"), 4, ".dfe" );
3006
int dfecopyr= my_copy(dfesrc.c_str(), dfedst.c_str(),
3007
MYF(MY_DONT_OVERWRITE_FILE));
3009
if(frmcopyr || dfecopyr) // FIXME: should handle only one fail.
3011
if (my_errno == ENOENT)
3012
my_error(ER_BAD_DB_ERROR,MYF(0),db);
3014
my_error(ER_CANT_CREATE_FILE,MYF(0),dst_path,my_errno);
3015
pthread_mutex_unlock(&LOCK_open);
3005
3023
and temporary tables).
3007
3025
dst_path[dst_path_length - reg_ext_length]= '\0'; // Remove .frm
3008
if (thd->variables.keep_files_on_create)
3026
if (session->variables.keep_files_on_create)
3009
3027
create_info->options|= HA_CREATE_KEEP_FILES;
3010
err= ha_create_table(thd, dst_path, db, table_name, create_info, 1);
3011
VOID(pthread_mutex_unlock(&LOCK_open));
3028
err= ha_create_table(session, dst_path, db, table_name, create_info, 1);
3029
pthread_mutex_unlock(&LOCK_open);
3013
3031
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
3015
if (err || !open_temporary_table(thd, dst_path, db, table_name, 1,
3033
if (err || !open_temporary_table(session, dst_path, db, table_name, 1,
3018
3036
(void) rm_temporary_table(create_info->db_type,
3019
dst_path, false); /* purecov: inspected */
3020
3038
goto err; /* purecov: inspected */
3063
3080
of this function.
3065
3082
table->table= name_lock;
3066
VOID(pthread_mutex_lock(&LOCK_open));
3067
if (reopen_name_locked_table(thd, table, false))
3083
pthread_mutex_lock(&LOCK_open);
3084
if (reopen_name_locked_table(session, table, false))
3069
VOID(pthread_mutex_unlock(&LOCK_open));
3086
pthread_mutex_unlock(&LOCK_open);
3072
VOID(pthread_mutex_unlock(&LOCK_open));
3089
pthread_mutex_unlock(&LOCK_open);
3074
int result= store_create_info(thd, table, &query,
3091
int result= store_create_info(session, table, &query,
3077
3094
assert(result == 0); // store_create_info() always return 0
3078
write_bin_log(thd, true, query.ptr(), query.length());
3095
write_bin_log(session, true, query.ptr(), query.length());
3081
write_bin_log(thd, true, thd->query, thd->query_length);
3098
write_bin_log(session, true, session->query, session->query_length);
3084
3101
Case 3 and 4 does nothing under RBR
3088
write_bin_log(thd, true, thd->query, thd->query_length);
3109
3124
pthread_mutex_lock(&LOCK_open);
3110
unlink_open_table(thd, name_lock, false);
3125
unlink_open_table(session, name_lock, false);
3111
3126
pthread_mutex_unlock(&LOCK_open);
3117
bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
3132
bool mysql_analyze_table(Session* session, TableList* tables, HA_CHECK_OPT* check_opt)
3119
3134
thr_lock_type lock_type = TL_READ_NO_INSERT;
3121
return(mysql_admin_table(thd, tables, check_opt,
3136
return(mysql_admin_table(session, tables, check_opt,
3122
3137
"analyze", lock_type, 1, 0, 0, 0,
3123
3138
&handler::ha_analyze));
3127
bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
3142
bool mysql_check_table(Session* session, TableList* tables,HA_CHECK_OPT* check_opt)
3129
3144
thr_lock_type lock_type = TL_READ_NO_INSERT;
3131
return(mysql_admin_table(thd, tables, check_opt,
3146
return(mysql_admin_table(session, tables, check_opt,
3132
3147
"check", lock_type,
3133
3148
0, 0, HA_OPEN_FOR_REPAIR, 0,
3134
3149
&handler::ha_check));
3158
3173
We set this flag so that ha_innobase::open and ::external_lock() do
3159
3174
not complain when we lock the table
3161
thd->tablespace_op= true;
3162
if (!(table=open_ltable(thd, table_list, TL_WRITE, 0)))
3176
session->tablespace_op= true;
3177
if (!(table=open_ltable(session, table_list, TL_WRITE, 0)))
3164
thd->tablespace_op=false;
3179
session->tablespace_op=false;
3168
3183
error= table->file->ha_discard_or_import_tablespace(discard);
3170
thd_proc_info(thd, "end");
3185
session->set_proc_info("end");
3175
/* The ALTER TABLE is always in its own transaction */
3176
error = ha_autocommit_or_rollback(thd, 0);
3177
if (end_active_trans(thd))
3190
/* The ALTER Table is always in its own transaction */
3191
error = ha_autocommit_or_rollback(session, 0);
3192
if (end_active_trans(session))
3181
write_bin_log(thd, false, thd->query, thd->query_length);
3196
write_bin_log(session, false, session->query, session->query_length);
3184
ha_autocommit_or_rollback(thd, error);
3185
thd->tablespace_op=false;
3199
ha_autocommit_or_rollback(session, error);
3200
session->tablespace_op=false;
3187
3202
if (error == 0)
3193
3208
table->file->print_error(error, MYF(0));
3332
3342
Some very basic checks. If number of fields changes, or the
3333
handler, we need to run full ALTER TABLE. In the future
3343
handler, we need to run full ALTER Table. In the future
3334
3344
new fields can be added and old dropped without copy, but
3337
Test also that engine was not given during ALTER TABLE, or
3347
Test also that engine was not given during ALTER Table, or
3338
3348
we are force to run regular alter table (copy).
3339
E.g. ALTER TABLE tbl_name ENGINE=MyISAM.
3349
E.g. ALTER Table tbl_name ENGINE=MyISAM.
3341
3351
For the following ones we also want to run regular alter table:
3342
ALTER TABLE tbl_name ORDER BY ..
3343
ALTER TABLE tbl_name CONVERT TO CHARACTER SET ..
3352
ALTER Table tbl_name order_st BY ..
3353
ALTER Table tbl_name CONVERT TO CHARACTER SET ..
3345
3355
At the moment we can't handle altering temporary tables without a copy.
3346
We also test if OPTIMIZE TABLE was given and was mapped to alter table.
3356
We also test if OPTIMIZE Table was given and was mapped to alter table.
3347
3357
In that case we always do full copy.
3349
3359
There was a bug prior to mysql-4.0.25. Number of null fields was
3757
3764
HA_CREATE_INFO altered_create_info(*create_info);
3758
TABLE *altered_table;
3765
Table *altered_table;
3759
3766
char tmp_name[80];
3760
3767
char path[FN_REFLEN];
3762
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx",
3763
tmp_file_prefix, current_pid, thd->thread_id);
3769
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64,
3770
TMP_FILE_PREFIX, (unsigned long)current_pid, session->thread_id);
3764
3771
/* Safety fix for InnoDB */
3765
3772
if (lower_case_table_names)
3766
3773
my_casedn_str(files_charset_info, tmp_name);
3767
3774
altered_create_info.options&= ~HA_LEX_CREATE_TMP_TABLE;
3768
altered_create_info.frm_only= 1;
3769
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
3776
if ((error= create_temporary_table(session, table, new_db, tmp_name,
3770
3777
&altered_create_info,
3771
3778
alter_info, db_change)))
3867
3874
table->s->table_name.str, FN_FROM_IS_TMP))
3870
VOID(pthread_mutex_unlock(&LOCK_open));
3877
pthread_mutex_unlock(&LOCK_open);
3873
3880
broadcast_refresh();
3874
VOID(pthread_mutex_unlock(&LOCK_open));
3881
pthread_mutex_unlock(&LOCK_open);
3877
The ALTER TABLE is always in its own transaction.
3884
The ALTER Table is always in its own transaction.
3878
3885
Commit must not be called while LOCK_open is locked. It could call
3879
3886
wait_if_global_read_lock(), which could create a deadlock if called
3880
3887
with LOCK_open.
3882
error= ha_autocommit_or_rollback(thd, 0);
3889
error= ha_autocommit_or_rollback(session, 0);
3891
if (ha_commit(session))
3890
VOID(pthread_mutex_lock(&LOCK_open));
3897
pthread_mutex_lock(&LOCK_open);
3891
3898
if (reopen_table(table))
3896
VOID(pthread_mutex_unlock(&LOCK_open));
3903
pthread_mutex_unlock(&LOCK_open);
3897
3904
t_table= table;
3900
3907
Tell the handler that the changed frm is on disk and table
3901
3908
has been re-opened
3903
if ((error= t_table->file->alter_table_phase3(thd, t_table)))
3910
if ((error= t_table->file->alter_table_phase3(session, t_table)))
3909
3916
We are going to reopen table down on the road, so we have to restore
3910
state of the TABLE object which we used for obtaining of handler
3917
state of the Table object which we used for obtaining of handler
3911
3918
object to make it suitable for reopening.
3913
3920
assert(t_table == table);
3914
3921
table->open_placeholder= 1;
3915
VOID(pthread_mutex_lock(&LOCK_open));
3922
pthread_mutex_lock(&LOCK_open);
3916
3923
close_handle_and_leave_table_as_lock(table);
3917
VOID(pthread_mutex_unlock(&LOCK_open));
3924
pthread_mutex_unlock(&LOCK_open);
3928
Prepare column and key definitions for CREATE TABLE in ALTER TABLE.
3935
Prepare column and key definitions for CREATE TABLE in ALTER Table.
3930
This function transforms parse output of ALTER TABLE - lists of
3937
This function transforms parse output of ALTER Table - lists of
3931
3938
columns and keys to add, drop or modify into, essentially,
3932
3939
CREATE TABLE definition - a list of columns and keys of the new
3933
3940
table. While doing so, it also performs some (bug not all)
3934
3941
semantic checks.
3936
3943
This function is invoked when we know that we're going to
3937
perform ALTER TABLE via a temporary table -- i.e. fast ALTER TABLE
3944
perform ALTER Table via a temporary table -- i.e. fast ALTER Table
3938
3945
is not possible, perhaps because the ALTER statement contains
3939
3946
instructions that require change in table data, not only in
3940
3947
table definition or indexes.
3942
@param[in,out] thd thread handle. Used as a memory pool
3949
@param[in,out] session thread handle. Used as a memory pool
3943
3950
and source of environment information.
3944
3951
@param[in] table the source table, open and locked
3945
3952
Used as an interface to the storage engine
3946
3953
to acquire additional information about
3947
3954
the original table.
3948
@param[in,out] create_info A blob with CREATE/ALTER TABLE
3955
@param[in,out] create_info A blob with CREATE/ALTER Table
3950
3957
@param[in,out] alter_info Another blob with ALTER/CREATE parameters.
3951
3958
Originally create_info was used only in
3952
CREATE TABLE and alter_info only in ALTER TABLE.
3959
CREATE TABLE and alter_info only in ALTER Table.
3953
3960
But since ALTER might end-up doing CREATE,
3954
3961
this distinction is gone and we just carry
3955
3962
around two structures.
4339
4353
table_list The table to change.
4340
4354
alter_info Lists of fields, keys to be changed, added
4342
order_num How many ORDER BY fields has been specified.
4343
order List of fields to ORDER BY.
4344
ignore Whether we have ALTER IGNORE TABLE
4356
order_num How many order_st BY fields has been specified.
4357
order List of fields to order_st BY.
4358
ignore Whether we have ALTER IGNORE Table
4347
4361
This is a veery long function and is everything but the kitchen sink :)
4348
It is used to alter a table and not only by ALTER TABLE but also
4362
It is used to alter a table and not only by ALTER Table but also
4349
4363
CREATE|DROP INDEX are mapped on this function.
4351
When the ALTER TABLE statement just does a RENAME or ENABLE|DISABLE KEYS,
4365
When the ALTER Table statement just does a RENAME or ENABLE|DISABLE KEYS,
4352
4366
or both, then this function short cuts its operation by renaming
4353
4367
the table and/or enabling/disabling the keys. In this case, the FRM is
4354
4368
not changed, directly by mysql_alter_table. However, if there is a
4371
bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
4385
bool mysql_alter_table(Session *session,char *new_db, char *new_name,
4372
4386
HA_CREATE_INFO *create_info,
4373
TABLE_LIST *table_list,
4387
TableList *table_list,
4374
4388
Alter_info *alter_info,
4375
uint order_num, ORDER *order, bool ignore)
4389
uint32_t order_num, order_st *order, bool ignore)
4377
TABLE *table, *new_table=0, *name_lock= 0;;
4391
Table *table, *new_table=0, *name_lock= 0;;
4392
string new_name_str;
4379
4394
char tmp_name[80],old_name[32],new_name_buff[FN_REFLEN];
4380
4395
char new_alias_buff[FN_REFLEN], *table_name, *db, *new_alias, *alias;
4381
4396
char path[FN_REFLEN];
4382
4397
ha_rows copied= 0,deleted= 0;
4383
4398
handlerton *old_db_type, *new_db_type, *save_old_db_type;
4384
legacy_db_type table_type;
4385
frm_type_enum frm_type;
4400
new_name_buff[0]= '\0';
4387
4402
if (table_list && table_list->schema_table)
4389
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.str);
4404
my_error(ER_DBACCESS_DENIED_ERROR, MYF(0), "", "", INFORMATION_SCHEMA_NAME.c_str());
4404
4419
build_table_filename(path, sizeof(path), db, table_name, "", 0);
4406
mysql_ha_rm_tables(thd, table_list, false);
4421
mysql_ha_rm_tables(session, table_list, false);
4408
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER TABLE */
4423
/* DISCARD/IMPORT TABLESPACE is always alone in an ALTER Table */
4409
4424
if (alter_info->tablespace_op != NO_TABLESPACE_OP)
4410
4425
/* Conditionally writes to binlog. */
4411
return(mysql_discard_or_import_tablespace(thd,table_list,
4426
return(mysql_discard_or_import_tablespace(session,table_list,
4412
4427
alter_info->tablespace_op));
4413
strxnmov(new_name_buff, sizeof (new_name_buff) - 1, mysql_data_home, "/", db,
4414
"/", table_name, reg_ext, NullS);
4415
(void) unpack_filename(new_name_buff, new_name_buff);
4429
oss << drizzle_data_home << "/" << db << "/" << table_name << reg_ext;
4431
(void) unpack_filename(new_name_buff, oss.str().c_str());
4417
4433
If this is just a rename of a view, short cut to the
4418
4434
following scenario: 1) lock LOCK_open 2) do a RENAME
4419
4435
2) unlock LOCK_open.
4420
4436
This is a copy-paste added to make sure
4421
ALTER (sic:) TABLE .. RENAME works for views. ALTER VIEW is handled
4437
ALTER (sic:) Table .. RENAME works for views. ALTER VIEW is handled
4422
4438
as an independent branch in mysql_execute_command. The need
4423
for a copy-paste arose because the main code flow of ALTER TABLE
4439
for a copy-paste arose because the main code flow of ALTER Table
4424
4440
... RENAME tries to use open_ltable, which does not work for views
4425
4441
(open_ltable was never modified to merge table lists of child tables
4426
4442
into the main table list, like open_tables does).
4427
4443
This code is wrong and will be removed, please do not copy.
4429
frm_type= mysql_frm_type(thd, new_name_buff, &table_type);
4431
if (!(table= open_n_lock_single_table(thd, table_list, TL_WRITE_ALLOW_READ)))
4446
if (!(table= open_n_lock_single_table(session, table_list, TL_WRITE_ALLOW_READ)))
4433
4448
table->use_all_columns();
4435
4450
/* Check that we are not trying to rename to an existing table */
4438
stpcpy(new_name_buff,new_name);
4439
stpcpy(new_alias= new_alias_buff, new_name);
4453
strcpy(new_name_buff,new_name);
4454
strcpy(new_alias= new_alias_buff, new_name);
4440
4455
if (lower_case_table_names)
4442
4457
if (lower_case_table_names != 2)
4444
my_casedn_str(files_charset_info, new_name_buff);
4445
new_alias= new_name; // Create lower case table name
4459
my_casedn_str(files_charset_info, new_name_buff);
4460
new_alias= new_name; // Create lower case table name
4447
4462
my_casedn_str(files_charset_info, new_name);
4532
4547
wait_while_table_is_used() ensures that table being altered is
4533
opened only by this thread and that TABLE::TABLE_SHARE::version
4534
of TABLE object corresponding to this table is 0.
4548
opened only by this thread and that Table::TABLE_SHARE::version
4549
of Table object corresponding to this table is 0.
4535
4550
The latter guarantees that no DML statement will open this table
4536
until ALTER TABLE finishes (i.e. until close_thread_tables())
4551
until ALTER Table finishes (i.e. until close_thread_tables())
4537
4552
while the fact that the table is still open gives us protection
4538
4553
from concurrent DDL statements.
4540
VOID(pthread_mutex_lock(&LOCK_open));
4541
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4542
VOID(pthread_mutex_unlock(&LOCK_open));
4555
pthread_mutex_lock(&LOCK_open);
4556
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
4557
pthread_mutex_unlock(&LOCK_open);
4543
4558
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4544
4559
/* COND_refresh will be signaled in close_thread_tables() */
4547
VOID(pthread_mutex_lock(&LOCK_open));
4548
wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN);
4549
VOID(pthread_mutex_unlock(&LOCK_open));
4562
pthread_mutex_lock(&LOCK_open);
4563
wait_while_table_is_used(session, table, HA_EXTRA_FORCE_REOPEN);
4564
pthread_mutex_unlock(&LOCK_open);
4550
4565
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
4551
4566
/* COND_refresh will be signaled in close_thread_tables() */
4649
4664
new_db_type= create_info->db_type;
4651
if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
4666
if (mysql_prepare_alter_table(session, table, create_info, alter_info))
4654
set_table_default_charset(thd, create_info, db);
4657
if (thd->variables.old_alter_table
4669
set_table_default_charset(session, create_info, db);
4671
if (session->variables.old_alter_table
4658
4672
|| (table->s->db_type() != create_info->db_type)
4661
4675
if (alter_info->build_method == HA_BUILD_ONLINE)
4663
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4677
my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
4666
4680
alter_info->build_method= HA_BUILD_OFFLINE;
4731
4745
case HA_ALTER_NOT_SUPPORTED:
4732
4746
if (alter_info->build_method == HA_BUILD_ONLINE)
4734
my_error(ER_NOT_SUPPORTED_YET, MYF(0), thd->query);
4735
close_temporary_table(thd, altered_table, 1, 1);
4748
my_error(ER_NOT_SUPPORTED_YET, MYF(0), session->query);
4749
close_temporary_table(session, altered_table, 1, 1);
4738
4752
need_copy_table= true;
4740
4754
case HA_ALTER_ERROR:
4742
close_temporary_table(thd, altered_table, 1, 1);
4756
close_temporary_table(session, altered_table, 1, 1);
4747
/* TODO need to check if changes can be handled as fast ALTER TABLE */
4761
/* TODO need to check if changes can be handled as fast ALTER Table */
4748
4762
if (!altered_table)
4749
4763
need_copy_table= true;
4751
4765
if (!need_copy_table)
4753
error= mysql_fast_or_online_alter_table(thd,
4767
error= mysql_fast_or_online_alter_table(session,
4757
4771
&ha_alter_info,
4758
4772
&ha_alter_flags,
4759
4773
alter_info->keys_onoff);
4762
mysql_unlock_tables(thd, thd->lock);
4776
mysql_unlock_tables(session, session->lock);
4765
close_temporary_table(thd, altered_table, 1, 1);
4779
close_temporary_table(session, altered_table, 1, 1);
4783
4797
if (altered_table)
4784
close_temporary_table(thd, altered_table, 1, 1);
4798
close_temporary_table(session, altered_table, 1, 1);
4787
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%lx", tmp_file_prefix,
4788
current_pid, thd->thread_id);
4801
snprintf(tmp_name, sizeof(tmp_name), "%s-%lx_%"PRIx64, TMP_FILE_PREFIX,
4802
(unsigned long)current_pid, session->thread_id);
4789
4803
/* Safety fix for innodb */
4790
4804
if (lower_case_table_names)
4791
4805
my_casedn_str(files_charset_info, tmp_name);
4794
4808
/* Create a temporary table with the new format */
4795
if ((error= create_temporary_table(thd, table, new_db, tmp_name,
4796
create_info, alter_info,
4809
if ((error= create_temporary_table(session, table, new_db, tmp_name,
4810
create_info, alter_info,
4797
4811
!strcmp(db, new_db))))
4802
4816
/* Open the table so we need to copy the data to it. */
4803
4817
if (table->s->tmp_table)
4806
4820
memset(&tbl, 0, sizeof(tbl));
4807
4821
tbl.db= new_db;
4808
4822
tbl.table_name= tbl.alias= tmp_name;
4809
/* Table is in thd->temporary_tables */
4810
new_table= open_table(thd, &tbl, thd->mem_root, (bool*) 0,
4811
DRIZZLE_LOCK_IGNORE_FLUSH);
4823
/* Table is in session->temporary_tables */
4824
new_table= open_table(session, &tbl, (bool*) 0, DRIZZLE_LOCK_IGNORE_FLUSH);
4815
char path[FN_REFLEN];
4828
char tmp_path[FN_REFLEN];
4816
4829
/* table is a normal table: Create temporary table in same directory */
4817
build_table_filename(path, sizeof(path), new_db, tmp_name, "",
4830
build_table_filename(tmp_path, sizeof(tmp_path), new_db, tmp_name, "",
4819
4832
/* Open our intermediate table */
4820
new_table=open_temporary_table(thd, path, new_db, tmp_name, 0, OTM_OPEN);
4833
new_table=open_temporary_table(session, tmp_path, new_db, tmp_name, 0, OTM_OPEN);
4822
4835
if (!new_table)
4825
4838
/* Copy the data if necessary. */
4826
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
4827
thd->cuted_fields=0L;
4828
thd_proc_info(thd, "copy to tmp table");
4839
session->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
4840
session->cuted_fields=0L;
4841
session->set_proc_info("copy to tmp table");
4829
4842
copied=deleted=0;
4831
4844
We do not copy data for MERGE tables. Only the children have data.
4863
4876
/* Close lock if this is a transactional table */
4866
mysql_unlock_tables(thd, thd->lock);
4879
mysql_unlock_tables(session, session->lock);
4869
4882
/* Remove link to old table and rename the new one */
4870
close_temporary_table(thd, table, 1, 1);
4883
close_temporary_table(session, table, 1, 1);
4871
4884
/* Should pass the 'new_name' as we store table name in the cache */
4872
if (rename_temporary_table(thd, new_table, new_db, new_name))
4885
if (rename_temporary_table(session, new_table, new_db, new_name))
4874
/* We don't replicate alter table statement on temporary tables */
4875
if (!thd->current_stmt_binlog_row_based)
4876
write_bin_log(thd, true, thd->query, thd->query_length);
4877
4887
goto end_temporary;
4901
4911
with exclusive name-locks.
4902
4912
3) Rename the old table to a temp name, rename the new one to the
4904
4) If we are under LOCK TABLES and don't do ALTER TABLE ... RENAME
4914
4) If we are under LOCK TABLES and don't do ALTER Table ... RENAME
4905
4915
we reopen new version of table.
4906
4916
5) Write statement to the binary log.
4907
6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
4917
6) If we are under LOCK TABLES and do ALTER Table ... RENAME we
4908
4918
remove name-locks from list of open tables and table cache.
4909
4919
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
4910
4920
call to remove name-locks from table cache and list of open table.
4913
thd_proc_info(thd, "rename result table");
4914
snprintf(old_name, sizeof(old_name), "%s2-%lx-%lx", tmp_file_prefix,
4915
current_pid, thd->thread_id);
4923
session->set_proc_info("rename result table");
4924
snprintf(old_name, sizeof(old_name), "%s2-%lx-%"PRIx64, TMP_FILE_PREFIX,
4925
(unsigned long)current_pid, session->thread_id);
4916
4926
if (lower_case_table_names)
4917
4927
my_casedn_str(files_charset_info, old_name);
4919
wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME);
4920
close_data_files_and_morph_locks(thd, db, table_name);
4929
wait_while_table_is_used(session, table, HA_EXTRA_PREPARE_FOR_RENAME);
4930
close_data_files_and_morph_locks(session, db, table_name);
4923
4933
save_old_db_type= old_db_type;
4942
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4952
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
4944
4954
else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
4945
4955
new_alias, FN_FROM_IS_TMP) || ((new_name != table_name || new_db != db) && 0))
4947
4957
/* Try to get everything back. */
4949
VOID(quick_rm_table(new_db_type,new_db,new_alias, 0));
4950
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
4951
VOID(mysql_rename_table(old_db_type, db, old_name, db, alias,
4959
quick_rm_table(new_db_type,new_db,new_alias, 0);
4960
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
4961
mysql_rename_table(old_db_type, db, old_name, db, alias,
4958
4968
goto err_with_placeholders;
4961
VOID(quick_rm_table(old_db_type, db, old_name, FN_IS_TMP));
4971
quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);
4964
if (thd->locked_tables && new_name == table_name && new_db == db)
4974
if (session->locked_tables && new_name == table_name && new_db == db)
4966
thd->in_lock_tables= 1;
4967
error= reopen_tables(thd, 1, 1);
4968
thd->in_lock_tables= 0;
4976
session->in_lock_tables= 1;
4977
error= reopen_tables(session, 1, 1);
4978
session->in_lock_tables= 0;
4970
4980
goto err_with_placeholders;
4972
VOID(pthread_mutex_unlock(&LOCK_open));
4974
thd_proc_info(thd, "end");
4976
ha_binlog_log_query(thd, create_info->db_type, LOGCOM_ALTER_TABLE,
4977
thd->query, thd->query_length,
4980
assert(!(mysql_bin_log.is_open() &&
4981
thd->current_stmt_binlog_row_based &&
4982
(create_info->options & HA_LEX_CREATE_TMP_TABLE)));
4983
write_bin_log(thd, true, thd->query, thd->query_length);
4985
if (ha_check_storage_engine_flag(old_db_type, HTON_FLUSH_AFTER_RENAME))
4982
pthread_mutex_unlock(&LOCK_open);
4984
session->set_proc_info("end");
4986
write_bin_log(session, true, session->query, session->query_length);
4988
if (ha_check_storage_engine_flag(old_db_type, HTON_BIT_FLUSH_AFTER_RENAME))
4988
4991
For the alter table to be properly flushed to the logs, we
4989
4992
have to open the new table. If not, we get a problem on server
4990
4993
shutdown. But we do not need to attach MERGE children.
4992
char path[FN_REFLEN];
4994
build_table_filename(path, sizeof(path), new_db, table_name, "", 0);
4995
t_table= open_temporary_table(thd, path, new_db, tmp_name, false, OTM_OPEN);
4995
char table_path[FN_REFLEN];
4997
build_table_filename(table_path, sizeof(table_path), new_db, table_name, "", 0);
4998
t_table= open_temporary_table(session, table_path, new_db, tmp_name, false, OTM_OPEN);
4998
5001
intern_close_table(t_table);
4999
my_free(t_table, MYF(0));
5002
sql_print_warning("Could not open table %s.%s after rename\n",
5005
errmsg_printf(ERRMSG_LVL_WARN,
5006
_("Could not open table %s.%s after rename\n"),
5004
5008
ha_flush_logs(old_db_type);
5006
5010
table_list->table=0; // For query cache
5008
if (thd->locked_tables && (new_name != table_name || new_db != db))
5012
if (session->locked_tables && (new_name != table_name || new_db != db))
5011
If are we under LOCK TABLES and did ALTER TABLE with RENAME we need
5015
If are we under LOCK TABLES and did ALTER Table with RENAME we need
5012
5016
to remove placeholders for the old table and for the target table
5013
5017
from the list of open tables and table cache. If we are not under
5014
5018
LOCK TABLES we can rely on close_thread_tables() doing this job.
5016
5020
pthread_mutex_lock(&LOCK_open);
5017
unlink_open_table(thd, table, false);
5018
unlink_open_table(thd, name_lock, false);
5021
unlink_open_table(session, table, false);
5022
unlink_open_table(session, name_lock, false);
5019
5023
pthread_mutex_unlock(&LOCK_open);
5023
5027
snprintf(tmp_name, sizeof(tmp_name), ER(ER_INSERT_INFO),
5024
5028
(ulong) (copied + deleted), (ulong) deleted,
5025
(ulong) thd->cuted_fields);
5026
my_ok(thd, copied + deleted, 0L, tmp_name);
5027
thd->some_tables_deleted=0;
5029
(ulong) session->cuted_fields);
5030
session->my_ok(copied + deleted, 0L, tmp_name);
5031
session->some_tables_deleted=0;
5033
5037
/* close_temporary_table() frees the new_table pointer. */
5034
close_temporary_table(thd, new_table, 1, 1);
5038
close_temporary_table(session, new_table, 1, 1);
5037
VOID(quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP));
5041
quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
5061
5065
/* Shouldn't get here. */
5064
bool save_abort_on_warning= thd->abort_on_warning;
5065
thd->abort_on_warning= true;
5066
make_truncated_value_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5068
bool save_abort_on_warning= session->abort_on_warning;
5069
session->abort_on_warning= true;
5070
make_truncated_value_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
5067
5071
f_val, strlength(f_val), t_type,
5068
5072
alter_info->datetime_field->field_name);
5069
thd->abort_on_warning= save_abort_on_warning;
5073
session->abort_on_warning= save_abort_on_warning;
5073
5077
pthread_mutex_lock(&LOCK_open);
5074
unlink_open_table(thd, name_lock, false);
5078
unlink_open_table(session, name_lock, false);
5075
5079
pthread_mutex_unlock(&LOCK_open);
5082
5086
being altered. To be safe under LOCK TABLES we should remove placeholders
5083
5087
from list of open tables list and table cache.
5085
unlink_open_table(thd, table, false);
5089
unlink_open_table(session, table, false);
5087
unlink_open_table(thd, name_lock, false);
5088
VOID(pthread_mutex_unlock(&LOCK_open));
5091
unlink_open_table(session, name_lock, false);
5092
pthread_mutex_unlock(&LOCK_open);
5091
5095
/* mysql_alter_table */
5094
copy_data_between_tables(TABLE *from,TABLE *to,
5098
copy_data_between_tables(Table *from,Table *to,
5095
5099
List<Create_field> &create,
5097
uint order_num, ORDER *order,
5101
uint32_t order_num, order_st *order,
5098
5102
ha_rows *copied,
5099
5103
ha_rows *deleted,
5100
5104
enum enum_enable_or_disable keys_onoff,
5119
5123
Turn off recovery logging since rollback of an alter table is to
5120
5124
delete the new table so there is no need to log the changes to it.
5122
5126
This needs to be done before external_lock
5124
error= ha_enable_transaction(thd, false);
5128
error= ha_enable_transaction(session, false);
5128
5132
if (!(copy= new Copy_field[to->s->fields]))
5129
5133
return(-1); /* purecov: inspected */
5131
if (to->file->ha_external_lock(thd, F_WRLCK))
5135
if (to->file->ha_external_lock(session, F_WRLCK))
5134
5138
/* We need external lock before we can disable/enable keys */
5135
5139
alter_table_manage_keys(to, from->file->indexes_are_disabled(), keys_onoff);
5137
5141
/* We can abort alter table for any table type */
5138
thd->abort_on_warning= !ignore;
5142
session->abort_on_warning= !ignore;
5140
5144
from->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
5141
5145
to->file->ha_start_bulk_insert(from->file->stats.records);
5143
save_sql_mode= thd->variables.sql_mode;
5147
save_sql_mode= session->variables.sql_mode;
5145
5149
List_iterator<Create_field> it(create);
5146
5150
Create_field *def;
5174
5169
if (to->s->primary_key != MAX_KEY && to->file->primary_key_is_clustered())
5176
5171
char warn_buff[DRIZZLE_ERRMSG_SIZE];
5177
snprintf(warn_buff, sizeof(warn_buff),
5178
"ORDER BY ignored as there is a user-defined clustered index"
5179
" in the table '%-.192s'", from->s->table_name.str);
5180
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
5172
snprintf(warn_buff, sizeof(warn_buff),
5173
_("order_st BY ignored because there is a user-defined clustered "
5174
"index in the table '%-.192s'"),
5175
from->s->table_name.str);
5176
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
5185
from->sort.io_cache=(IO_CACHE*) my_malloc(sizeof(IO_CACHE),
5186
MYF(MY_FAE | MY_ZEROFILL));
5181
from->sort.io_cache= new IO_CACHE;
5182
memset(from->sort.io_cache, 0, sizeof(IO_CACHE));
5187
5184
memset(&tables, 0, sizeof(tables));
5188
5185
tables.table= from;
5189
5186
tables.alias= tables.table_name= from->s->table_name.str;
5190
5187
tables.db= from->s->db.str;
5193
if (thd->lex->select_lex.setup_ref_array(thd, order_num) ||
5194
setup_order(thd, thd->lex->select_lex.ref_pointer_array,
5190
if (session->lex->select_lex.setup_ref_array(session, order_num) ||
5191
setup_order(session, session->lex->select_lex.ref_pointer_array,
5195
5192
&tables, fields, all_fields, order) ||
5196
5193
!(sortorder= make_unireg_sortorder(order, &length, NULL)) ||
5197
(from->sort.found_records= filesort(thd, from, sortorder, length,
5194
(from->sort.found_records= filesort(session, from, sortorder, length,
5198
5195
(SQL_SELECT *) 0, HA_POS_ERROR,
5199
5196
1, &examined_rows)) ==
5335
5333
create_info.default_table_charset=default_charset_info;
5336
5334
/* Force alter table to recreate table */
5337
5335
alter_info.flags= (ALTER_CHANGE_COLUMN | ALTER_RECREATE);
5338
return(mysql_alter_table(thd, NullS, NullS, &create_info,
5336
return(mysql_alter_table(session, NULL, NULL, &create_info,
5339
5337
table_list, &alter_info, 0,
5338
(order_st *) 0, 0));
5344
bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
5342
bool mysql_checksum_table(Session *session, TableList *tables,
5345
5343
HA_CHECK_OPT *check_opt)
5348
5346
List<Item> field_list;
5350
Protocol *protocol= thd->protocol;
5348
Protocol *protocol= session->protocol;
5352
5350
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
5353
5351
item->maybe_null= 1;
5439
5437
t->file->ha_rnd_end();
5443
close_thread_tables(thd);
5440
session->clear_error();
5441
close_thread_tables(session);
5444
5442
table->table=0; // For query cache
5446
5444
if (protocol->write())
5454
close_thread_tables(thd); // Shouldn't be needed
5452
close_thread_tables(session); // Shouldn't be needed
5456
5454
table->table=0;
5460
static bool check_engine(THD *thd, const char *table_name,
5458
static bool check_engine(Session *session, const char *table_name,
5461
5459
HA_CREATE_INFO *create_info)
5463
5461
handlerton **new_engine= &create_info->db_type;
5464
5462
handlerton *req_engine= *new_engine;
5465
5463
bool no_substitution= 1;
5466
if (!(*new_engine= ha_checktype(thd, ha_legacy_type(req_engine),
5464
if (!(*new_engine= ha_checktype(session, ha_legacy_type(req_engine),
5467
5465
no_substitution, 1)))
5470
5468
if (req_engine && req_engine != *new_engine)
5472
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
5470
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_NOTE,
5473
5471
ER_WARN_USING_OTHER_HANDLER,
5474
5472
ER(ER_WARN_USING_OTHER_HANDLER),
5475
5473
ha_resolve_storage_engine_name(*new_engine),
5478
5476
if (create_info->options & HA_LEX_CREATE_TMP_TABLE &&
5479
ha_check_storage_engine_flag(*new_engine, HTON_TEMPORARY_NOT_SUPPORTED))
5477
ha_check_storage_engine_flag(*new_engine, HTON_BIT_TEMPORARY_NOT_SUPPORTED))
5481
5479
if (create_info->used_fields & HA_CREATE_USED_ENGINE)