~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/heap/ha_heap.cc

  • Committer: Monty
  • Date: 2008-10-02 05:41:33 UTC
  • mfrom: (398.1.10 codestyle)
  • Revision ID: mordred@scylla.inaugust.com-20081002054133-tyxv5bmqpazfaqqi
Merged up to 408 of stdint-includes-fix.

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
 
 
16
 
#include "heap_priv.h"
17
 
#include <drizzled/error.h>
18
 
#include <drizzled/table.h>
19
 
#include <drizzled/session.h>
20
 
#include <drizzled/field/varstring.h>
21
 
#include <drizzled/plugin/daemon.h>
22
 
#include <drizzled/plugin/storage_engine.h>
23
 
 
24
 
#include <boost/thread/mutex.hpp>
25
 
 
26
 
#include "heap.h"
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#define DRIZZLE_SERVER 1
 
17
#include <drizzled/server_includes.h>
27
18
#include "ha_heap.h"
28
 
 
29
 
#include <string>
30
 
 
31
 
 
32
 
using namespace drizzled;
33
 
using namespace std;
34
 
 
35
 
static const string engine_name("MEMORY");
36
 
 
37
 
boost::mutex THR_LOCK_heap;
38
 
 
39
 
static const char *ha_heap_exts[] = {
40
 
  NULL
41
 
};
42
 
 
43
 
class HeapEngine : public plugin::StorageEngine
44
 
{
45
 
public:
46
 
  explicit HeapEngine(string name_arg) :
47
 
    plugin::StorageEngine(name_arg,
48
 
                          HTON_STATS_RECORDS_IS_EXACT |
49
 
                          HTON_NULL_IN_KEY |
50
 
                          HTON_FAST_KEY_READ |
51
 
                          HTON_NO_BLOBS |
52
 
                          HTON_HAS_RECORDS |
53
 
                          HTON_SKIP_STORE_LOCK |
54
 
                          HTON_TEMPORARY_ONLY)
55
 
  {
56
 
  }
57
 
 
58
 
  virtual ~HeapEngine()
59
 
  {
60
 
    hp_panic(HA_PANIC_CLOSE);
61
 
  }
62
 
 
63
 
  virtual Cursor *create(Table &table)
64
 
  {
65
 
    return new ha_heap(*this, table);
66
 
  }
67
 
 
68
 
  const char **bas_ext() const {
69
 
    return ha_heap_exts;
70
 
  }
71
 
 
72
 
  int doCreateTable(Session &session,
73
 
                    Table &table_arg,
74
 
                    const identifier::Table &identifier,
75
 
                    message::Table &create_proto);
76
 
 
77
 
  /* For whatever reason, internal tables can be created by Cursor::open()
78
 
     for MEMORY.
79
 
     Instead of diving down a rat hole, let's just cry ourselves to sleep
80
 
     at night with this odd hackish workaround.
81
 
   */
82
 
  int heap_create_table(Session *session, const char *table_name,
83
 
                        Table *table_arg,
84
 
                        bool internal_table,
85
 
                        message::Table &create_proto,
86
 
                        HP_SHARE **internal_share);
87
 
 
88
 
  int doRenameTable(Session&, const identifier::Table &from, const identifier::Table &to);
89
 
 
90
 
  int doDropTable(Session&, const identifier::Table &identifier);
91
 
 
92
 
  int doGetTableDefinition(Session& session,
93
 
                           const identifier::Table &identifier,
94
 
                           message::Table &table_message);
95
 
 
96
 
  uint32_t max_supported_keys()          const { return MAX_KEY; }
97
 
  uint32_t max_supported_key_part_length() const { return MAX_KEY_LENGTH; }
98
 
 
99
 
  uint32_t index_flags(enum  ha_key_alg ) const
100
 
  {
101
 
    return ( HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR);
102
 
  }
103
 
 
104
 
  bool doDoesTableExist(Session& session, const identifier::Table &identifier);
105
 
  void doGetTableIdentifiers(CachedDirectory &directory,
106
 
                             const identifier::Schema &schema_identifier,
107
 
                             identifier::Table::vector &set_of_identifiers);
108
 
};
109
 
 
110
 
void HeapEngine::doGetTableIdentifiers(CachedDirectory&,
111
 
                                       const identifier::Schema&,
112
 
                                       identifier::Table::vector&)
113
 
{
114
 
}
115
 
 
116
 
bool HeapEngine::doDoesTableExist(Session& session, const identifier::Table &identifier)
117
 
{
118
 
  return session.getMessageCache().doesTableMessageExist(identifier);
119
 
}
120
 
 
121
 
int HeapEngine::doGetTableDefinition(Session &session,
122
 
                                     const identifier::Table &identifier,
123
 
                                     message::Table &table_proto)
124
 
{
125
 
  if (session.getMessageCache().getTableMessage(identifier, table_proto))
126
 
    return EEXIST;
127
 
 
128
 
  return ENOENT;
129
 
}
130
 
/*
131
 
  We have to ignore ENOENT entries as the MEMORY table is created on open and
132
 
  not when doing a CREATE on the table.
133
 
*/
134
 
int HeapEngine::doDropTable(Session &session, const identifier::Table &identifier)
135
 
