~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/heap/ha_heap.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
13
13
   along with this program; if not, write to the Free Software
14
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
 
#include "heap_priv.h"
17
 
#include <drizzled/error.h>
18
 
#include <drizzled/table.h>
19
 
#include <drizzled/session.h>
20
 
#include <drizzled/current_session.h>
21
 
#include <drizzled/field/timestamp.h>
22
 
#include <drizzled/field/varstring.h>
23
 
 
24
 
#include "heap.h"
 
16
 
 
17
#ifdef USE_PRAGMA_IMPLEMENTATION
 
18
#pragma implementation                          // gcc: Class implementation
 
19
#endif
 
20
 
 
21
#define MYSQL_SERVER 1
 
22
#include "mysql_priv.h"
 
23
#include <mysql/plugin.h>
25
24
#include "ha_heap.h"
26
 
 
27
 
#include <string>
28
 
 
29
 
 
30
 
using namespace drizzled;
31
 
using namespace std;
32
 
 
33
 
static const string engine_name("MEMORY");
34
 
 
35
 
pthread_mutex_t THR_LOCK_heap= PTHREAD_MUTEX_INITIALIZER;
36
 
 
37
 
static const char *ha_heap_exts[] = {
38
 
  NULL
39
 
};
40
 
 
41
 
class HeapEngine : public drizzled::plugin::StorageEngine
42
 
{
43
 
public:
44
 
  HeapEngine(string name_arg)
45
 
   : drizzled::plugin::StorageEngine(name_arg,
46
 
                                     HTON_STATS_RECORDS_IS_EXACT |
47
 
                                     HTON_NULL_IN_KEY |
48
 
                                     HTON_FAST_KEY_READ |
49
 
                                     HTON_NO_BLOBS |
50
 
                                     HTON_HAS_RECORDS |
51
 
                                     HTON_SKIP_STORE_LOCK |
52
 
                                     HTON_TEMPORARY_ONLY)
53
 
  { }
54
 
 
55
 
  virtual Cursor *create(TableShare &table,
56
 
                          memory::Root *mem_root)
57
 
  {
58
 
    return new (mem_root) ha_heap(*this, table);
59
 
  }
60
 
 
61
 
  const char **bas_ext() const {
62
 
    return ha_heap_exts;
63
 
  }
64
 
 
65
 
  int doCreateTable(Session *session,
66
 
                    const char *table_name,
67
 
                    Table& table_arg,
68
 
                    drizzled::message::Table &create_proto);
69
 
 
70
 
  /* For whatever reason, internal tables can be created by Cursor::open()
71
 
     for MEMORY.
72
 
     Instead of diving down a rat hole, let's just cry ourselves to sleep
73
 
     at night with this odd hackish workaround.
74
 
   */
75
 
  int heap_create_table(Session *session, const char *table_name,
76
 
                        Table *table_arg,
77
 
                        bool internal_table,
78
 
                        drizzled::message::Table &create_proto,
79
 
                        HP_SHARE **internal_share);
80
 
 
81
 
  int doRenameTable(Session*, const char * from, const char * to);
82
 
 
83
 
  int doDropTable(Session&, const string table_path);
84
 
 
85
 
  int doGetTableDefinition(Session& session,
86
 
                           const char* path,
87
 
                           const char *db,
88
 
                           const char *table_name,
89
 
                           const bool is_tmp,
90
 
                           drizzled::message::Table *table_proto);
91
 
 
92
 
  /* Temp only engine, so do not return values. */
93
 
  void doGetTableNames(drizzled::CachedDirectory &, string& , set<string>&) { };
94
 
 
95
 
  uint32_t max_supported_keys()          const { return MAX_KEY; }
96
 
  uint32_t max_supported_key_part_length() const { return MAX_KEY_LENGTH; }
97
 
 
98
 
  uint32_t index_flags(enum  ha_key_alg algorithm) const
99
 
  {
100
 
    return ((algorithm == HA_KEY_ALG_BTREE) ?
101
 
            HA_READ_NEXT |
102
 
            HA_READ_PREV |
103
 
            HA_READ_ORDER |
104
 
            HA_READ_RANGE :
105
 
            HA_ONLY_WHOLE_INDEX |
106
 
            HA_KEY_SCAN_NOT_ROR);
107
 
  }
108
 
 
109
 
};
110
 
 
111
 
int HeapEngine::doGetTableDefinition(Session&,
112
 
                                     const char* path,
113
 
                                     const char *,
114
 
                                     const char *,
115
 
                                     const bool,
116
 
                                     drizzled::message::Table *table_proto)
117
 
