21
21
the most natural (easiest, fastest) way to do it is to
22
22
compute List<Item> field_list not in mysql_ha_read
23
but in mysql_ha_open, and then store it in TABLE structure.
23
but in mysql_ha_open, and then store it in Table structure.
25
25
The problem here is that mysql_parse calls free_item to free all the
26
26
items allocated at the end of every query. The workaround would to
36
36
There are two containers holding information about open handler tables.
37
The first is 'thd->handler_tables'. It is a linked list of TABLE objects.
37
The first is 'thd->handler_tables'. It is a linked list of Table objects.
38
38
It is used like 'thd->open_tables' in the table cache. The trick is to
39
39
exchange these two lists during open and lock of tables. Thus the normal
40
40
table cache code can be used.
41
The second container is a HASH. It holds objects of the type TABLE_LIST.
41
The second container is a HASH. It holds objects of the type TableList.
42
42
Despite its name, no lists of tables but only single structs are hashed
43
43
(the 'next' pointer is always NULL). The reason for theis second container
44
is, that we want handler tables to survive FLUSH TABLE commands. A table
45
affected by FLUSH TABLE must be closed so that other threads are not
44
is, that we want handler tables to survive FLUSH Table commands. A table
45
affected by FLUSH Table must be closed so that other threads are not
46
46
blocked by handler tables still in use. Since we use the normal table cache
47
47
functions with 'thd->handler_tables', the closed tables are removed from
48
48
this list. Hence we need the original open information for the handler
49
49
table in the case that it is used again. This information is handed over
50
to mysql_ha_open() as a TABLE_LIST. So we store this information in the
51
second container, where it is not affected by FLUSH TABLE. The second
50
to mysql_ha_open() as a TableList. So we store this information in the
51
second container, where it is not affected by FLUSH Table. The second
52
52
container is implemented as a hash for performance reasons. Consequently,
53
53
we use it not only for re-opening a handler table, but also for the
54
54
HANDLER ... READ commands. For this purpose, we store a pointer to the
55
TABLE structure (in the first container) in the TBALE_LIST object in the
55
Table structure (in the first container) in the TBALE_LIST object in the
56
56
second container. When the table is flushed, the pointer is cleared.
59
#include "mysql_priv.h"
60
#include "sql_select.h"
59
#include <drizzled/server_includes.h>
60
#include <drizzled/sql_select.h>
63
62
#define HANDLER_TABLES_HASH_SIZE 120
74
73
@note Broadcasts refresh if it closed a table with old version.
77
static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables,
76
static void mysql_ha_close_table(THD *thd, TableList *tables,
83
82
Though we could take the table pointer from hash_tables->table,
95
94
(*table_ptr)->file->ha_index_or_rnd_end();
97
VOID(pthread_mutex_lock(&LOCK_open));
96
pthread_mutex_lock(&LOCK_open);
98
97
if (close_thread_table(thd, table_ptr))
100
99
/* Tell threads waiting for refresh that something has happened */
101
100
broadcast_refresh();
104
VOID(pthread_mutex_unlock(&LOCK_open));
103
pthread_mutex_unlock(&LOCK_open);
106
105
else if (tables->table)
108
107
/* Must be a temporary table */
109
TABLE *table= tables->table;
108
Table *table= tables->table;
110
109
table->file->ha_index_or_rnd_end();
111
110
table->query_id= thd->query_id;
112
111
table->open_by_handler= 0;
134
bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
133
bool mysql_ha_close(THD *thd, TableList *tables)
136
TABLE_LIST *hash_tables;
135
TableList *hash_tables;
138
if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
139
(uchar*) tables->alias,
137
if ((hash_tables= (TableList*) hash_search(&thd->handler_tables_hash,
138
(unsigned char*) tables->alias,
140
139
strlen(tables->alias) + 1)))
142
141
mysql_ha_close_table(thd, hash_tables, false);
143
hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
142
hash_delete(&thd->handler_tables_hash, (unsigned char*) hash_tables);
159
158
@param thd Thread identifier.
160
159
@param tables The list of tables to remove.
162
@return Pointer to head of linked list (TABLE_LIST::next_local) of matching
163
TABLE_LIST elements from handler_tables_hash. Otherwise, NULL if no
161
@return Pointer to head of linked list (TableList::next_local) of matching
162
TableList elements from handler_tables_hash. Otherwise, NULL if no
164
163
table was matched.
167
static TABLE_LIST *mysql_ha_find(THD *thd, TABLE_LIST *tables)
166
static TableList *mysql_ha_find(THD *thd, TableList *tables)
169
TABLE_LIST *hash_tables, *head= NULL, *first= tables;
168
TableList *hash_tables, *head= NULL, *first= tables;
171
170
/* search for all handlers with matching table names */
172
for (uint i= 0; i < thd->handler_tables_hash.records; i++)
171
for (uint32_t i= 0; i < thd->handler_tables_hash.records; i++)
174
hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
173
hash_tables= (TableList*) hash_element(&thd->handler_tables_hash, i);
175
174
for (tables= first; tables; tables= tables->next_local)
177
176
if ((! *tables->db ||
178
! my_strcasecmp(&my_charset_latin1, hash_tables->db, tables->db)) &&
179
! my_strcasecmp(&my_charset_latin1, hash_tables->table_name,
177
! my_strcasecmp(&my_charset_utf8_general_ci, hash_tables->db, tables->db)) &&
178
! my_strcasecmp(&my_charset_utf8_general_ci, hash_tables->table_name,
180
179
tables->table_name))
201
200
@note Broadcasts refresh if it closed a table with old version.
204
void mysql_ha_rm_tables(THD *thd, TABLE_LIST *tables, bool is_locked)
203
void mysql_ha_rm_tables(THD *thd, TableList *tables, bool is_locked)
206
TABLE_LIST *hash_tables, *next;
205
TableList *hash_tables, *next;
214
213
next= hash_tables->next_local;
215
214
if (hash_tables->table)
216
215
mysql_ha_close_table(thd, hash_tables, is_locked);
217
hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
216
hash_delete(&thd->handler_tables_hash, (unsigned char*) hash_tables);
218
217
hash_tables= next;
234
233
void mysql_ha_flush(THD *thd)
236
TABLE_LIST *hash_tables;
235
TableList *hash_tables;
238
237
safe_mutex_assert_owner(&LOCK_open);
240
for (uint i= 0; i < thd->handler_tables_hash.records; i++)
239
for (uint32_t i= 0; i < thd->handler_tables_hash.records; i++)
242
hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
241
hash_tables= (TableList*) hash_element(&thd->handler_tables_hash, i);
243
242
if (hash_tables->table && hash_tables->table->needs_reopen_or_name_lock())
245
244
mysql_ha_close_table(thd, hash_tables, true);
263
262
void mysql_ha_cleanup(THD *thd)
265
TABLE_LIST *hash_tables;
264
TableList *hash_tables;
267
for (uint i= 0; i < thd->handler_tables_hash.records; i++)
266
for (uint32_t i= 0; i < thd->handler_tables_hash.records; i++)
269
hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
268
hash_tables= (TableList*) hash_element(&thd->handler_tables_hash, i);
270
269
if (hash_tables->table)
271
270
mysql_ha_close_table(thd, hash_tables, false);