{
136
 
  session.getMessageCache().removeTableMessage(identifier);
137
 
 
138
 
  int error= heap_delete_table(identifier.getPath().c_str());
139
 
 
140
 
  if (error == ENOENT)
141
 
    error= 0;
142
 
 
143
 
  return error;
144
 
}
145
 
 
146
 
static HeapEngine *heap_storage_engine= NULL;
147
 
 
148
 
static int heap_init(module::Context &context)
149
 
{
150
 
  heap_storage_engine= new HeapEngine(engine_name);
151
 
  context.add(heap_storage_engine);
 
19
#include "heapdef.h"
 
20
 
 
21
static handler *heap_create_handler(handlerton *hton,
 
22
                                    TABLE_SHARE *table, 
 
23
                                    MEM_ROOT *mem_root);
 
24
 
 
25
int heap_deinit(void *p __attribute__((unused)))
 
26
            
 
27
{
 
28
  return hp_panic(HA_PANIC_CLOSE);
 
29
}
 
30
 
 
31
 
 
32
int heap_init(void *p)
 
33
{
 
34
  handlerton *heap_hton;
 
35
 
 
36
  heap_hton= (handlerton *)p;
 
37
  heap_hton->state=      SHOW_OPTION_YES;
 
38
  heap_hton->create=     heap_create_handler;
 
39
  heap_hton->flags=      HTON_CAN_RECREATE;
 
40
 
152
41
  return 0;
153
42
}
154
43
 
 
44
static handler *heap_create_handler(handlerton *hton,
 
45
                                    TABLE_SHARE *table, 
 
46
                                    MEM_ROOT *mem_root)
 
47
{
 
48
  return new (mem_root) ha_heap(hton, table);
 
49
}
 
50
 
155
51
 
156
52
/*****************************************************************************
157
 
** MEMORY tables
 
53
** HEAP tables
158
54
*****************************************************************************/
159
55
 
160
 
ha_heap::ha_heap(plugin::StorageEngine &engine_arg,
161
 
                 Table &table_arg)
162
 
  :Cursor(engine_arg, table_arg), file(0), records_changed(0), key_stat_version(0),
 
56
ha_heap::ha_heap(handlerton *hton, TABLE_SHARE *table_arg)
 
57
  :handler(hton, table_arg), file(0), records_changed(0), key_stat_version(0), 
163
58
  internal_table(0)
164
59
{}
165
60
 
 
61
 
 
62
static const char *ha_heap_exts[] = {
 
63
  NullS
 
64
};
 
65
 
 
66
const char **ha_heap::bas_ext() const
 
67
{
 
68
  return ha_heap_exts;
 
69
}
 
70
 
166
71
/*
167
 
  Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to
168
 
  rec_per_key) after 1/MEMORY_STATS_UPDATE_THRESHOLD fraction of table records
169
 
  have been inserted/updated/deleted. delete_all_rows() and table flush cause
 
72
  Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to 
 
73
  rec_per_key) after 1/HEAP_STATS_UPDATE_THRESHOLD fraction of table records 
 
74
  have been inserted/updated/deleted. delete_all_rows() and table flush cause 
170
75
  immediate update.
171
76
 
172
77
  NOTE
173
78
   hash index statistics must be updated when number of table records changes
174
 
   from 0 to non-zero value and vice versa. Otherwise records_in_range may
 
79
   from 0 to non-zero value and vice versa. Otherwise records_in_range may 
175
80
   erroneously return 0 and 'range' may miss records.
176
81
*/
177
 
#define MEMORY_STATS_UPDATE_THRESHOLD 10
 
82
#define HEAP_STATS_UPDATE_THRESHOLD 10
178
83
 
179
 
int ha_heap::doOpen(const drizzled::identifier::Table &identifier, int mode, uint32_t test_if_locked)
 
84
int ha_heap::open(const char *name, int mode, uint test_if_locked)
180
85
{
181
 
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(identifier.getPath().c_str(), mode)) && errno == ENOENT))
 
86
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
182
87
  {
 
88
    HA_CREATE_INFO create_info;
183
89
    internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
 
90
    memset(&create_info, 0, sizeof(create_info));
184
91
    file= 0;
185
 
    HP_SHARE *internal_share= NULL;
186
 
    message::Table create_proto;
187
 
 
188
 
    if (not heap_storage_engine->heap_create_table(getTable()->in_use,
189
 
                                                   identifier.getPath().c_str(),
190
 
                                                   getTable(),
191
 
                                                   internal_table,
192
 
                                                   create_proto,
193
 
                                                   &internal_share))
 
92
    if (!create(name, table, &create_info))
194
93
    {
195
94
        file= internal_table ?
196
95
          heap_open_from_share(internal_share, mode) :
198
97
      if (!file)
199
98
      {
200
99
         /* Couldn't open table; Remove the newly created table */
201
 
        THR_LOCK_heap.lock();
 
100
        pthread_mutex_lock(&THR_LOCK_heap);
202
101
        hp_free(internal_share);
203
 
        THR_LOCK_heap.unlock();
 
102
        pthread_mutex_unlock(&THR_LOCK_heap);
204
103
      }
 
104
      implicit_emptied= 1;
205
105
    }
206
106
  }
207
107
  ref_length= sizeof(HEAP_PTR);
217
117
      ha_heap::info(), which is always called before key statistics are
218
118
      used.
219
119
    */
220
 
    key_stat_version= file->getShare()->key_stat_version - 1;
 