{
118
 
  int error= ENOENT;
119
 
  ProtoCache::iterator iter;
120
 
 
121
 
  pthread_mutex_lock(&proto_cache_mutex);
122
 
  iter= proto_cache.find(path);
123
 
 
124
 
  if (iter!= proto_cache.end())
125
 
  {
126
 
    if (table_proto)
127
 
      table_proto->CopyFrom(((*iter).second));
128
 
    error= EEXIST;
129
 
  }
130
 
  pthread_mutex_unlock(&proto_cache_mutex);
131
 
 
132
 
  return error;
133
 
}
134
 
/*
135
 
  We have to ignore ENOENT entries as the MEMORY table is created on open and
136
 
  not when doing a CREATE on the table.
137
 
*/
138
 
int HeapEngine::doDropTable(Session&, const string table_path)
139
 
{
140
 
  ProtoCache::iterator iter;
141
 
 
142
 
  pthread_mutex_lock(&proto_cache_mutex);
143
 
  iter= proto_cache.find(table_path.c_str());
144
 
 
145
 
  if (iter!= proto_cache.end())
146
 
    proto_cache.erase(iter);
147
 
  pthread_mutex_unlock(&proto_cache_mutex);
148
 
 
149
 
  return heap_delete_table(table_path.c_str());
150
 
}
151
 
 
152
 
static HeapEngine *heap_storage_engine= NULL;
153
 
 
154
 
static int heap_init(drizzled::plugin::Registry &registry)
155
 
{
156
 
  heap_storage_engine= new HeapEngine(engine_name);
157
 
  registry.add(heap_storage_engine);
158
 
  pthread_mutex_init(&THR_LOCK_heap, MY_MUTEX_INIT_FAST);
 
25
#include "heapdef.h"
 
26
 
 
27
static handler *heap_create_handler(handlerton *hton,
 
28
                                    TABLE_SHARE *table, 
 
29
                                    MEM_ROOT *mem_root);
 
30
 
 
31
int heap_panic(handlerton *hton, ha_panic_function flag)
 
32
{
 
33
  return hp_panic(flag);
 
34
}
 
35
 
 
36
 
 
37
int heap_init(void *p)
 
38
{
 
39
  handlerton *heap_hton;
 
40
 
 
41
  heap_hton= (handlerton *)p;
 
42
  heap_hton->state=      SHOW_OPTION_YES;
 
43
  heap_hton->db_type=    DB_TYPE_HEAP;
 
44
  heap_hton->create=     heap_create_handler;
 
45
  heap_hton->panic=      heap_panic;
 
46
  heap_hton->flags=      HTON_CAN_RECREATE;
 
47
 
159
48
  return 0;
160
49
}
161
50
 
162
 
static int heap_deinit(drizzled::plugin::Registry &registry)
 
51
static handler *heap_create_handler(handlerton *hton,
 
52
                                    TABLE_SHARE *table, 
 
53
                                    MEM_ROOT *mem_root)
163
54
{
164
 
  registry.remove(heap_storage_engine);
165
 
  delete heap_storage_engine;
166
 
 
167
 
  int ret= hp_panic(HA_PANIC_CLOSE);
168
 
 
169
 
  pthread_mutex_destroy(&THR_LOCK_heap);
170
 
 
171
 
  return ret;
 
55
  return new (mem_root) ha_heap(hton, table);
172
56
}
173
57
 
174
58
 
175
 
 
176
59
/*****************************************************************************
177
 
** MEMORY tables
 
60
** HEAP tables
178
61
*****************************************************************************/
179
62
 
180
 
ha_heap::ha_heap(drizzled::plugin::StorageEngine &engine_arg,
181
 
                 TableShare &table_arg)
182
 
  :Cursor(engine_arg, table_arg), file(0), records_changed(0), key_stat_version(0),
 
63
ha_heap::ha_heap(handlerton *hton, TABLE_SHARE *table_arg)
 
64
  :handler(hton, table_arg), file(0), records_changed(0), key_stat_version(0), 
183
65
  internal_table(0)
184
66
{}
185
67
 
 
68
 
 
69
static const char *ha_heap_exts[] = {
 
70
  NullS
 
71
};
 
72
 
 
73
const char **ha_heap::bas_ext() const
 
74
{
 
75
  return ha_heap_exts;
 
76
}
 
77
 
186
78
/*
187
 
  Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to
188
 
  rec_per_key) after 1/MEMORY_STATS_UPDATE_THRESHOLD fraction of table records
189
 
  have been inserted/updated/deleted. delete_all_rows() and table flush cause
 
79
  Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to 
 
80
  rec_per_key) after 1/HEAP_STATS_UPDATE_THRESHOLD fraction of table records 
 
81
  have been inserted/updated/deleted. delete_all_rows() and table flush cause 
190
82
  immediate update.
191
83
 
192
84
  NOTE
193
85
   hash index statistics must be updated when number of table records changes
194
 
   from 0 to non-zero value and vice versa. Otherwise records_in_range may
 
86
   from 0 to non-zero value and vice versa. Otherwise records_in_range may 
195
87
   erroneously return 0 and 'range' may miss records.
196
88
*/
197
 
#define MEMORY_STATS_UPDATE_THRESHOLD 10
 
89
#define HEAP_STATS_UPDATE_THRESHOLD 10
198
90
 
199
 
int ha_heap::open(const char *name, int mode, uint32_t test_if_locked)
 
91
int ha_heap::open(const char *name, int mode, uint test_if_locked)
200
92
{
201
 
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && errno == ENOENT))
 
