61
54
Table *unused_tables; /* Used by mysql_test */
62
55
HASH open_cache; /* Used by mysql_test */
63
56
static HASH table_def_cache;
64
static TABLE_SHARE *oldest_unused_share, end_of_unused_share;
57
static TableShare *oldest_unused_share, end_of_unused_share;
65
58
static pthread_mutex_t LOCK_table_share;
66
59
static bool table_def_inited= 0;
68
61
static int open_unireg_entry(Session *session, Table *entry, TableList *table_list,
70
63
char *cache_key, uint32_t cache_key_length);
71
static void free_cache_entry(Table *entry);
64
extern "C" void free_cache_entry(void *entry);
72
65
static void close_old_data_files(Session *session, Table *table, bool morph_locks,
73
66
bool send_refresh);
76
69
extern "C" unsigned char *table_cache_key(const unsigned char *record, size_t *length,
77
bool not_used __attribute__((unused)))
79
72
Table *entry=(Table*) record;
80
73
*length= entry->s->table_cache_key.length;
133
uint32_t create_table_def_key(Session *session, char *key, TableList *table_list,
125
uint32_t create_table_def_key(char *key, TableList *table_list)
136
uint32_t key_length= (uint) (my_stpcpy(my_stpcpy(key, table_list->db)+1,
137
table_list->table_name)-key)+1;
140
int4store(key + key_length, session->server_id);
141
int4store(key + key_length + 4, session->variables.pseudo_thread_id);
142
key_length+= TMP_TABLE_KEY_EXTRA;
129
key_pos= strcpy(key_pos, table_list->db) + strlen(table_list->db);
130
key_pos= strcpy(key_pos+1, table_list->table_name) +
131
strlen(table_list->table_name);
132
key_length= (uint32_t)(key_pos-key)+1;
144
134
return key_length;
149
139
/*****************************************************************************
150
Functions to handle table definition cach (TABLE_SHARE)
140
Functions to handle table definition cach (TableShare)
151
141
*****************************************************************************/
153
143
extern "C" unsigned char *table_def_key(const unsigned char *record, size_t *length,
154
bool not_used __attribute__((unused)))
156
TABLE_SHARE *entry=(TABLE_SHARE*) record;
146
TableShare *entry=(TableShare*) record;
157
147
*length= entry->table_cache_key.length;
158
148
return (unsigned char*) entry->table_cache_key.str;
162
static void table_def_free_entry(TABLE_SHARE *share)
152
static void table_def_free_entry(TableShare *share)
254
242
(void) pthread_mutex_lock(&share->mutex);
257
We assign a new table id under the protection of the LOCK_open and
258
the share's own mutex. We do this insted of creating a new mutex
259
and using it for the sole purpose of serializing accesses to a
260
static variable, we assign the table id here. We assign it to the
261
share before inserting it into the table_def_cache to be really
262
sure that it cannot be read from the cache without having a table
265
CAVEAT. This means that the table cannot be used for
266
binlogging/replication purposes, unless get_table_share() has been
267
called directly or indirectly.
269
assign_new_table_id(share);
271
244
if (my_hash_insert(&table_def_cache, (unsigned char*) share))
273
free_table_share(share);
246
share->free_table_share();
274
247
return(0); // return error
276
if (open_table_def(session, share, db_flags))
249
if (open_table_def(session, share))
278
251
*error= share->error;
279
252
(void) hash_delete(&table_def_cache, (unsigned char*) share);
367
/* Table didn't exist. Check if some engine can provide it */
368
if ((tmp= ha_create_table_from_engine(session, table_list->db,
369
table_list->table_name)) < 0)
374
/* Give right error message */
375
session->clear_error();
376
my_printf_error(ER_UNKNOWN_ERROR,
377
"Failed to open '%-.64s', error while "
378
"unpacking from engine",
379
MYF(0), table_list->table_name);
382
/* Table existed in engine. Let's open it */
383
drizzle_reset_errors(session, 1); // Clear warnings
384
session->clear_error(); // Clear error message
385
return(get_table_share(session, table_list, key, key_length,
391
344
Mark that we are not using table share anymore.
1148
1098
return(found_old_table);
1152
/* close_temporary_tables' internal, 4 is due to uint4korr definition */
1153
static inline uint32_t tmpkeyval(Session *session __attribute__((unused)),
1156
return uint4korr(table->s->table_cache_key.str + table->s->table_cache_key.length - 4);
1161
Close all temporary tables created by 'CREATE TEMPORARY TABLE' for thread
1162
creates one DROP TEMPORARY Table binlog event for each pseudo-thread
1165
void close_temporary_tables(Session *session)
1170
/* Assume session->options has OPTION_QUOTE_SHOW_CREATE */
1171
bool was_quote_show= true;
1173
if (!session->temporary_tables)
1176
if (!drizzle_bin_log.is_open() || true )
1179
for (table= session->temporary_tables; table; table= tmp_next)
1181
tmp_next= table->next;
1182
close_temporary(table, 1, 1);
1184
session->temporary_tables= 0;
1188
/* Better add "if exists", in case a RESET MASTER has been done */
1189
const char stub[]= "DROP /*!40005 TEMPORARY */ Table IF EXISTS ";
1190
uint32_t stub_len= sizeof(stub) - 1;
1192
String s_query= String(buf, sizeof(buf), system_charset_info);
1193
bool found_user_tables= false;
1195
memcpy(buf, stub, stub_len);
1198
Insertion sort of temp tables by pseudo_thread_id to build ordered list
1199
of sublists of equal pseudo_thread_id
1202
for (prev_table= session->temporary_tables, table= prev_table->next;
1204
prev_table= table, table= table->next)
1206
Table *prev_sorted /* same as for prev_table */, *sorted;
1207
if (is_user_table(table))
1209
if (!found_user_tables)
1210
found_user_tables= true;
1211
for (prev_sorted= NULL, sorted= session->temporary_tables; sorted != table;
1212
prev_sorted= sorted, sorted= sorted->next)
1214
if (!is_user_table(sorted) ||
1215
tmpkeyval(session, sorted) > tmpkeyval(session, table))
1217
/* move into the sorted part of the list from the unsorted */
1218
prev_table->next= table->next;
1219
table->next= sorted;
1222
prev_sorted->next= table;
1226
session->temporary_tables= table;
1235
/* We always quote db,table names though it is slight overkill */
1236
if (found_user_tables &&
1237
!(was_quote_show= test(session->options & OPTION_QUOTE_SHOW_CREATE)))
1239
session->options |= OPTION_QUOTE_SHOW_CREATE;
1242
/* scan sorted tmps to generate sequence of DROP */
1243
for (table= session->temporary_tables; table; table= next)
1245
if (is_user_table(table))
1247
my_thread_id save_pseudo_thread_id= session->variables.pseudo_thread_id;
1248
/* Set pseudo_thread_id to be that of the processed table */
1249
session->variables.pseudo_thread_id= tmpkeyval(session, table);
1251
Loop forward through all tables within the sublist of
1252
common pseudo_thread_id to create single DROP query.
1254
for (s_query.length(stub_len);
1255
table && is_user_table(table) &&
1256
tmpkeyval(session, table) == session->variables.pseudo_thread_id;
1260
We are going to add 4 ` around the db/table names and possible more
1261
due to special characters in the names
1263
append_identifier(session, &s_query, table->s->db.str, strlen(table->s->db.str));
1264
s_query.append('.');
1265
append_identifier(session, &s_query, table->s->table_name.str,
1266
strlen(table->s->table_name.str));
1267
s_query.append(',');
1269
close_temporary(table, 1, 1);
1271
session->clear_error();
1272
const CHARSET_INFO * const cs_save= session->variables.character_set_client;
1273
session->variables.character_set_client= system_charset_info;
1274
Query_log_event qinfo(session, s_query.ptr(),
1275
s_query.length() - 1 /* to remove trailing ',' */,
1277
session->variables.character_set_client= cs_save;
1279
Imagine the thread had created a temp table, then was doing a
1280
SELECT, and the SELECT was killed. Then it's not clever to
1281
mark the statement above as "killed", because it's not really
1282
a statement updating data, and there are 99.99% chances it
1283
will succeed on slave. If a real update (one updating a
1284
persistent table) was killed on the master, then this real
1285
update will be logged with error_code=killed, rightfully
1286
causing the slave to stop.
1288
qinfo.error_code= 0;
1289
drizzle_bin_log.write(&qinfo);
1290
session->variables.pseudo_thread_id= save_pseudo_thread_id;
1295
close_temporary(table, 1, 1);
1298
if (!was_quote_show)
1299
session->options&= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */
1300
session->temporary_tables=0;
1304
1102
Find table in list.
1594
1386
session->slave_proxy_id, separated by '\0'.
1597
bool rename_temporary_table(Session* session, Table *table, const char *db,
1598
const char *table_name)
1389
bool rename_temporary_table(Table *table, const char *db, const char *table_name)
1601
1392
uint32_t key_length;
1602
TABLE_SHARE *share= table->s;
1393
TableShare *share= table->s;
1603
1394
TableList table_list;
1605
1396
if (!(key=(char*) alloc_root(&share->mem_root, MAX_DBKEY_LENGTH)))
1606
return(1); /* purecov: inspected */
1397
return true; /* purecov: inspected */
1608
1399
table_list.db= (char*) db;
1609
1400
table_list.table_name= (char*) table_name;
1610
key_length= create_table_def_key(session, key, &table_list, 1);
1401
key_length= create_table_def_key(key, &table_list);
1611
1402
share->set_table_cache_key(key, key_length);
1997
Check that table exists in table definition cache, on disk
1998
or in some storage engine.
2000
@param session Thread context
2001
@param table Table list element
2002
@param[out] exists Out parameter which is set to true if table
2003
exists and to false otherwise.
2005
@note This function assumes that caller owns LOCK_open mutex.
2006
It also assumes that the fact that there are no name-locks
2007
on the table was checked beforehand.
2009
@note If there is no .FRM file for the table but it exists in one
2010
of engines (e.g. it was created on another node of NDB cluster)
2011
this function will fetch and create proper .FRM file for it.
2013
@retval true Some error occured
2014
@retval false No error. 'exists' out parameter set accordingly.
2017
bool check_if_table_exists(Session *session, TableList *table, bool *exists)
2019
char path[FN_REFLEN];
2022
safe_mutex_assert_owner(&LOCK_open);
2026
if (get_cached_table_share(table->db, table->table_name))
2029
build_table_filename(path, sizeof(path) - 1, table->db, table->table_name,
2032
if (!access(path, F_OK))
2035
/* .FRM file doesn't exist. Check if some engine can provide it. */
2037
rc= ha_create_table_from_engine(session, table->db, table->table_name);
2041
/* Table does not exists in engines as well. */
2047
/* Table exists in some engine and .FRM for it was created. */
2052
my_printf_error(ER_UNKNOWN_ERROR, "Failed to open '%-.64s', error while "
2053
"unpacking from engine", MYF(0), table->table_name);
2510
2214
Table *find_locked_table(Session *session, const char *db,const char *table_name)
2512
char key[MAX_DBKEY_LENGTH];
2513
uint32_t key_length=(uint) (my_stpcpy(my_stpcpy(key,db)+1,table_name)-key)+1;
2216
char key[MAX_DBKEY_LENGTH];
2218
uint32_t key_length;
2220
key_pos= strcpy(key_pos, db) + strlen(db);
2221
key_pos= strcpy(key_pos+1, table_name) + strlen(table_name);
2222
key_length= (uint32_t)(key_pos-key)+1;
2515
2224
for (Table *table=session->open_tables; table ; table=table->next)
2517
2226
if (table->s->table_cache_key.length == key_length &&
2518
!memcmp(table->s->table_cache_key.str, key, key_length))
2227
!memcmp(table->s->table_cache_key.str, key, key_length))
3043
Function to assign a new table map id to a table share.
3047
share - Pointer to table share structure
3051
We are intentionally not checking that share->mutex is locked
3052
since this function should only be called when opening a table
3053
share and before it is entered into the table_def_cache (meaning
3054
that it cannot be fetched by another thread, even accidentally).
3059
The LOCK_open mutex is locked
3063
share->table_map_id is given a value that with a high certainty is
3064
not used by any other table (the only case where a table id can be
3065
reused is on wrap-around, which means more than 4 billion table
3066
share opens have been executed while one table was open all the
3069
share->table_map_id is not UINT32_MAX.
3071
void assign_new_table_id(TABLE_SHARE *share)
3073
static uint32_t last_table_id= UINT32_MAX;
3076
assert(share != NULL);
3077
safe_mutex_assert_owner(&LOCK_open);
3079
ulong tid= ++last_table_id; /* get next id */
3081
There is one reserved number that cannot be used. Remember to
3082
change this when 6-byte global table id's are introduced.
3084
if (unlikely(tid == UINT32_MAX))
3085
tid= ++last_table_id;
3086
share->table_map_id= tid;
3088
/* Post conditions */
3089
assert(share->table_map_id != UINT32_MAX);
3095
2748
Load a table definition from file and open unireg table
3226
2877
if (unlikely(entry->file->implicit_emptied))
3228
2879
entry->file->implicit_emptied= 0;
3229
if (drizzle_bin_log.is_open())
3231
2881
char *query, *end;
3232
2882
uint32_t query_buf_size= 20 + share->db.length + share->table_name.length +1;
3233
if ((query= (char*) my_malloc(query_buf_size,MYF(MY_WME))))
2883
if ((query= (char*) malloc(query_buf_size)))
3235
/* this DELETE FROM is needed even with row-based binlogging */
3236
end = strxmov(my_stpcpy(query, "DELETE FROM `"),
3237
share->db.str,"`.`",share->table_name.str,"`", NULL);
3238
session->binlog_query(Session::STMT_QUERY_TYPE,
3239
query, (ulong)(end-query), false, false);
2886
"this DELETE FROM is needed even with row-based binlogging"
2888
We inherited this from MySQL. TODO: fix it to issue a propper truncate
2889
of the table (though that may not be completely right sematics).
2892
end+= sprintf(query, "DELETE FROM `%s`.`%s`", share->db.str,
2893
share->table_name.str);
2894
transaction_services.rawStatement(session, query, (size_t)(end - query));
3245
As replication is maybe going to be corrupted, we need to warn the
3246
DBA on top of warning the client (which will automatically be done
3247
because of MYF(MY_WME) in my_malloc() above).
3249
sql_print_error(_("When opening HEAP table, could not allocate memory "
3250
"to write 'DELETE FROM `%s`.`%s`' to the binary log"),
3251
table_list->db, table_list->table_name);
2899
errmsg_printf(ERRMSG_LVL_ERROR, _("When opening HEAP table, could not allocate memory "
2900
"to write 'DELETE FROM `%s`.`%s`' to replication"),
2901
table_list->db, table_list->table_name);
2902
my_error(ER_OUTOFMEMORY, MYF(0), query_buf_size);
2903
entry->closefrm(false);
3769
3420
open_table_mode open_mode)
3771
3422
Table *tmp_table;
3773
3424
char cache_key[MAX_DBKEY_LENGTH], *saved_cache_key, *tmp_path;
3774
uint32_t key_length;
3425
uint32_t key_length, path_length;
3775
3426
TableList table_list;
3777
3428
table_list.db= (char*) db;
3778
3429
table_list.table_name= (char*) table_name;
3779
3430
/* Create the cache_key for temporary tables */
3780
key_length= create_table_def_key(session, cache_key, &table_list, 1);
3782
if (!(tmp_table= (Table*) my_malloc(sizeof(*tmp_table) + sizeof(*share) +
3783
strlen(path)+1 + key_length,
3785
return(0); /* purecov: inspected */
3787
share= (TABLE_SHARE*) (tmp_table+1);
3431
key_length= create_table_def_key(cache_key, &table_list);
3432
path_length= strlen(path);
3434
if (!(tmp_table= (Table*) malloc(sizeof(*tmp_table) + sizeof(*share) +
3435
path_length + 1 + key_length)))
3438
share= (TableShare*) (tmp_table+1);
3788
3439
tmp_path= (char*) (share+1);
3789
saved_cache_key= my_stpcpy(tmp_path, path)+1;
3440
saved_cache_key= strcpy(tmp_path, path)+path_length+1;
3790
3441
memcpy(saved_cache_key, cache_key, key_length);
3792
init_tmp_table_share(session, share, saved_cache_key, key_length,
3793
strchr(saved_cache_key, '\0')+1, tmp_path);
3443
share->init(saved_cache_key, key_length, strchr(saved_cache_key, '\0')+1, tmp_path);
3795
if (open_table_def(session, share, 0) ||
3445
if (open_table_def(session, share) ||
3796
3446
open_table_from_share(session, share, table_name,
3797
3447
(open_mode == OTM_ALTER) ? 0 :
3798
(uint) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
3448
(uint32_t) (HA_OPEN_KEYFILE | HA_OPEN_RNDFILE |
3800
3450
(open_mode == OTM_ALTER) ?
3801
3451
(EXTRA_RECORD | OPEN_FRM_FILE_ONLY)
3830
3480
tmp_table->next->prev= tmp_table;
3831
3481
session->temporary_tables= tmp_table;
3832
3482
session->temporary_tables->prev= 0;
3833
if (session->slave_thread)
3834
slave_open_temp_tables++;
3836
3484
tmp_table->pos_in_table_list= 0;
3837
3485
return(tmp_table);
3841
bool rm_temporary_table(handlerton *base, char *path)
3489
bool rm_temporary_table(StorageEngine *base, char *path)
3847
delete_table_proto_file(path);
3849
my_stpcpy(ext= strchr(path, '\0'), reg_ext);
3850
if (my_delete(path,MYF(0)))
3494
if(delete_table_proto_file(path))
3851
3495
error=1; /* purecov: inspected */
3852
*ext= 0; // remove extension
3853
file= get_new_handler((TABLE_SHARE*) 0, current_session->mem_root, base);
3497
file= get_new_handler((TableShare*) 0, current_session->mem_root, base);
3854
3498
if (file && file->ha_delete_table(path))
3857
sql_print_warning(_("Could not remove temporary table: '%s', error: %d"),
3501
errmsg_printf(ERRMSG_LVL_WARN, _("Could not remove temporary table: '%s', error: %d"),
3858
3502
path, my_errno);
4992
4613
Table *table_1= nj_col_1->table_ref->table;
4993
4614
/* Mark field_1 used for table cache. */
4994
bitmap_set_bit(table_1->read_set, field_1->field_index);
4995
table_1->covering_keys.intersect(field_1->part_of_key);
4996
table_1->merge_keys.merge(field_1->part_of_key);
4615
table_1->setReadSet(field_1->field_index);
4616
table_1->covering_keys&= field_1->part_of_key;
4617
table_1->merge_keys|= field_1->part_of_key;
5000
4621
Table *table_2= nj_col_2->table_ref->table;
5001
4622
/* Mark field_2 used for table cache. */
5002
bitmap_set_bit(table_2->read_set, field_2->field_index);
5003
table_2->covering_keys.intersect(field_2->part_of_key);
5004
table_2->merge_keys.merge(field_2->part_of_key);
4623
table_2->setReadSet(field_2->field_index);
4624
table_2->covering_keys&= field_2->part_of_key;
4625
table_2->merge_keys|= field_2->part_of_key;
5007
4628
if (using_fields != NULL)
5793
5414
if ((field= field_iterator.field()))
5795
5416
/* Mark fields as used to allow storage engine to optimze access */
5796
bitmap_set_bit(field->table->read_set, field->field_index);
5798
Mark virtual fields for write and others that the virtual fields
5801
if (field->vcol_info)
5803
Item *vcol_item= field->vcol_info->expr_item;
5805
vcol_item->walk(&Item::register_field_in_read_map, 1, (unsigned char *) 0);
5806
bitmap_set_bit(field->table->write_set, field->field_index);
5417
field->table->setReadSet(field->field_index);
5810
table->covering_keys.intersect(field->part_of_key);
5811
table->merge_keys.merge(field->part_of_key);
5420
table->covering_keys&= field->part_of_key;
5421
table->merge_keys|= field->part_of_key;
5813
5423
if (tables->is_natural_join)
6019
5629
table= rfield->table;
6020
5630
if (rfield == table->next_number_field)
6021
5631
table->auto_increment_field_not_null= true;
6022
if (rfield->vcol_info &&
6023
value->type() != Item::DEFAULT_VALUE_ITEM &&
6024
value->type() != Item::NULL_ITEM &&
6025
table->s->table_category != TABLE_CATEGORY_TEMPORARY)
6027
session->abort_on_warning= false;
6028
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
6029
ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
6030
ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
6031
rfield->field_name, table->s->table_name.str);
6032
session->abort_on_warning= abort_on_warning_saved;
6034
5632
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
6036
5634
my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
6122
5713
table= field->table;
6123
5714
if (field == table->next_number_field)
6124
5715
table->auto_increment_field_not_null= true;
6125
if (field->vcol_info &&
6126
value->type() != Item::DEFAULT_VALUE_ITEM &&
6127
value->type() != Item::NULL_ITEM &&
6128
table->s->table_category != TABLE_CATEGORY_TEMPORARY)
6130
session->abort_on_warning= false;
6131
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
6132
ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN,
6133
ER(ER_WARNING_NON_DEFAULT_VALUE_FOR_VIRTUAL_COLUMN),
6134
field->field_name, table->s->table_name.str);
6135
session->abort_on_warning= abort_on_warning_saved;
6137
5716
if (value->save_in_field(field, 0) < 0)
6139
5718
tbl_list.push_back(table);
6177
5749
bool drizzle_rm_tmp_tables(void)
6180
char filePath[FN_REFLEN], *tmpdir, filePathCopy[FN_REFLEN];
5752
char filePath[FN_REFLEN], filePathCopy[FN_REFLEN];
6182
5754
FILEINFO *file;
6184
5756
Session *session;
6186
if (!(session= new Session))
5758
assert(drizzle_tmpdir);
5760
if (!(session= new Session(get_protocol())))
6188
5762
session->thread_stack= (char*) &session;
6189
5763
session->store_globals();
6191
for (i=0; i<=drizzle_tmpdir_list.max; i++)
5765
/* Remove all temp tables in the tmpdir */
5766
/* See if the directory exists */
5767
if ((dirp = my_dir(drizzle_tmpdir ,MYF(MY_WME | MY_DONT_SORT))))
6193
tmpdir=drizzle_tmpdir_list.list[i];
6194
/* See if the directory exists */
6195
if (!(dirp = my_dir(tmpdir,MYF(MY_WME | MY_DONT_SORT))))
6198
5769
/* Remove all SQLxxx tables from directory */
6200
for (idx=0 ; idx < (uint) dirp->number_off_files ; idx++)
5770
for (idx=0 ; idx < (uint32_t) dirp->number_off_files ; idx++)
6202
5772
file=dirp->dir_entry+idx;
6211
5781
char *ext= fn_ext(file->name);
6212
5782
uint32_t ext_len= strlen(ext);
6213
5783
uint32_t filePath_len= snprintf(filePath, sizeof(filePath),
6214
"%s%c%s", tmpdir, FN_LIBCHAR,
6216
if (!memcmp(reg_ext, ext, ext_len))
5784
"%s%c%s", drizzle_tmpdir, FN_LIBCHAR,
5786
if (!memcmp(".dfe", ext, ext_len))
6218
5788
handler *handler_file= 0;
6219
5789
/* We should cut file extention before deleting of table */
6220
5790
memcpy(filePathCopy, filePath, filePath_len - ext_len);
6221
5791
filePathCopy[filePath_len - ext_len]= 0;
6222
init_tmp_table_share(session, &share, "", 0, "", filePathCopy);
6223
if (!open_table_def(session, &share, 0) &&
5792
share.init(NULL, filePathCopy);
5793
if (!open_table_def(session, &share) &&
6224
5794
((handler_file= get_new_handler(&share, session->mem_root,
6225
5795
share.db_type()))))
6227
5797
handler_file->ha_delete_table(filePathCopy);
6228
5798
delete handler_file;
6230
free_table_share(&share);
5800
share.free_table_share();
6233
5803
File can be already deleted by tmp_table.file->delete_table().
6234
5804
So we hide error messages which happnes during deleting of these
6237
my_delete(filePath, MYF(0));
5807
my_delete(filePath, MYF(0));
6240
5810
my_dirend(dirp);
6242
5813
delete session;
6243
pthread_setspecific(THR_Session, 0);