120
    key_stat_version= file->s->key_stat_version-1;
221
121
  }
222
122
  return (file ? 0 : 1);
223
123
}
232
132
  Create a copy of this table
233
133
 
234
134
  DESCRIPTION
235
 
    Do same as default implementation but use file->s->name instead of
236
 
    table->getShare()->path. This is needed by Windows where the clone() call sees
237
 
    '/'-delimited path in table->getShare()->path, while ha_peap::open() was called
 
135
    Do same as default implementation but use file->s->name instead of 
 
136
    table->s->path. This is needed by Windows where the clone() call sees
 
137
    '/'-delimited path in table->s->path, while ha_peap::open() was called 
238
138
    with '\'-delimited path.
239
139
*/
240
140
 
241
 
Cursor *ha_heap::clone(memory::Root *)
 
141
handler *ha_heap::clone(MEM_ROOT *mem_root)
242
142
{
243
 
  Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
244
 
  identifier::Table identifier(getTable()->getShare()->getSchemaName(),
245
 
                             getTable()->getShare()->getTableName(),
246
 
                             getTable()->getShare()->getPath());
247
 
 
248
 
  if (new_handler && !new_handler->ha_open(identifier, getTable()->db_stat,
 
143
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
 
144
  if (new_handler && !new_handler->ha_open(table, file->s->name, table->db_stat,
249
145
                                           HA_OPEN_IGNORE_IF_LOCKED))
250
146
    return new_handler;
251
 
  return NULL;
252
 
}
253
 
 
254
 
 
255
 
const char *ha_heap::index_type(uint32_t )
256
 
{
257
 
  return ("HASH");
 
147
  return NULL;  /* purecov: inspected */
258
148
}
259
149
 
260
150
 
276
166
 
277
167
void ha_heap::set_keys_for_scanning(void)
278
168
{
 
169
  btree_keys.clear_all();
 
170
  for (uint i= 0 ; i < table->s->keys ; i++)
 
171
  {
 
172
    if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
 
173
      btree_keys.set_bit(i);
 
174
  }
279
175
}
280
176
 
281
177
 
282
178
void ha_heap::update_key_stats()
283
179
{
284
 
  for (uint32_t i= 0; i < getTable()->getShare()->sizeKeys(); i++)
 
180
  for (uint i= 0; i < table->s->keys; i++)
285
181
  {
286
 
    KeyInfo *key= &getTable()->key_info[i];
287
 
 
 
182
    KEY *key=table->key_info+i;
288
183
    if (!key->rec_per_key)
289
184
      continue;
290
 
 
 
185
    if (key->algorithm != HA_KEY_ALG_BTREE)
291
186
    {
292
187
      if (key->flags & HA_NOSAME)
293
188
        key->rec_per_key[key->key_parts-1]= 1;
294
189
      else
295
190
      {
296
 
        ha_rows hash_buckets= file->getShare()->keydef[i].hash_buckets;
297
 
        uint32_t no_records= hash_buckets ? (uint) (file->getShare()->records/hash_buckets) : 2;
 
191
        ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
 
192
        uint no_records= hash_buckets ? (uint) (file->s->records/hash_buckets) : 2;
298
193
        if (no_records < 2)
299
194
          no_records= 2;
300
195
        key->rec_per_key[key->key_parts-1]= no_records;
303
198
  }
304
199
  records_changed= 0;
305
200
  /* At the end of update_key_stats() we can proudly claim they are OK. */
306
 
  key_stat_version= file->getShare()->key_stat_version;
 
201
  key_stat_version= file->s->key_stat_version;
307
202
}
308
203
 
309
204
 
310
 
int ha_heap::doInsertRecord(unsigned char * buf)
 
205
int ha_heap::write_row(uchar * buf)
311
206
{
312
207
  int res;
313
 
  if (getTable()->next_number_field && buf == getTable()->getInsertRecord())
 
208
  ha_statistic_increment(&SSV::ha_write_count);
 
209
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
210
    table->timestamp_field->set_time();
 
211
  if (table->next_number_field && buf == table->record[0])
314
212
  {
315
213
    if ((res= update_auto_increment()))
316
214
      return res;
317
215
  }
318
216
  res= heap_write(file,buf);
319
 
  if (!res && (++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
320
 
               file->getShare()->records))
 
217
  if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD > 
 
218
               file->s->records))
321
219
  {
322
220
    /*
323
221
       We can perform this safely since only one writer at the time is
324
222
       allowed on the table.
325
223
    */
326
 
    file->getShare()->key_stat_version++;
 
224
    file->s->key_stat_version++;
327
225
  }
328
226
  return res;
329
227
}
330
228
 
331
 
int ha_heap::doUpdateRecord(const unsigned char * old_data, unsigned char * new_data)
 
229
int ha_heap::update_row(const uchar * old_data, uchar * new_data)
332
230
{
333
231
  int res;
334
 
 
 
232
  ha_statistic_increment(&SSV::ha_update_count);
 
233
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 
234
    table->timestamp_field->set_time();
335
235
  res= heap_update(file,old_data,new_data);
336
 
  if (!res && ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
337
 
              file->getShare()->records)
 
236
  if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > 
 
237
              file->s->records)
338
238
  {
339
239
    /*
340
240
       We can perform this safely since only one writer at the time is
341
241
       allowed on the table.
342
242
    */
343
 
    file->getShare()->key_stat_version++;
 
243
    file->s->key_stat_version++;
344
244
  }
345
245
  return res;
346
246
}
347
247
 
348
 
int ha_heap::doDeleteRecord(const unsigned char * buf)
 
248
int ha_heap::delete_row(const uchar * buf)
349
249
{
350
250
  int res;
351
 
 
 
251
  ha_statistic_increment(&SSV::ha_delete_count);
352
252
  res= heap_delete(file,buf);
353
 
  if (!res && getTable()->getShare()->getType() == message::Table::STANDARD &&
354
 
      ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD > file->getShare()->records)
 
253
  if (!res && table->s->tmp_table == NO_TMP_TABLE && 
 
254
      ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
355
255
  {
356
256
    /*
357
257
       We can perform this safely since only one writer at the time is
358
258
       allowed on the table.
359
259
    */
360
 
    file->getShare()->key_stat_version++;
 
260
    file->s->key_stat_version++;
361
261
  }
362
262
  return res;
363
263
}
364
264
 
365
 
int ha_heap::index_read_map(unsigned char *buf, const unsigned char *key,
 
265
int ha_heap::index_read_map(uchar *buf, const uchar *key,
366
266
                            key_part_map keypart_map,
367
267
                            enum ha_rkey_function find_flag)
368
268
{
369
269
  assert(inited==INDEX);
370
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
270
  ha_statistic_increment(&SSV::ha_read_key_count);
371
271
  int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
372
 
  getTable()->status = error ? STATUS_NOT_FOUND : 0;
 
272
  table->status = error ? STATUS_NOT_FOUND : 0;
373
273
  return error;
374
274
}
375
275
 
376
 
int ha_heap::index_read_last_map(unsigned char *buf, const unsigned char *key,
 
276
int ha_heap::index_read_last_map(uchar *buf, const uchar *key,
377
277
                                 key_part_map keypart_map)
378
278
{
379
279
  assert(inited==INDEX);
380
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
280
  ha_statistic_increment(&SSV::ha_read_key_count);
381
281
  int error= heap_rkey(file, buf, active_index, key, keypart_map,
382
282
                       HA_READ_PREFIX_LAST);
383
 
  getTable()->status= error ? STATUS_NOT_FOUND : 0;
 
283
  table->status= error ? STATUS_NOT_FOUND : 0;
384
284
  return error;
385
285
}
386
286
 
387
 
int ha_heap::index_read_idx_map(unsigned char *buf, uint32_t index, const unsigned char *key,
 
287
int ha_heap::index_read_idx_map(uchar *buf, uint index, const uchar *key,
388
288
                                key_part_map keypart_map,
389
289
                                enum ha_rkey_function find_flag)
390
290
{
391
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
291
  ha_statistic_increment(&SSV::ha_read_key_count);
392
292
  int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
393
 
  getTable()->status = error ? STATUS_NOT_FOUND : 0;
 
293
  table->status = error ? STATUS_NOT_FOUND : 0;
394
294
  return error;
395
295
}
396
296
 
397
 
int ha_heap::index_next(unsigned char * buf)
 
297
int ha_heap::index_next(uchar * buf)
398
298
{
399
299
  assert(inited==INDEX);
400
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
300
  ha_statistic_increment(&SSV::ha_read_next_count);
401
301
  int error=heap_rnext(file,buf);
402
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
302
  table->status=error ? STATUS_NOT_FOUND: 0;
403
303
  return error;
404
304
}
405
305
 
406
 
int ha_heap::index_prev(unsigned char * buf)
 
306
int ha_heap::index_prev(uchar * buf)
407
307
{
408
308
  assert(inited==INDEX);
409
 
  ha_statistic_increment(&system_status_var::ha_read_prev_count);
 
309
  ha_statistic_increment(&SSV::ha_read_prev_count);
410
310
  int error=heap_rprev(file,buf);
411
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
311
  table->status=error ? STATUS_NOT_FOUND: 0;
412
312
  return error;
413
313
}
414
314
 
415
 
int ha_heap::index_first(unsigned char * buf)
 
315
int ha_heap::index_first(uchar * buf)
416
316
{
417
317
  assert(inited==INDEX);
418
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
318
  ha_statistic_increment(&SSV::ha_read_first_count);
419
319
  int error=heap_rfirst(file, buf, active_index);
420
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
320
  table->status=error ? STATUS_NOT_FOUND: 0;
421
321
  return error;
422
322
}
423
323
 
424
 
int ha_heap::index_last(unsigned char * buf)
 
324
int ha_heap::index_last(uchar * buf)
425
325
{
426
326
  assert(inited==INDEX);
427
 
  ha_statistic_increment(&system_status_var::ha_read_last_count);
 
327
  ha_statistic_increment(&SSV::ha_read_last_count);
428
328
  int error=heap_rlast(file, buf, active_index);
429
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
329
  table->status=error ? STATUS_NOT_FOUND: 0;
430
330
  return error;
431
331
}
432
332
 
433
 
int ha_heap::doStartTableScan(bool scan)
 
333
int ha_heap::rnd_init(bool scan)
434
334
{
435
335
  return scan ? heap_scan_init(file) : 0;
436
336
}
437
337
 
438
 
int ha_heap::rnd_next(unsigned char *buf)
 
338
int ha_heap::rnd_next(uchar *buf)
439
339
{
440
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
340
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
441
341
  int error=heap_scan(file, buf);
442
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
342
  table->status=error ? STATUS_NOT_FOUND: 0;
443
343
  return error;
444
344
}
445
345
 
446
 
int ha_heap::rnd_pos(unsigned char * buf, unsigned char *pos)
 
346
int ha_heap::rnd_pos(uchar * buf, uchar *pos)
447
347
{
448
348
  int error;
449
349
  HEAP_PTR heap_position;
450
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
 
350
  ha_statistic_increment(&SSV::ha_read_rnd_count);
451
351
  memcpy(&heap_position, pos, sizeof(HEAP_PTR));
452
352
  error=heap_rrnd(file, buf, heap_position);
453
 
  getTable()->status=error ? STATUS_NOT_FOUND: 0;
 
353
  table->status=error ? STATUS_NOT_FOUND: 0;
454
354
  return error;
455
355
}
456
356
 
457
 
void ha_heap::position(const unsigned char *)
 
357
void ha_heap::position(const uchar *record __attribute__((unused)))
458
358
{
459
359
  *(HEAP_PTR*) ref= heap_position(file);        // Ref is aligned
460
360
}
461
361
 
462
 
int ha_heap::info(uint32_t flag)
 
362
int ha_heap::info(uint flag)
463
363
{
464
364
  HEAPINFO hp_info;
465
365
  (void) heap_info(file,&hp_info,flag);
479
379
    have to update the key statistics. Hoping that a table lock is now
480
380
    in place.
481
381
  */
482
 
  if (key_stat_version != file->getShare()->key_stat_version)
 
382
  if (key_stat_version != file->s->key_stat_version)
483
383
    update_key_stats();
484
384
  return 0;
485
385
}
486
386
 
 
387
 
 
388
enum row_type ha_heap::get_row_type() const
 
389
{
 
390
  if (file->s->recordspace.is_variable_size)
 
391
    return ROW_TYPE_DYNAMIC;
 
392
 
 
393
  return ROW_TYPE_FIXED;
 
394
}
 
395
 
487
396
int ha_heap::extra(enum ha_extra_function operation)
488
397
{
489
398
  return heap_extra(file,operation);
499
408
int ha_heap::delete_all_rows()
500
409
{
501
410
  heap_clear(file);
502
 
  if (getTable()->getShare()->getType() == message::Table::STANDARD)
 
411
  if (table->s->tmp_table == NO_TMP_TABLE)
503
412
  {
504
413
    /*
505
414
       We can perform this safely since only one writer at the time is
506
415
       allowed on the table.
507
416
    */
508
 
    file->getShare()->key_stat_version++;
 
417
    file->s->key_stat_version++;
509
418
  }
510
419
  return 0;
511
420
}
512
421
 
 
422
int ha_heap::external_lock(THD *thd __attribute__((unused)),
 
423
                           int lock_type __attribute__((unused)))
 
424
{
 
425
  return 0;                                     // No external locking
 
426
}
 
427
 
 
428
 
513
429
/*
514
430
  Disable indexes.
515
431
 
534
450
    HA_ERR_WRONG_COMMAND  mode not implemented.
535
451
*/
536
452
 
537
 
int ha_heap::disable_indexes(uint32_t mode)
 
453
int ha_heap::disable_indexes(uint mode)
538
454
{
539
455
  int error;
540
456
 
568
484
    The indexes might have been disabled by disable_index() before.
569
485
    The function works only if both data and indexes are empty,
570
486
    since the heap storage engine cannot repair the indexes.
571
 
    To be sure, call Cursor::delete_all_rows() before.
 
487
    To be sure, call handler::delete_all_rows() before.
572
488
 
573
489
  IMPLEMENTATION
574
490
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
581
497
    HA_ERR_WRONG_COMMAND  mode not implemented.
582
498
*/
583
499
 
584
 
int ha_heap::enable_indexes(uint32_t mode)
 
500
int ha_heap::enable_indexes(uint mode)
585
501
{
586
502
  int error;
587
503
 
617
533
  return heap_indexes_are_disabled(file);
618
534
}
619
535
 
620
 
void ha_heap::drop_table(const char *)
621
 
{
622
 
  file->getShare()->delete_on_close= 1;
 
536
THR_LOCK_DATA **ha_heap::store_lock(THD *thd __attribute__((unused)),
 
537
                                    THR_LOCK_DATA **to,
 
538
                                    enum thr_lock_type lock_type)
 
539
{
 
540
  if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
 
541
    file->lock.type=lock_type;
 
542
  *to++= &file->lock;
 
543
  return to;
 
544
}
 
545
 
 
546
/*
 
547
  We have to ignore ENOENT entries as the HEAP table is created on open and
 
548
  not when doing a CREATE on the table.
 
549
*/
 
550
 
 
551
int ha_heap::delete_table(const char *name)
 
552
{
 
553
  int error= heap_delete_table(name);
 
554
  return error == ENOENT ? 0 : error;
 
555
}
 
556
 
 
557
 
 
558
void ha_heap::drop_table(const char *name __attribute__((unused)))
 
559
{
 
560
  file->s->delete_on_close= 1;
623
561
  close();
624
562
}
625
563
 
626
564
 
627
 
int HeapEngine::doRenameTable(Session &session, const identifier::Table &from, const identifier::Table &to)
 
565
int ha_heap::rename_table(const char * from, const char * to)
628
566
{
629
 
  session.getMessageCache().renameTableMessage(from, to);
630
 
  return heap_rename(from.getPath().c_str(), to.getPath().c_str());
 
567
  return heap_rename(from,to);
631
568
}
632
569
 
633
570
 
634
 
ha_rows ha_heap::records_in_range(uint32_t inx, key_range *min_key,
 
571
ha_rows ha_heap::records_in_range(uint inx, key_range *min_key,
635
572
                                  key_range *max_key)
636
573
{
637
 
  KeyInfo *key= &getTable()->key_info[inx];
 
574
  KEY *key=table->key_info+inx;
 
575
  if (key->algorithm == HA_KEY_ALG_BTREE)
 
576
    return hp_rb_records_in_range(file, inx, min_key, max_key);
638
577
 
639
578
  if (!min_key || !max_key ||
640
579
      min_key->length != max_key->length ||
647
586
    return stats.records;
648
587
 
649
588
  /* Assert that info() did run. We need current statistics here. */
650
 
  assert(key_stat_version == file->getShare()->key_stat_version);
 
589
  assert(key_stat_version == file->s->key_stat_version);
651
590
  return key->rec_per_key[key->key_parts-1];
652
591
}
653
592
 
654
 
int HeapEngine::doCreateTable(Session &session,
655
 
                              Table &table_arg,
656
 
                              const identifier::Table &identifier,
657
 
                              message::Table& create_proto)
658
 
{
659
 
  int error;
660
 
  HP_SHARE *internal_share;
661
 
  const char *table_name= identifier.getPath().c_str();
662
 
 
663
 
  error= heap_create_table(&session, table_name, &table_arg,
664
 
                           false, 
665
 
                           create_proto,
666
 
                           &internal_share);
667
 
 
668
 
  if (error == 0)
669
 
  {
670
 
    session.getMessageCache().storeTableMessage(identifier, create_proto);
671
 
  }
672
 
 
673
 
  return error;
674
 
}
675
 
 
676
 
 
677
 
int HeapEngine::heap_create_table(Session *session, const char *table_name,
678
 
                                  Table *table_arg,
679
 
                                  bool internal_table, 
680
 
                                  message::Table &create_proto,
681
 
                                  HP_SHARE **internal_share)
682
 
{
683
 
  uint32_t key, parts, mem_per_row_keys= 0;
684
 
  uint32_t keys= table_arg->getShare()->sizeKeys();
685
 
  uint32_t auto_key= 0, auto_key_type= 0;
686
 
  uint32_t max_key_fieldnr = 0, key_part_size = 0, next_field_pos = 0;
687
 
  uint32_t column_count= table_arg->getShare()->sizeFields();
688
 
  std::vector<HP_KEYDEF> keydef;
689
 
  int error;
 
593
 
 
594
int ha_heap::create(const char *name, Table *table_arg,
 
595
                    HA_CREATE_INFO *create_info)
 
596
{
 
597
  uint key, parts, mem_per_row_keys= 0, keys= table_arg->s->keys;
 
598
  uint auto_key= 0, auto_key_type= 0;
 
599
  uint max_key_fieldnr = 0, key_part_size = 0, next_field_pos = 0;
 
600
  uint column_idx, column_count= table_arg->s->fields;
 
601
  HP_COLUMNDEF *columndef;
 
602
  HP_KEYDEF *keydef;
 
603
  HA_KEYSEG *seg;
 
604
  char buff[FN_REFLEN];
 
605
  int error;
 
606
  TABLE_SHARE *share= table_arg->s;
690
607
  bool found_real_auto_increment= 0;
691
608
 
692
 
  /* 
693
 
   * We cannot create tables with more rows than UINT32_MAX.  This is a
694
 
   * limitation of the HEAP engine.  Here, since TableShare::getMaxRows()
695
 
   * can return a number more than that, we trap it here instead of casting
696
 
   * to a truncated integer.
697
 
   */
698
 
  uint64_t num_rows= table_arg->getShare()->getMaxRows();
699
 
  if (num_rows > UINT32_MAX)
700
 
    return -1;
 
609
  if (!(columndef= (HP_COLUMNDEF*) my_malloc(column_count * sizeof(HP_COLUMNDEF), MYF(MY_WME))))
 
610
    return my_errno;
 
611
 
 
612
  for (column_idx= 0; column_idx < column_count; column_idx++)
 
613
  {
 
614
    Field* field= *(table_arg->field + column_idx);
 
615
    HP_COLUMNDEF* column= columndef + column_idx;
 
616
    column->type= (uint16_t)field->type();
 
617
    column->length= field->pack_length();
 
618
    column->offset= field->offset(field->table->record[0]);
 
619
 
 
620
    if (field->null_bit)
 
621
    {
 
622
      column->null_bit= field->null_bit;
 
623
      column->null_pos= (uint) (field->null_ptr - (uchar*) table_arg->record[0]);
 
624
    }
 
625
    else
 
626
    {
 
627
      column->null_bit= 0;
 
628
      column->null_pos= 0;
 
629
    }
 
630
 
 
631
    if (field->type() == DRIZZLE_TYPE_VARCHAR)
 
632
    {
 
633
      column->length_bytes= (uint8_t)(((Field_varstring*)field)->length_bytes);
 
634
    }
 
635
    else
 
636
    {
 
637
      column->length_bytes= 0;
 
638
    }
 
639
  }
701
640
 
702
641
  for (key= parts= 0; key < keys; key++)
703
642
    parts+= table_arg->key_info[key].key_parts;
704
643
 
705
 
  keydef.resize(keys);
706
 
  std::vector<HA_KEYSEG> seg_buffer;
707
 
  seg_buffer.resize(parts);
708
 
  HA_KEYSEG *seg= &seg_buffer[0];
 
644
  if (!(keydef= (HP_KEYDEF*) my_malloc(keys * sizeof(HP_KEYDEF) +
 
645
                                       parts * sizeof(HA_KEYSEG),
 
646
                                       MYF(MY_WME))))
 
647
  {
 
648
    my_free((void *) columndef, MYF(0));
 
649
    return my_errno;
 
650
  }
709
651
 
 
652
  seg= my_reinterpret_cast(HA_KEYSEG*) (keydef + keys);
710
653
  for (key= 0; key < keys; key++)
711
654
  {
712
 
    KeyInfo *pos= &table_arg->key_info[key];
713
 
    KeyPartInfo *key_part=     pos->key_part;
714
 
    KeyPartInfo *key_part_end= key_part + pos->key_parts;
 
655
    KEY *pos= table_arg->key_info+key;
 
656
    KEY_PART_INFO *key_part=     pos->key_part;
 
657
    KEY_PART_INFO *key_part_end= key_part + pos->key_parts;
715
658
 
716
659
    keydef[key].keysegs=   (uint) pos->key_parts;
717
660
    keydef[key].flag=      (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
718
661
    keydef[key].seg=       seg;
719
662
 
720
 
    mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
 
663
    switch (pos->algorithm) {
 
664
    case HA_KEY_ALG_UNDEF:
 
665
    case HA_KEY_ALG_HASH:
 
666
      keydef[key].algorithm= HA_KEY_ALG_HASH;
 
667
      mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
 
668
      break;
 
669
    case HA_KEY_ALG_BTREE:
 
670
      keydef[key].algorithm= HA_KEY_ALG_BTREE;
 
671
      mem_per_row_keys+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
 
672
      break;
 
673
    default:
 
674
      assert(0); // cannot happen
 
675
    }
721
676
 
722
677
    for (; key_part != key_part_end; key_part++, seg++)
723
678
    {
724
679
      Field *field= key_part->field;
725
680
 
 
681
      if (pos->algorithm == HA_KEY_ALG_BTREE)
 
682
        seg->type= field->key_type();
 
683
      else
726
684
      {
727
685
        if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
728
686
            seg->type != HA_KEYTYPE_VARTEXT1 &&
738
696
      next_field_pos= seg->start + seg->length;
739
697
      if (field->type() == DRIZZLE_TYPE_VARCHAR)
740
698
      {
741
 
        next_field_pos+= (uint8_t)(((Field_varstring*)field)->pack_length_no_ptr());
 
699
        next_field_pos+= (uint8_t)(((Field_varstring*)field)->length_bytes);
742
700
      }
743
701
 
744
702
      if (next_field_pos > key_part_size) {
745
703
        key_part_size= next_field_pos;
746
704
      }
747
705
 
748
 
      if (field->flags & ENUM_FLAG)
 
706
      if (field->flags & (ENUM_FLAG | SET_FLAG))
749
707
        seg->charset= &my_charset_bin;
750
708
      else
751
709
        seg->charset= field->charset();
752
710
      if (field->null_ptr)
753
711
      {
754
712
        seg->null_bit= field->null_bit;
755
 
        seg->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->getInsertRecord());
 
713
        seg->null_pos= (uint) (field->null_ptr - (uchar*) table_arg->record[0]);
756
714
      }
757
715
      else
758
716
      {
761
719
      }
762
720
      if (field->flags & AUTO_INCREMENT_FLAG &&
763
721
          table_arg->found_next_number_field &&
764
 
          key == table_arg->getShare()->next_number_index)
 
722
          key == share->next_number_index)
765
723
      {
766
724
        /*
767
725
          Store key number and type for found auto_increment key
770
728
        auto_key= key+ 1;
771
729
        auto_key_type= field->key_type();
772
730
      }
773
 
      if ((uint)field->position() + 1 > max_key_fieldnr)
 
731
      if ((uint)field->field_index + 1 > max_key_fieldnr)
774
732
      {
775
733
        /* Do not use seg->fieldnr as it's not reliable in case of temp tables */
776
 
        max_key_fieldnr= field->position() + 1;
 
734
        max_key_fieldnr= field->field_index + 1;
777
735
      }
778
736
    }
779
737
  }
780
 
 
781
 
  if (key_part_size < table_arg->getShare()->null_bytes + ((table_arg->getShare()->last_null_bit_pos+7) >> 3))
 
738
  
 
739
  if (key_part_size < share->null_bytes + ((share->last_null_bit_pos+7) >> 3))
782
740
  {
783
741
    /* Make sure to include null fields regardless of the presense of keys */
784
 
    key_part_size = table_arg->getShare()->null_bytes + ((table_arg->getShare()->last_null_bit_pos+7) >> 3);
 
742
    key_part_size = share->null_bytes + ((share->last_null_bit_pos+7) >> 3);
785
743
  }
786
744
 
787
 
 
788
 
 
 
745
  
 
746
  
789
747
  if (table_arg->found_next_number_field)
790
748
  {
791
 
    keydef[table_arg->getShare()->next_number_index].flag|= HA_AUTO_KEY;
792
 
    found_real_auto_increment= table_arg->getShare()->next_number_key_offset == 0;
 
749
    keydef[share->next_number_index].flag|= HA_AUTO_KEY;
 
750
    found_real_auto_increment= share->next_number_key_offset == 0;
793
751
  }
794
752
  HP_CREATE_INFO hp_create_info;
795
753
  hp_create_info.auto_key= auto_key;
796
754
  hp_create_info.auto_key_type= auto_key_type;
797
 
  hp_create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
798
 
                                  create_proto.options().auto_increment_value() - 1 : 0);
799
 
  hp_create_info.max_table_size=session->variables.max_heap_table_size;
 
755
  hp_create_info.auto_increment= (create_info->auto_increment_value ?
 
756
                                  create_info->auto_increment_value - 1 : 0);
 
757
  hp_create_info.max_table_size=current_thd->variables.max_heap_table_size;
800
758
  hp_create_info.with_auto_increment= found_real_auto_increment;
801
759
  hp_create_info.internal_table= internal_table;
802
 
  hp_create_info.max_chunk_size= table_arg->getShare()->block_size;
803
 
 
804
 
  error= heap_create(table_name,
805
 
                     keys, &keydef[0],
806
 
                     column_count,
807
 
                     key_part_size,
808
 
                     table_arg->getShare()->getRecordLength(), mem_per_row_keys,
809
 
                     static_cast<uint32_t>(num_rows), /* We check for overflow above, so cast is fine here. */
810
 
                     0, // Factor out MIN
811
 
                     &hp_create_info, internal_share);
812
 
 
 
760
  hp_create_info.max_chunk_size= share->block_size;
 
761
  hp_create_info.is_dynamic= (share->row_type == ROW_TYPE_DYNAMIC);
 
762
  error= heap_create(fn_format(buff,name,"","",
 
763
                               MY_REPLACE_EXT|MY_UNPACK_FILENAME),
 
764
                   keys, keydef,
 
765
         column_count, columndef,
 
766
         max_key_fieldnr, key_part_size,
 
767
         share->reclength, mem_per_row_keys,
 
768
         (uint32_t) share->max_rows, (uint32_t) share->min_rows,
 
769
         &hp_create_info, &internal_share);
 
770
  
 
771
  my_free((uchar*) keydef, MYF(0));
 
772
  my_free((void *) columndef, MYF(0));
 
773
  assert(file == 0);
813
774
  return (error);
814
775
}
815
776
 
816
777
 
817
 
void ha_heap::get_auto_increment(uint64_t, uint64_t, uint64_t,
 
778
void ha_heap::update_create_info(HA_CREATE_INFO *create_info)
 
779
{
 
780
  table->file->info(HA_STATUS_AUTO);
 
781
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
 
782
    create_info->auto_increment_value= stats.auto_increment_value;
 
783
  if (!(create_info->used_fields & HA_CREATE_USED_BLOCK_SIZE))
 
784
  {
 
785
    if (file->s->recordspace.is_variable_size)
 
786
      create_info->block_size= file->s->recordspace.chunk_length;
 
787
    else
 
788
      create_info->block_size= 0;
 
789
  }
 
790
}
 
791
 
 
792
void ha_heap::get_auto_increment(uint64_t offset __attribute__((unused)),
 
793
                                 uint64_t increment __attribute__((unused)),
 
794
                                 uint64_t nb_desired_values __attribute__((unused)),
818
795
                                 uint64_t *first_value,
819
796
                                 uint64_t *nb_reserved_values)
820
797
{
825
802
}
826
803
 
827
804
 
828
 
int ha_heap::cmp_ref(const unsigned char *ref1, const unsigned char *ref2)
 
805
bool ha_heap::check_if_incompatible_data(HA_CREATE_INFO *info,
 
806
                                         uint table_changes)
829
807
{
830
 
  return memcmp(ref1, ref2, sizeof(HEAP_PTR));
 
808
  /* Check that auto_increment value was not changed */
 
809
  if ((info->used_fields & HA_CREATE_USED_AUTO &&
 
810
       info->auto_increment_value != 0) ||
 
811
      table_changes == IS_EQUAL_NO ||
 
812
      table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
 
813
    return COMPATIBLE_DATA_NO;
 
814
  return COMPATIBLE_DATA_YES;
831
815
}
832
816
 
833
 
 
834
 
DRIZZLE_DECLARE_PLUGIN
 
817
mysql_declare_plugin(heap)
835
818
{
836
 
  DRIZZLE_VERSION_ID,
 
819
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
837
820
  "MEMORY",
838
821
  "1.0",
839
822
  "MySQL AB",
840
823
  "Hash based, stored in memory, useful for temporary tables",
841
824
  PLUGIN_LICENSE_GPL,
842
825
  heap_init,
843
 
  NULL,                       /* depends */
 
826
  heap_deinit,
 
827
  NULL,                       /* status variables                */
 
828
  NULL,                       /* system variables                */
844
829
  NULL                        /* config options                  */
845
830
}
846
 
DRIZZLE_DECLARE_PLUGIN_END;
 
831
mysql_declare_plugin_end;