93
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
202
94
  {
203
95
    HA_CREATE_INFO create_info;
204
96
    internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
205
 
    memset(&create_info, 0, sizeof(create_info));
 
97
    bzero(&create_info, sizeof(create_info));
206
98
    file= 0;
207
 
    HP_SHARE *internal_share= NULL;
208
 
    drizzled::message::Table create_proto;
209
 
 
210
 
    if (!heap_storage_engine->heap_create_table(ha_session(), name, table,
211
 
                                                internal_table,
212
 
                                                create_proto,
213
 
                                                &internal_share))
 
99
    if (!create(name, table, &create_info))
214
100
    {
215
101
        file= internal_table ?
216
102
          heap_open_from_share(internal_share, mode) :
253
139
  Create a copy of this table
254
140
 
255
141
  DESCRIPTION
256
 
    Do same as default implementation but use file->s->name instead of
 
142
    Do same as default implementation but use file->s->name instead of 
257
143
    table->s->path. This is needed by Windows where the clone() call sees
258
 
    '/'-delimited path in table->s->path, while ha_peap::open() was called
 
144
    '/'-delimited path in table->s->path, while ha_peap::open() was called 
259
145
    with '\'-delimited path.
260
146
*/
261
147
 
262
 
Cursor *ha_heap::clone(memory::Root *mem_root)
 
148
handler *ha_heap::clone(MEM_ROOT *mem_root)
263
149
{
264
 
  Cursor *new_handler= table->s->db_type()->getCursor(*table->s, mem_root);
265
 
 
 
150
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
266
151
  if (new_handler && !new_handler->ha_open(table, file->s->name, table->db_stat,
267
152
                                           HA_OPEN_IGNORE_IF_LOCKED))
268
153
    return new_handler;
269
 
  return NULL;
270
 
}
271
 
 
272
 
 
273
 
const char *ha_heap::index_type(uint32_t inx)
274
 
{
275
 
  return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ?
276
 
          "BTREE" : "HASH");
 
154
  return NULL;  /* purecov: inspected */
277
155
}
278
156
 
279
157
 
295
173
 
296
174
void ha_heap::set_keys_for_scanning(void)
297
175
{
298
 
  btree_keys.reset();
299
 
  for (uint32_t i= 0 ; i < table->s->keys ; i++)
 
176
  btree_keys.clear_all();
 
177
  for (uint i= 0 ; i < table->s->keys ; i++)
300
178
  {
301
179
    if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
302
 
      btree_keys.set(i);
 
180
      btree_keys.set_bit(i);
303
181
  }
304
182
}
305
183
 
306
184
 
307
185
void ha_heap::update_key_stats()
308
186
{
309
 
  for (uint32_t i= 0; i < table->s->keys; i++)
 
187
  for (uint i= 0; i < table->s->keys; i++)
310
188
  {
311
189
    KEY *key=table->key_info+i;
312
190
    if (!key->rec_per_key)
318
196
      else
319
197
      {
320
198
        ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
321
 
        uint32_t no_records= hash_buckets ? (uint) (file->s->records/hash_buckets) : 2;
 
199
        uint no_records= hash_buckets ? (uint) (file->s->records/hash_buckets) : 2;
322
200
        if (no_records < 2)
323
201
          no_records= 2;
324
202
        key->rec_per_key[key->key_parts-1]= no_records;
331
209
}
332
210
 
333
211
 
334
 
int ha_heap::write_row(unsigned char * buf)
 
212
int ha_heap::write_row(uchar * buf)
335
213
{
336
214
  int res;
337
215
  ha_statistic_increment(&SSV::ha_write_count);
 
216
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
 
217
    table->timestamp_field->set_time();
338
218
  if (table->next_number_field && buf == table->record[0])
339
219
  {
340
220
    if ((res= update_auto_increment()))
341
221
      return res;
342
222
  }
343
223
  res= heap_write(file,buf);
344
 
  if (!res && (++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
 
224
  if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD > 
345
225
               file->s->records))
346
226
  {
347
227
    /*
353
233
  return res;
354
234
}
355
235
 
356
 
int ha_heap::update_row(const unsigned char * old_data, unsigned char * new_data)
 
236
int ha_heap::update_row(const uchar * old_data, uchar * new_data)
357
237
{
358
238
  int res;
359
239
  ha_statistic_increment(&SSV::ha_update_count);
360
240
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
361
241
    table->timestamp_field->set_time();
362
242
  res= heap_update(file,old_data,new_data);
363
 
  if (!res && ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
 
243
  if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > 
364
244
              file->s->records)
365
245
  {
366
246
    /*
372
252
  return res;
373
253
}
374
254
 
375
 
int ha_heap::delete_row(const unsigned char * buf)
 
255
int ha_heap::delete_row(const uchar * buf)
376
256
{
377
257
  int res;
378
258
  ha_statistic_increment(&SSV::ha_delete_count);
379
259
  res= heap_delete(file,buf);
380
 
  if (!res && table->s->tmp_table == NO_TMP_TABLE &&
381
 
      ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD > file->s->records)
 
260
  if (!res && table->s->tmp_table == NO_TMP_TABLE && 
 
261
      ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
382
262
  {
383
263
    /*
384
264
       We can perform this safely since only one writer at the time is
389
269
  return res;
390
270
}
391
271
 
392
 
int ha_heap::index_read_map(unsigned char *buf, const unsigned char *key,
 
272
int ha_heap::index_read_map(uchar *buf, const uchar *key,
393
273
                            key_part_map keypart_map,
394
274
                            enum ha_rkey_function find_flag)
395
275
{
396
 
  assert(inited==INDEX);
 
276
  DBUG_ASSERT(inited==INDEX);
397
277
  ha_statistic_increment(&SSV::ha_read_key_count);
398
278
  int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
399
279
  table->status = error ? STATUS_NOT_FOUND : 0;
400
280
  return error;
401
281
}
402
282
 
403
 
int ha_heap::index_read_last_map(unsigned char *buf, const unsigned char *key,
 
283
int ha_heap::index_read_last_map(uchar *buf, const uchar *key,
404
284
                                 key_part_map keypart_map)
405
285
{
406
 
  assert(inited==INDEX);
 
286
  DBUG_ASSERT(inited==INDEX);
407
287
  ha_statistic_increment(&SSV::ha_read_key_count);
408
288
  int error= heap_rkey(file, buf, active_index, key, keypart_map,
409
289
                       HA_READ_PREFIX_LAST);
411
291
  return error;
412
292
}
413
293
 
414
 
int ha_heap::index_read_idx_map(unsigned char *buf, uint32_t index, const unsigned char *key,
 
294
int ha_heap::index_read_idx_map(uchar *buf, uint index, const uchar *key,
415
295
                                key_part_map keypart_map,
416
296
                                enum ha_rkey_function find_flag)
417
297
{
421
301
  return error;
422
302
}
423
303
 
424
 
int ha_heap::index_next(unsigned char * buf)
 
304
int ha_heap::index_next(uchar * buf)
425
305
{
426
 
  assert(inited==INDEX);
 
306
  DBUG_ASSERT(inited==INDEX);
427
307
  ha_statistic_increment(&SSV::ha_read_next_count);
428
308
  int error=heap_rnext(file,buf);
429
309
  table->status=error ? STATUS_NOT_FOUND: 0;
430
310
  return error;
431
311
}
432
312
 
433
 
int ha_heap::index_prev(unsigned char * buf)
 
313
int ha_heap::index_prev(uchar * buf)
434
314
{
435
 
  assert(inited==INDEX);
 
315
  DBUG_ASSERT(inited==INDEX);
436
316
  ha_statistic_increment(&SSV::ha_read_prev_count);
437
317
  int error=heap_rprev(file,buf);
438
318
  table->status=error ? STATUS_NOT_FOUND: 0;
439
319
  return error;
440
320
}
441
321
 
442
 
int ha_heap::index_first(unsigned char * buf)
 
322
int ha_heap::index_first(uchar * buf)
443
323
{
444
 
  assert(inited==INDEX);
 
324
  DBUG_ASSERT(inited==INDEX);
445
325
  ha_statistic_increment(&SSV::ha_read_first_count);
446
326
  int error=heap_rfirst(file, buf, active_index);
447
327
  table->status=error ? STATUS_NOT_FOUND: 0;
448
328
  return error;
449
329
}
450
330
 
451
 
int ha_heap::index_last(unsigned char * buf)
 
331
int ha_heap::index_last(uchar * buf)
452
332
{
453
 
  assert(inited==INDEX);
 
333
  DBUG_ASSERT(inited==INDEX);
454
334
  ha_statistic_increment(&SSV::ha_read_last_count);
455
335
  int error=heap_rlast(file, buf, active_index);
456
336
  table->status=error ? STATUS_NOT_FOUND: 0;
462
342
  return scan ? heap_scan_init(file) : 0;
463
343
}
464
344
 
465
 
int ha_heap::rnd_next(unsigned char *buf)
 
345
int ha_heap::rnd_next(uchar *buf)
466
346
{
467
347
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
468
348
  int error=heap_scan(file, buf);
470
350
  return error;
471
351
}
472
352
 
473
 
int ha_heap::rnd_pos(unsigned char * buf, unsigned char *pos)
 
353
int ha_heap::rnd_pos(uchar * buf, uchar *pos)
474
354
{
475
355
  int error;
476
356
  HEAP_PTR heap_position;
477
357
  ha_statistic_increment(&SSV::ha_read_rnd_count);
478
 
  memcpy(&heap_position, pos, sizeof(HEAP_PTR));
 
358
  memcpy_fixed((char*) &heap_position, pos, sizeof(HEAP_PTR));
479
359
  error=heap_rrnd(file, buf, heap_position);
480
360
  table->status=error ? STATUS_NOT_FOUND: 0;
481
361
  return error;
482
362
}
483
363
 
484
 
void ha_heap::position(const unsigned char *)
 
364
void ha_heap::position(const uchar *record)
485
365
{
486
366
  *(HEAP_PTR*) ref= heap_position(file);        // Ref is aligned
487
367
}
488
368
 
489
 
int ha_heap::info(uint32_t flag)
 
369
int ha_heap::info(uint flag)
490
370
{
491
371
  HEAPINFO hp_info;
492
372
  (void) heap_info(file,&hp_info,flag);
512
392
}
513
393
 
514
394
 
515
 
enum row_type ha_heap::get_row_type() const
516
 
{
517
 
  if (file->s->recordspace.is_variable_size)
518
 
    return ROW_TYPE_DYNAMIC;
519
 
 
520
 
  return ROW_TYPE_FIXED;
521
 
}
522
 
 
523
395
int ha_heap::extra(enum ha_extra_function operation)
524
396
{
525
397
  return heap_extra(file,operation);
546
418
  return 0;
547
419
}
548
420
 
 
421
int ha_heap::external_lock(THD *thd, int lock_type)
 
422
{
 
423
  return 0;                                     // No external locking
 
424
}
 
425
 
 
426
 
549
427
/*
550
428
  Disable indexes.
551
429
 
570
448
    HA_ERR_WRONG_COMMAND  mode not implemented.
571
449
*/
572
450
 
573
 
int ha_heap::disable_indexes(uint32_t mode)
 
451
int ha_heap::disable_indexes(uint mode)
574
452
{
575
453
  int error;
576
454
 
604
482
    The indexes might have been disabled by disable_index() before.
605
483
    The function works only if both data and indexes are empty,
606
484
    since the heap storage engine cannot repair the indexes.
607
 
    To be sure, call Cursor::delete_all_rows() before.
 
485
    To be sure, call handler::delete_all_rows() before.
608
486
 
609
487
  IMPLEMENTATION
610
488
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
617
495
    HA_ERR_WRONG_COMMAND  mode not implemented.
618
496
*/
619
497
 
620
 
int ha_heap::enable_indexes(uint32_t mode)
 
498
int ha_heap::enable_indexes(uint mode)
621
499
{
622
500
  int error;
623
501
 
653
531
  return heap_indexes_are_disabled(file);
654
532
}
655
533
 
656
 
void ha_heap::drop_table(const char *)
 
534
THR_LOCK_DATA **ha_heap::store_lock(THD *thd,
 
535
                                    THR_LOCK_DATA **to,
 
536
                                    enum thr_lock_type lock_type)
 
537
{
 
538
  if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
 
539
    file->lock.type=lock_type;
 
540
  *to++= &file->lock;
 
541
  return to;
 
542
}
 
543
 
 
544
/*
 
545
  We have to ignore ENOENT entries as the HEAP table is created on open and
 
546
  not when doing a CREATE on the table.
 
547
*/
 
548
 
 
549
int ha_heap::delete_table(const char *name)
 
550
{
 
551
  int error= heap_delete_table(name);
 
552
  return error == ENOENT ? 0 : error;
 
553
}
 
554
 
 
555
 
 
556
void ha_heap::drop_table(const char *name)
657
557
{
658
558
  file->s->delete_on_close= 1;
659
559
  close();
660
560
}
661
561
 
662
562
 
663
 
int HeapEngine::doRenameTable(Session*,
664
 
                              const char *from, const char *to)
 
563
int ha_heap::rename_table(const char * from, const char * to)
665
564
{
666
565
  return heap_rename(from,to);
667
566
}
668
567
 
669
568
 
670
 
ha_rows ha_heap::records_in_range(uint32_t inx, key_range *min_key,
 
569
ha_rows ha_heap::records_in_range(uint inx, key_range *min_key,
671
570
                                  key_range *max_key)
672
571
{
673
572
  KEY *key=table->key_info+inx;
685
584
    return stats.records;
686
585
 
687
586
  /* Assert that info() did run. We need current statistics here. */
688
 
  assert(key_stat_version == file->s->key_stat_version);
 
587
  DBUG_ASSERT(key_stat_version == file->s->key_stat_version);
689
588
  return key->rec_per_key[key->key_parts-1];
690
589
}
691
590
 
692
 
int HeapEngine::doCreateTable(Session *session,
693
 
                              const char *table_name,
694
 
                              Table &table_arg,
695
 
                              drizzled::message::Table& create_proto)
696
 
{
697
 
  int error;
698
 
  HP_SHARE *internal_share;
699
 
 
700
 
  error= heap_create_table(session, table_name, &table_arg,
701
 
                           false, 
702
 
                           create_proto,
703
 
                           &internal_share);
704
 
 
705
 
  if (error == 0)
706
 
  {
707
 
    pthread_mutex_lock(&proto_cache_mutex);
708
 
    proto_cache.insert(make_pair(table_name, create_proto));
709
 
    pthread_mutex_unlock(&proto_cache_mutex);
710
 
  }
711
 
 
712
 
  return error;
713
 
}
714
 
 
715
 
 
716
 
int HeapEngine::heap_create_table(Session *session, const char *table_name,
717
 
                                  Table *table_arg,
718
 
                                  bool internal_table, 
719
 
                                  drizzled::message::Table &create_proto,
720
 
                                  HP_SHARE **internal_share)
721
 
{
722
 
  uint32_t key, parts, mem_per_row_keys= 0, keys= table_arg->s->keys;
723
 
  uint32_t auto_key= 0, auto_key_type= 0;
724
 
  uint32_t max_key_fieldnr = 0, key_part_size = 0, next_field_pos = 0;
725
 
  uint32_t column_idx, column_count= table_arg->s->fields;
726
 
  HP_COLUMNDEF *columndef;
 
591
 
 
592
int ha_heap::create(const char *name, TABLE *table_arg,
 
593
                    HA_CREATE_INFO *create_info)
 
594
{
 
595
  uint key, parts, mem_per_row= 0, keys= table_arg->s->keys;
 
596
  uint auto_key= 0, auto_key_type= 0;
 
597
  ha_rows max_rows;
727
598
  HP_KEYDEF *keydef;
728
599
  HA_KEYSEG *seg;
729
 
  char buff[FN_REFLEN];
730
600
  int error;
731
 
  TableShare *share= table_arg->s;
 
601
  TABLE_SHARE *share= table_arg->s;
732
602
  bool found_real_auto_increment= 0;
733
603
 
734
 
  /* 
735
 
   * We cannot create tables with more rows than UINT32_MAX.  This is a
736
 
   * limitation of the HEAP engine.  Here, since TableShare::getMaxRows()
737
 
   * can return a number more than that, we trap it here instead of casting
738
 
   * to a truncated integer.
739
 
   */
740
 
  uint64_t num_rows= share->getMaxRows();
741
 
  if (num_rows > UINT32_MAX)
742
 
    return -1;
743
 
 
744
 
  if (!(columndef= (HP_COLUMNDEF*) malloc(column_count * sizeof(HP_COLUMNDEF))))
745
 
    return errno;
746
 
 
747
 
  for (column_idx= 0; column_idx < column_count; column_idx++)
748
 
  {
749
 
    Field* field= *(table_arg->field + column_idx);
750
 
    HP_COLUMNDEF* column= columndef + column_idx;
751
 
    column->type= (uint16_t)field->type();
752
 
    column->length= field->pack_length();
753
 
    column->offset= field->offset(field->table->record[0]);
754
 
 
755
 
    if (field->null_bit)
756
 
    {
757
 
      column->null_bit= field->null_bit;
758
 
      column->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->record[0]);
759
 
    }
760
 
    else
761
 
    {
762
 
      column->null_bit= 0;
763
 
      column->null_pos= 0;
764
 
    }
765
 
 
766
 
    if (field->type() == DRIZZLE_TYPE_VARCHAR)
767
 
    {
768
 
      column->length_bytes= (uint8_t)(((Field_varstring*)field)->length_bytes);
769
 
    }
770
 
    else
771
 
    {
772
 
      column->length_bytes= 0;
773
 
    }
774
 
  }
775
 
 
776
604
  for (key= parts= 0; key < keys; key++)
777
605
    parts+= table_arg->key_info[key].key_parts;
778
606
 
779
 
  if (!(keydef= (HP_KEYDEF*) malloc(keys * sizeof(HP_KEYDEF) +
780
 
                                    parts * sizeof(HA_KEYSEG))))
781
 
  {
782
 
    free((void *) columndef);
783
 
    return errno;
784
 
  }
785
 
 
786
 
  seg= reinterpret_cast<HA_KEYSEG*> (keydef + keys);
 
607
  if (!(keydef= (HP_KEYDEF*) my_malloc(keys * sizeof(HP_KEYDEF) +
 
608
                                       parts * sizeof(HA_KEYSEG),
 
609
                                       MYF(MY_WME))))
 
610
    return my_errno;
 
611
  seg= my_reinterpret_cast(HA_KEYSEG*) (keydef + keys);
787
612
  for (key= 0; key < keys; key++)
788
613
  {
789
614
    KEY *pos= table_arg->key_info+key;
798
623
    case HA_KEY_ALG_UNDEF:
799
624
    case HA_KEY_ALG_HASH:
800
625
      keydef[key].algorithm= HA_KEY_ALG_HASH;
801
 
      mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
 
626
      mem_per_row+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
802
627
      break;
803
628
    case HA_KEY_ALG_BTREE:
804
629
      keydef[key].algorithm= HA_KEY_ALG_BTREE;
805
 
      mem_per_row_keys+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
 
630
      mem_per_row+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
806
631
      break;
807
632
    default:
808
 
      assert(0); // cannot happen
 
633
      DBUG_ASSERT(0); // cannot happen
809
634
    }
810
635
 
811
636
    for (; key_part != key_part_end; key_part++, seg++)
827
652
      seg->length=  (uint) key_part->length;
828
653
      seg->flag=    key_part->key_part_flag;
829
654
 
830
 
      next_field_pos= seg->start + seg->length;
831
 
      if (field->type() == DRIZZLE_TYPE_VARCHAR)
832
 
      {
833
 
        next_field_pos+= (uint8_t)(((Field_varstring*)field)->length_bytes);
834
 
      }
835
 
 
836
 
      if (next_field_pos > key_part_size) {
837
 
        key_part_size= next_field_pos;
838
 
      }
839
 
 
840
655
      if (field->flags & (ENUM_FLAG | SET_FLAG))
841
656
        seg->charset= &my_charset_bin;
842
657
      else
844
659
      if (field->null_ptr)
845
660
      {
846
661
        seg->null_bit= field->null_bit;
847
 
        seg->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->record[0]);
 
662
        seg->null_pos= (uint) (field->null_ptr - (uchar*) table_arg->record[0]);
848
663
      }
849
664
      else
850
665
      {
862
677
        auto_key= key+ 1;
863
678
        auto_key_type= field->key_type();
864
679
      }
865
 
      if ((uint)field->field_index + 1 > max_key_fieldnr)
866
 
      {
867
 
        /* Do not use seg->fieldnr as it's not reliable in case of temp tables */
868
 
        max_key_fieldnr= field->field_index + 1;
869
 
      }
870
680
    }
871
681
  }
872
 
 
873
 
  if (key_part_size < share->null_bytes + ((share->last_null_bit_pos+7) >> 3))
874
 
  {
875
 
    /* Make sure to include null fields regardless of the presense of keys */
876
 
    key_part_size = share->null_bytes + ((share->last_null_bit_pos+7) >> 3);
877
 
  }
878
 
 
879
 
 
880
 
 
 
682
  mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*));
 
683
  max_rows = (ha_rows) (table_arg->in_use->variables.max_heap_table_size /
 
684
                        (uint64_t) mem_per_row);
881
685
  if (table_arg->found_next_number_field)
882
686
  {
883
687
    keydef[share->next_number_index].flag|= HA_AUTO_KEY;
886
690
  HP_CREATE_INFO hp_create_info;
887
691
  hp_create_info.auto_key= auto_key;
888
692
  hp_create_info.auto_key_type= auto_key_type;
889
 
  hp_create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
890
 
                                  create_proto.options().auto_increment_value() - 1 : 0);
891
 
  hp_create_info.max_table_size=session->variables.max_heap_table_size;
 
693
  hp_create_info.auto_increment= (create_info->auto_increment_value ?
 
694
                                  create_info->auto_increment_value - 1 : 0);
 
695
  hp_create_info.max_table_size=current_thd->variables.max_heap_table_size;
892
696
  hp_create_info.with_auto_increment= found_real_auto_increment;
893
697
  hp_create_info.internal_table= internal_table;
894
 
  hp_create_info.max_chunk_size= share->block_size;
895
 
  hp_create_info.is_dynamic= (share->row_type == ROW_TYPE_DYNAMIC);
896
 
 
897
 
  error= heap_create(fn_format(buff,table_name,"","",
898
 
                              MY_REPLACE_EXT|MY_UNPACK_FILENAME),
899
 
                    keys, keydef,
900
 
                    column_count, columndef,
901
 
                    max_key_fieldnr, key_part_size,
902
 
                    share->reclength, mem_per_row_keys,
903
 
                    static_cast<uint32_t>(num_rows), /* We check for overflow above, so cast is fine here. */
904
 
                    0, // Factor out MIN
905
 
                    &hp_create_info, internal_share);
906
 
 
907
 
  free((unsigned char*) keydef);
908
 
  free((void *) columndef);
909
 
 
 
698
  max_rows = (ha_rows) (hp_create_info.max_table_size / mem_per_row);
 
699
  error= heap_create(name,
 
700
                     keys, keydef, share->reclength,
 
701
                     (ulong) ((share->max_rows < max_rows &&
 
702
                               share->max_rows) ? 
 
703
                              share->max_rows : max_rows),
 
704
                     (ulong) share->min_rows, &hp_create_info, &internal_share);
 
705
  my_free((uchar*) keydef, MYF(0));
 
706
  DBUG_ASSERT(file == 0);
910
707
  return (error);
911
708
}
912
709
 
913
710
 
914
 
void ha_heap::get_auto_increment(uint64_t, uint64_t, uint64_t,
 
711
void ha_heap::update_create_info(HA_CREATE_INFO *create_info)
 
712
{
 
713
  table->file->info(HA_STATUS_AUTO);
 
714
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
 
715
    create_info->auto_increment_value= stats.auto_increment_value;
 
716
}
 
717
 
 
718
void ha_heap::get_auto_increment(uint64_t offset, uint64_t increment,
 
719
                                 uint64_t nb_desired_values,
915
720
                                 uint64_t *first_value,
916
721
                                 uint64_t *nb_reserved_values)
917
722
{
918
723
  ha_heap::info(HA_STATUS_AUTO);
919
724
  *first_value= stats.auto_increment_value;
920
725
  /* such table has only table-level locking so reserves up to +inf */
921
 
  *nb_reserved_values= UINT64_MAX;
922
 
}
923
 
 
924
 
 
925
 
int ha_heap::cmp_ref(const unsigned char *ref1, const unsigned char *ref2)
926
 
{
927
 
  return memcmp(ref1, ref2, sizeof(HEAP_PTR));
928
 
}
929
 
 
930
 
 
931
 
DRIZZLE_DECLARE_PLUGIN
932
 
{
933
 
  DRIZZLE_VERSION_ID,
 
726
  *nb_reserved_values= ULONGLONG_MAX;
 
727
}
 
728
 
 
729
 
 
730
bool ha_heap::check_if_incompatible_data(HA_CREATE_INFO *info,
 
731
                                         uint table_changes)
 
732
{
 
733
  /* Check that auto_increment value was not changed */
 
734
  if ((info->used_fields & HA_CREATE_USED_AUTO &&
 
735
       info->auto_increment_value != 0) ||
 
736
      table_changes == IS_EQUAL_NO ||
 
737
      table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
 
738
    return COMPATIBLE_DATA_NO;
 
739
  return COMPATIBLE_DATA_YES;
 
740
}
 
741
 
 
742
struct st_mysql_storage_engine heap_storage_engine=
 
743
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
744
 
 
745
mysql_declare_plugin(heap)
 
746
{
 
747
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
748
  &heap_storage_engine,
934
749
  "MEMORY",
935
 
  "1.0",
936
750
  "MySQL AB",
937
751
  "Hash based, stored in memory, useful for temporary tables",
938
752
  PLUGIN_LICENSE_GPL,
939
753
  heap_init,
940
 
  heap_deinit,
 
754
  NULL,
 
755
  0x0100, /* 1.0 */
941
756
  NULL,                       /* status variables                */
942
757
  NULL,                       /* system variables                */
943
758
  NULL                        /* config options                  */
944
759
}
945
 
DRIZZLE_DECLARE_PLUGIN_END;
 
760
mysql_declare_plugin_end;