~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_handler.cc

  • Committer: Monty Taylor
  • Date: 2008-10-16 06:32:30 UTC
  • mto: (511.1.5 codestyle)
  • mto: This revision was merged to the branch mainline in revision 521.
  • Revision ID: monty@inaugust.com-20081016063230-4brxsra0qsmsg84q
Added -Wunused-macros.

Show diffs side-by-side

added added

removed removed

Lines of Context:
20
20
 
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.
24
24
 
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
34
34
 
35
35
/*
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.
57
57
*/
58
58
 
59
 
#include "mysql_priv.h"
60
 
#include "sql_select.h"
61
 
#include <assert.h>
 
59
#include <drizzled/server_includes.h>
 
60
#include <drizzled/sql_select.h>
62
61
 
63
62
#define HANDLER_TABLES_HASH_SIZE 120
64
63
 
74
73
  @note Broadcasts refresh if it closed a table with old version.
75
74
*/
76
75
 
77
 
static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables,
 
76
static void mysql_ha_close_table(THD *thd, TableList *tables,
78
77
                                 bool is_locked)
79
78
{
80
 
  TABLE **table_ptr;
 
79
  Table **table_ptr;
81
80
 
82
81
  /*
83
82
    Though we could take the table pointer from hash_tables->table,
94
93
  {
95
94
    (*table_ptr)->file->ha_index_or_rnd_end();
96
95
    if (! is_locked)
97
 
      VOID(pthread_mutex_lock(&LOCK_open));
 
96
      pthread_mutex_lock(&LOCK_open);
98
97
    if (close_thread_table(thd, table_ptr))
99
98
    {
100
99
      /* Tell threads waiting for refresh that something has happened */
101
100
      broadcast_refresh();
102
101
    }
103
102
    if (! is_locked)
104
 
      VOID(pthread_mutex_unlock(&LOCK_open));
 
103
      pthread_mutex_unlock(&LOCK_open);
105
104
  }
106
105
  else if (tables->table)
107
106
  {
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;
127
126
    name (table->alias) of the specified table.
128
127
 
129
128
  RETURN
130
 
    FALSE ok
131
 
    TRUE  error
 
129
    false ok
 
130
    true  error
132
131
*/
133
132
 
134
 
bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
 
133
bool mysql_ha_close(THD *thd, TableList *tables)
135
134
{
136
 
  TABLE_LIST    *hash_tables;
137
 
  DBUG_ENTER("mysql_ha_close");
138
 
  DBUG_PRINT("enter",("'%s'.'%s' as '%s'",
139
 
                      tables->db, tables->table_name, tables->alias));
 
135
  TableList    *hash_tables;
140
136
 
141
 
  if ((hash_tables= (TABLE_LIST*) hash_search(&thd->handler_tables_hash,
142
 
                                              (uchar*) tables->alias,
 
137
  if ((hash_tables= (TableList*) hash_search(&thd->handler_tables_hash,
 
138
                                              (unsigned char*) tables->alias,
143
139
                                              strlen(tables->alias) + 1)))
144
140
  {
145
 
    mysql_ha_close_table(thd, hash_tables, FALSE);
146
 
    hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
 
141
    mysql_ha_close_table(thd, hash_tables, false);
 
142
    hash_delete(&thd->handler_tables_hash, (unsigned char*) hash_tables);
147
143
  }
148
144
  else
149
145
  {
150
146
    my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias, "HANDLER");
151
 
    DBUG_PRINT("exit",("ERROR"));
152
 
    DBUG_RETURN(TRUE);
 
147
    return(true);
153
148
  }
154
149
 
155
150
  my_ok(thd);
156
 
  DBUG_PRINT("exit", ("OK"));
157
 
  DBUG_RETURN(FALSE);
 
151
  return(false);
158
152
}
159
153
 
160
154
 
164
158
  @param thd Thread identifier.
165
159
  @param tables The list of tables to remove.
166
160
 
167
 
  @return Pointer to head of linked list (TABLE_LIST::next_local) of matching
168
 
          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
169
163
          table was matched.
170
164
*/
171
165
 
172
 
static TABLE_LIST *mysql_ha_find(THD *thd, TABLE_LIST *tables)
 
166
static TableList *mysql_ha_find(THD *thd, TableList *tables)
173
167
{
174
 
  TABLE_LIST *hash_tables, *head= NULL, *first= tables;
175
 
  DBUG_ENTER("mysql_ha_find");
 
168
  TableList *hash_tables, *head= NULL, *first= tables;
176
169
 
177
170
  /* search for all handlers with matching table names */
178
 
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
 
171
  for (uint32_t i= 0; i < thd->handler_tables_hash.records; i++)
179
172
  {
180
 
    hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
 
173
    hash_tables= (TableList*) hash_element(&thd->handler_tables_hash, i);
181
174
    for (tables= first; tables; tables= tables->next_local)
182
175
    {
183
176
      if ((! *tables->db ||
184
 
          ! my_strcasecmp(&my_charset_latin1, hash_tables->db, tables->db)) &&
185
 
          ! 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,
186
179
                          tables->table_name))
187
180
        break;
188
181
    }
193
186
    }
194
187
  }
195
188
 
196
 
  DBUG_RETURN(head);
 
189
  return(head);
197
190
}
198
191
 
199
192
 
207
200
  @note Broadcasts refresh if it closed a table with old version.
208
201
*/
209
202
 
210
 
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)
211
204
{
212
 
  TABLE_LIST *hash_tables, *next;
213
 
  DBUG_ENTER("mysql_ha_rm_tables");
 
205
  TableList *hash_tables, *next;
214
206
 
215
 
  DBUG_ASSERT(tables);
 
207
  assert(tables);
216
208
 
217
209
  hash_tables= mysql_ha_find(thd, tables);
218
210
 
221
213
    next= hash_tables->next_local;
222
214
    if (hash_tables->table)
223
215
      mysql_ha_close_table(thd, hash_tables, is_locked);
224
 
    hash_delete(&thd->handler_tables_hash, (uchar*) hash_tables);
 
216
    hash_delete(&thd->handler_tables_hash, (unsigned char*) hash_tables);
225
217
    hash_tables= next;
226
218
  }
227
219
 
228
 
  DBUG_VOID_RETURN;
 
220
  return;
229
221
}
230
222
 
231
223
 
240
232
 
241
233
void mysql_ha_flush(THD *thd)
242
234
{
243
 
  TABLE_LIST *hash_tables;
244
 
  DBUG_ENTER("mysql_ha_flush");
 
235
  TableList *hash_tables;
245
236
 
246
237
  safe_mutex_assert_owner(&LOCK_open);
247
238
 
248
 
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
 
239
  for (uint32_t i= 0; i < thd->handler_tables_hash.records; i++)
249
240
  {
250
 
    hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
 
241
    hash_tables= (TableList*) hash_element(&thd->handler_tables_hash, i);
251
242
    if (hash_tables->table && hash_tables->table->needs_reopen_or_name_lock())
252
243
    {
253
 
      mysql_ha_close_table(thd, hash_tables, TRUE);
 
244
      mysql_ha_close_table(thd, hash_tables, true);
254
245
      /* Mark table as closed, ready for re-open. */
255
246
      hash_tables->table= NULL;
256
247
    }
257
248
  }
258
249
 
259
 
  DBUG_VOID_RETURN;
 
250
  return;
260
251
}
261
252
 
262
253
 
270
261
 
271
262
void mysql_ha_cleanup(THD *thd)
272
263
{
273
 
  TABLE_LIST *hash_tables;
274
 
  DBUG_ENTER("mysql_ha_cleanup");
 
264
  TableList *hash_tables;
275
265
 
276
 
  for (uint i= 0; i < thd->handler_tables_hash.records; i++)
 
266
  for (uint32_t i= 0; i < thd->handler_tables_hash.records; i++)
277
267
  {
278
 
    hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
 
268
    hash_tables= (TableList*) hash_element(&thd->handler_tables_hash, i);
279
269
    if (hash_tables->table)
280
 
      mysql_ha_close_table(thd, hash_tables, FALSE);
 
270
      mysql_ha_close_table(thd, hash_tables, false);
281
271
   }
282
272
 
283
273
  hash_free(&thd->handler_tables_hash);
284
274
 
285
 
  DBUG_VOID_RETURN;
 
275
  return;
286
276
}