~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/heap/ha_heap.cc

  • Committer: Brian Aker
  • Date: 2008-10-06 06:47:29 UTC
  • Revision ID: brian@tangent.org-20081006064729-2i9mhjkzyvow9xsm
RemoveĀ uint.

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
 
#include "drizzled/plugin/daemon.h"
24
 
 
25
 
#include "heap.h"
 
16
#define DRIZZLE_SERVER 1
 
17
#include <drizzled/server_includes.h>
26
18
#include "ha_heap.h"
27
 
 
28
 
#include <string>
29
 
 
30
 
 
31
 
using namespace drizzled;
32
 
using namespace std;
33
 
 
34
 
static const string engine_name("MEMORY");
35
 
 
36
 
pthread_mutex_t THR_LOCK_heap= PTHREAD_MUTEX_INITIALIZER;
37
 
 
38
 
static const char *ha_heap_exts[] = {
39
 
  NULL
40
 
};
41
 
 
42
 
class HeapEngine : public plugin::StorageEngine
43
 
{
44
 
public:
45
 
  explicit HeapEngine(string name_arg) :
46
 
    plugin::StorageEngine(name_arg,
47
 
                          HTON_STATS_RECORDS_IS_EXACT |
48
 
                          HTON_NULL_IN_KEY |
49
 
                          HTON_FAST_KEY_READ |
50
 
                          HTON_NO_BLOBS |
51
 
                          HTON_HAS_RECORDS |
52
 
                          HTON_SKIP_STORE_LOCK |
53
 
                          HTON_TEMPORARY_ONLY)
54
 
  {
55
 
    pthread_mutex_init(&THR_LOCK_heap, MY_MUTEX_INIT_FAST);
56
 
  }
57
 
 
58
 
  virtual ~HeapEngine()
59
 
  {
60
 
    hp_panic(HA_PANIC_CLOSE);
61
 
 
62
 
    pthread_mutex_destroy(&THR_LOCK_heap);
63
 
  }
64
 
 
65
 
  virtual Cursor *create(TableShare &table,
66
 
                          memory::Root *mem_root)
67
 
  {
68
 
    return new (mem_root) ha_heap(*this, table);
69
 
  }
70
 
 
71
 
  const char **bas_ext() const {
72
 
    return ha_heap_exts;
73
 
  }
74
 
 
75
 
  int doCreateTable(Session &session,
76
 
                    Table &table_arg,
77
 
                    drizzled::TableIdentifier &identifier,
78
 
                    message::Table &create_proto);
79
 
 
80
 
  /* For whatever reason, internal tables can be created by Cursor::open()
81
 
     for MEMORY.
82
 
     Instead of diving down a rat hole, let's just cry ourselves to sleep
83
 
     at night with this odd hackish workaround.
84
 
   */
85
 
  int heap_create_table(Session *session, const char *table_name,
86
 
                        Table *table_arg,
87
 
                        bool internal_table,
88
 
                        message::Table &create_proto,
89
 
                        HP_SHARE **internal_share);
90
 
 
91
 
  int doRenameTable(Session&, TableIdentifier &from, TableIdentifier &to);
92
 
 
93
 
  int doDropTable(Session&, TableIdentifier &identifier);
94
 
 
95
 
  int doGetTableDefinition(Session& session,
96
 
                           TableIdentifier &identifier,
97
 
                           message::Table &table_message);
98
 
 
99
 
  /* Temp only engine, so do not return values. */
100
 
  void doGetTableNames(CachedDirectory &, SchemaIdentifier& , set<string>&) { };
101
 
 
102
 
  uint32_t max_supported_keys()          const { return MAX_KEY; }
103
 
  uint32_t max_supported_key_part_length() const { return MAX_KEY_LENGTH; }
104
 
 
105
 
  uint32_t index_flags(enum  ha_key_alg algorithm) const
106
 
  {
107
 
    return ((algorithm == HA_KEY_ALG_BTREE) ?
108
 
            HA_READ_NEXT |
109
 
            HA_READ_PREV |
110
 
            HA_READ_ORDER |
111
 
            HA_READ_RANGE :
112
 
            HA_ONLY_WHOLE_INDEX |
113
 
            HA_KEY_SCAN_NOT_ROR);
114
 
  }
115
 
 
116
 
  bool doDoesTableExist(Session& session, TableIdentifier &identifier);
117
 
  void doGetTableIdentifiers(drizzled::CachedDirectory &directory,
118
 
                             drizzled::SchemaIdentifier &schema_identifier,
119
 
                             drizzled::TableIdentifiers &set_of_identifiers);
120
 
};
121
 
 
122
 
void HeapEngine::doGetTableIdentifiers(drizzled::CachedDirectory&,
123
 
                                       drizzled::SchemaIdentifier&,
124
 
                                       drizzled::TableIdentifiers&)
125
 
{
126
 
}
127
 
 
128
 
bool HeapEngine::doDoesTableExist(Session& session, TableIdentifier &identifier)
129
 
{
130
 
  return session.doesTableMessageExist(identifier);
131
 
}
132
 
 
133
 
int HeapEngine::doGetTableDefinition(Session &session,
134
 
                                     TableIdentifier &identifier,
135
 
                                     message::Table &table_proto)
136
 
{
137
 
  if (session.getTableMessage(identifier, table_proto))
138
 
    return EEXIST;
139
 
 
140
 
  return ENOENT;
141
 
}
142
 
/*
143
 
  We have to ignore ENOENT entries as the MEMORY table is created on open and
144
 
  not when doing a CREATE on the table.
145
 
*/
146
 
int HeapEngine::doDropTable(Session &session, TableIdentifier &identifier)
147
 
{
148
 
  session.removeTableMessage(identifier);
149
 
 
150
 
  int error= heap_delete_table(identifier.getPath().c_str());
151
 
 
152
 
  if (error == ENOENT)
153
 
    error= 0;
154
 
 
155
 
  return error;
156
 
}
157
 
 
158
 
static HeapEngine *heap_storage_engine= NULL;
159
 
 
160
 
static int heap_init(plugin::Context &context)
161
 
{
162
 
  heap_storage_engine= new HeapEngine(engine_name);
163
 
  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
 
164
41
  return 0;
165
42
}
166
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
 
167
51
 
168
52
/*****************************************************************************
169
 
** MEMORY tables
 
53
** HEAP tables
170
54
*****************************************************************************/
171
55
 
172
 
ha_heap::ha_heap(plugin::StorageEngine &engine_arg,
173
 
                 TableShare &table_arg)
174
 
  :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), 
175
58
  internal_table(0)
176
59
{}
177
60
 
 
61
 
 
62
static const char *ha_heap_exts[] = {
 
63
  NULL
 
64
};
 
65
 
 
66
const char **ha_heap::bas_ext() const
 
67
{
 
68
  return ha_heap_exts;
 
69
}
 
70
 
178
71
/*
179
 
  Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to
180
 
  rec_per_key) after 1/MEMORY_STATS_UPDATE_THRESHOLD fraction of table records
181
 
  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 
182
75
  immediate update.
183
76
 
184
77
  NOTE
185
78
   hash index statistics must be updated when number of table records changes
186
 
   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 
187
80
   erroneously return 0 and 'range' may miss records.
188
81
*/
189
 
#define MEMORY_STATS_UPDATE_THRESHOLD 10
 
82
#define HEAP_STATS_UPDATE_THRESHOLD 10
190
83
 
191
84
int ha_heap::open(const char *name, int mode, uint32_t test_if_locked)
192
85
{
193
 
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && errno == ENOENT))
 
86
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
194
87
  {
195
88
    HA_CREATE_INFO create_info;
196
89
    internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
197
90
    memset(&create_info, 0, sizeof(create_info));
198
91
    file= 0;
199
 
    HP_SHARE *internal_share= NULL;
200
 
    message::Table create_proto;
201
 
 
202
 
    if (!heap_storage_engine->heap_create_table(ha_session(), name, table,
203
 
                                                internal_table,
204
 
                                                create_proto,
205
 
                                                &internal_share))
 
92
    if (!create(name, table, &create_info))
206
93
    {
207
94
        file= internal_table ?
208
95
          heap_open_from_share(internal_share, mode) :
245
132
  Create a copy of this table
246
133
 
247
134
  DESCRIPTION
248
 
    Do same as default implementation but use file->s->name instead of
 
135
    Do same as default implementation but use file->s->name instead of 
249
136
    table->s->path. This is needed by Windows where the clone() call sees
250
 
    '/'-delimited path in table->s->path, while ha_peap::open() was called
 
137
    '/'-delimited path in table->s->path, while ha_peap::open() was called 
251
138
    with '\'-delimited path.
252
139
*/
253
140
 
254
 
Cursor *ha_heap::clone(memory::Root *mem_root)
 
141
handler *ha_heap::clone(MEM_ROOT *mem_root)
255
142
{
256
 
  Cursor *new_handler= table->s->db_type()->getCursor(*table->s, mem_root);
257
 
 
 
143
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
258
144
  if (new_handler && !new_handler->ha_open(table, file->s->name, table->db_stat,
259
145
                                           HA_OPEN_IGNORE_IF_LOCKED))
260
146
    return new_handler;
261
 
  return NULL;
262
 
}
263
 
 
264
 
 
265
 
const char *ha_heap::index_type(uint32_t inx)
266
 
{
267
 
  return ((table_share->key_info[inx].algorithm == HA_KEY_ALG_BTREE) ?
268
 
          "BTREE" : "HASH");
 
147
  return NULL;  /* purecov: inspected */
269
148
}
270
149
 
271
150
 
287
166
 
288
167
void ha_heap::set_keys_for_scanning(void)
289
168
{
290
 
  btree_keys.reset();
 
169
  btree_keys.clear_all();
291
170
  for (uint32_t i= 0 ; i < table->s->keys ; i++)
292
171
  {
293
172
    if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
294
 
      btree_keys.set(i);
 
173
      btree_keys.set_bit(i);
295
174
  }
296
175
}
297
176
 
326
205
int ha_heap::write_row(unsigned char * buf)
327
206
{
328
207
  int res;
329
 
  ha_statistic_increment(&system_status_var::ha_write_count);
 
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();
330
211
  if (table->next_number_field && buf == table->record[0])
331
212
  {
332
213
    if ((res= update_auto_increment()))
333
214
      return res;
334
215
  }
335
216
  res= heap_write(file,buf);
336
 
  if (!res && (++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
 
217
  if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD > 
337
218
               file->s->records))
338
219
  {
339
220
    /*
348
229
int ha_heap::update_row(const unsigned char * old_data, unsigned char * new_data)
349
230
{
350
231
  int res;
351
 
  ha_statistic_increment(&system_status_var::ha_update_count);
 
232
  ha_statistic_increment(&SSV::ha_update_count);
352
233
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
353
234
    table->timestamp_field->set_time();
354
235
  res= heap_update(file,old_data,new_data);
355
 
  if (!res && ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD >
 
236
  if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > 
356
237
              file->s->records)
357
238
  {
358
239
    /*
367
248
int ha_heap::delete_row(const unsigned char * buf)
368
249
{
369
250
  int res;
370
 
  ha_statistic_increment(&system_status_var::ha_delete_count);
 
251
  ha_statistic_increment(&SSV::ha_delete_count);
371
252
  res= heap_delete(file,buf);
372
 
  if (!res && table->s->tmp_table == message::Table::STANDARD &&
373
 
      ++records_changed*MEMORY_STATS_UPDATE_THRESHOLD > file->s->records)
 
253
  if (!res && table->s->tmp_table == NO_TMP_TABLE && 
 
254
      ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
374
255
  {
375
256
    /*
376
257
       We can perform this safely since only one writer at the time is
386
267
                            enum ha_rkey_function find_flag)
387
268
{
388
269
  assert(inited==INDEX);
389
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
270
  ha_statistic_increment(&SSV::ha_read_key_count);
390
271
  int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
391
272
  table->status = error ? STATUS_NOT_FOUND : 0;
392
273
  return error;
396
277
                                 key_part_map keypart_map)
397
278
{
398
279
  assert(inited==INDEX);
399
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
280
  ha_statistic_increment(&SSV::ha_read_key_count);
400
281
  int error= heap_rkey(file, buf, active_index, key, keypart_map,
401
282
                       HA_READ_PREFIX_LAST);
402
283
  table->status= error ? STATUS_NOT_FOUND : 0;
407
288
                                key_part_map keypart_map,
408
289
                                enum ha_rkey_function find_flag)
409
290
{
410
 
  ha_statistic_increment(&system_status_var::ha_read_key_count);
 
291
  ha_statistic_increment(&SSV::ha_read_key_count);
411
292
  int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
412
293
  table->status = error ? STATUS_NOT_FOUND : 0;
413
294
  return error;
416
297
int ha_heap::index_next(unsigned char * buf)
417
298
{
418
299
  assert(inited==INDEX);
419
 
  ha_statistic_increment(&system_status_var::ha_read_next_count);
 
300
  ha_statistic_increment(&SSV::ha_read_next_count);
420
301
  int error=heap_rnext(file,buf);
421
302
  table->status=error ? STATUS_NOT_FOUND: 0;
422
303
  return error;
425
306
int ha_heap::index_prev(unsigned char * buf)
426
307
{
427
308
  assert(inited==INDEX);
428
 
  ha_statistic_increment(&system_status_var::ha_read_prev_count);
 
309
  ha_statistic_increment(&SSV::ha_read_prev_count);
429
310
  int error=heap_rprev(file,buf);
430
311
  table->status=error ? STATUS_NOT_FOUND: 0;
431
312
  return error;
434
315
int ha_heap::index_first(unsigned char * buf)
435
316
{
436
317
  assert(inited==INDEX);
437
 
  ha_statistic_increment(&system_status_var::ha_read_first_count);
 
318
  ha_statistic_increment(&SSV::ha_read_first_count);
438
319
  int error=heap_rfirst(file, buf, active_index);
439
320
  table->status=error ? STATUS_NOT_FOUND: 0;
440
321
  return error;
443
324
int ha_heap::index_last(unsigned char * buf)
444
325
{
445
326
  assert(inited==INDEX);
446
 
  ha_statistic_increment(&system_status_var::ha_read_last_count);
 
327
  ha_statistic_increment(&SSV::ha_read_last_count);
447
328
  int error=heap_rlast(file, buf, active_index);
448
329
  table->status=error ? STATUS_NOT_FOUND: 0;
449
330
  return error;
456
337
 
457
338
int ha_heap::rnd_next(unsigned char *buf)
458
339
{
459
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
 
340
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
460
341
  int error=heap_scan(file, buf);
461
342
  table->status=error ? STATUS_NOT_FOUND: 0;
462
343
  return error;
466
347
{
467
348
  int error;
468
349
  HEAP_PTR heap_position;
469
 
  ha_statistic_increment(&system_status_var::ha_read_rnd_count);
 
350
  ha_statistic_increment(&SSV::ha_read_rnd_count);
470
351
  memcpy(&heap_position, pos, sizeof(HEAP_PTR));
471
352
  error=heap_rrnd(file, buf, heap_position);
472
353
  table->status=error ? STATUS_NOT_FOUND: 0;
473
354
  return error;
474
355
}
475
356
 
476
 
void ha_heap::position(const unsigned char *)
 
357
void ha_heap::position(const unsigned char *record __attribute__((unused)))
477
358
{
478
359
  *(HEAP_PTR*) ref= heap_position(file);        // Ref is aligned
479
360
}
527
408
int ha_heap::delete_all_rows()
528
409
{
529
410
  heap_clear(file);
530
 
  if (table->s->tmp_table == message::Table::STANDARD)
 
411
  if (table->s->tmp_table == NO_TMP_TABLE)
531
412
  {
532
413
    /*
533
414
       We can perform this safely since only one writer at the time is
538
419
  return 0;
539
420
}
540
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
 
541
429
/*
542
430
  Disable indexes.
543
431
 
596
484
    The indexes might have been disabled by disable_index() before.
597
485
    The function works only if both data and indexes are empty,
598
486
    since the heap storage engine cannot repair the indexes.
599
 
    To be sure, call Cursor::delete_all_rows() before.
 
487
    To be sure, call handler::delete_all_rows() before.
600
488
 
601
489
  IMPLEMENTATION
602
490
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
645
533
  return heap_indexes_are_disabled(file);
646
534
}
647
535
 
648
 
void ha_heap::drop_table(const char *)
 
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)))
649
559
{
650
560
  file->s->delete_on_close= 1;
651
561
  close();
652
562
}
653
563
 
654
564
 
655
 
int HeapEngine::doRenameTable(Session &session, TableIdentifier &from, TableIdentifier &to)
 
565
int ha_heap::rename_table(const char * from, const char * to)
656
566
{
657
 
  session.renameTableMessage(from, to);
658
 
  return heap_rename(from.getPath().c_str(), to.getPath().c_str());
 
567
  return heap_rename(from,to);
659
568
}
660
569
 
661
570
 
681
590
  return key->rec_per_key[key->key_parts-1];
682
591
}
683
592
 
684
 
int HeapEngine::doCreateTable(Session &session,
685
 
                              Table &table_arg,
686
 
                              drizzled::TableIdentifier &identifier,
687
 
                              message::Table& create_proto)
688
 
{
689
 
  int error;
690
 
  HP_SHARE *internal_share;
691
 
  const char *table_name= identifier.getPath().c_str();
692
 
 
693
 
  error= heap_create_table(&session, table_name, &table_arg,
694
 
                           false, 
695
 
                           create_proto,
696
 
                           &internal_share);
697
 
 
698
 
  if (error == 0)
699
 
  {
700
 
    session.storeTableMessage(identifier, create_proto);
701
 
  }
702
 
 
703
 
  return error;
704
 
}
705
 
 
706
 
 
707
 
int HeapEngine::heap_create_table(Session *session, const char *table_name,
708
 
                                  Table *table_arg,
709
 
                                  bool internal_table, 
710
 
                                  message::Table &create_proto,
711
 
                                  HP_SHARE **internal_share)
 
593
 
 
594
int ha_heap::create(const char *name, Table *table_arg,
 
595
                    HA_CREATE_INFO *create_info)
712
596
{
713
597
  uint32_t key, parts, mem_per_row_keys= 0, keys= table_arg->s->keys;
714
598
  uint32_t auto_key= 0, auto_key_type= 0;
719
603
  HA_KEYSEG *seg;
720
604
  char buff[FN_REFLEN];
721
605
  int error;
722
 
  TableShare *share= table_arg->s;
 
606
  TABLE_SHARE *share= table_arg->s;
723
607
  bool found_real_auto_increment= 0;
724
608
 
725
 
  /* 
726
 
   * We cannot create tables with more rows than UINT32_MAX.  This is a
727
 
   * limitation of the HEAP engine.  Here, since TableShare::getMaxRows()
728
 
   * can return a number more than that, we trap it here instead of casting
729
 
   * to a truncated integer.
730
 
   */
731
 
  uint64_t num_rows= share->getMaxRows();
732
 
  if (num_rows > UINT32_MAX)
733
 
    return -1;
734
 
 
735
 
  if (!(columndef= (HP_COLUMNDEF*) malloc(column_count * sizeof(HP_COLUMNDEF))))
736
 
    return errno;
 
609
  if (!(columndef= (HP_COLUMNDEF*) my_malloc(column_count * sizeof(HP_COLUMNDEF), MYF(MY_WME))))
 
610
    return my_errno;
737
611
 
738
612
  for (column_idx= 0; column_idx < column_count; column_idx++)
739
613
  {
767
641
  for (key= parts= 0; key < keys; key++)
768
642
    parts+= table_arg->key_info[key].key_parts;
769
643
 
770
 
  if (!(keydef= (HP_KEYDEF*) malloc(keys * sizeof(HP_KEYDEF) +
771
 
                                    parts * sizeof(HA_KEYSEG))))
 
644
  if (!(keydef= (HP_KEYDEF*) my_malloc(keys * sizeof(HP_KEYDEF) +
 
645
                                       parts * sizeof(HA_KEYSEG),
 
646
                                       MYF(MY_WME))))
772
647
  {
773
648
    free((void *) columndef);
774
 
    return errno;
 
649
    return my_errno;
775
650
  }
776
651
 
777
652
  seg= reinterpret_cast<HA_KEYSEG*> (keydef + keys);
828
703
        key_part_size= next_field_pos;
829
704
      }
830
705
 
831
 
      if (field->flags & ENUM_FLAG)
 
706
      if (field->flags & (ENUM_FLAG | SET_FLAG))
832
707
        seg->charset= &my_charset_bin;
833
708
      else
834
709
        seg->charset= field->charset();
860
735
      }
861
736
    }
862
737
  }
863
 
 
 
738
  
864
739
  if (key_part_size < share->null_bytes + ((share->last_null_bit_pos+7) >> 3))
865
740
  {
866
741
    /* Make sure to include null fields regardless of the presense of keys */
867
742
    key_part_size = share->null_bytes + ((share->last_null_bit_pos+7) >> 3);
868
743
  }
869
744
 
870
 
 
871
 
 
 
745
  
 
746
  
872
747
  if (table_arg->found_next_number_field)
873
748
  {
874
749
    keydef[share->next_number_index].flag|= HA_AUTO_KEY;
877
752
  HP_CREATE_INFO hp_create_info;
878
753
  hp_create_info.auto_key= auto_key;
879
754
  hp_create_info.auto_key_type= auto_key_type;
880
 
  hp_create_info.auto_increment= (create_proto.options().has_auto_increment_value() ?
881
 
                                  create_proto.options().auto_increment_value() - 1 : 0);
882
 
  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;
883
758
  hp_create_info.with_auto_increment= found_real_auto_increment;
884
759
  hp_create_info.internal_table= internal_table;
885
760
  hp_create_info.max_chunk_size= share->block_size;
886
761
  hp_create_info.is_dynamic= (share->row_type == ROW_TYPE_DYNAMIC);
887
 
 
888
 
  error= heap_create(internal::fn_format(buff,table_name,"","",
889
 
                              MY_REPLACE_EXT|MY_UNPACK_FILENAME),
890
 
                    keys, keydef,
891
 
                    column_count, columndef,
892
 
                    max_key_fieldnr, key_part_size,
893
 
                    share->reclength, mem_per_row_keys,
894
 
                    static_cast<uint32_t>(num_rows), /* We check for overflow above, so cast is fine here. */
895
 
                    0, // Factor out MIN
896
 
                    &hp_create_info, internal_share);
897
 
 
 
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
  
898
771
  free((unsigned char*) keydef);
899
772
  free((void *) columndef);
900
 
 
 
773
  assert(file == 0);
901
774
  return (error);
902
775
}
903
776
 
904
777
 
905
 
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)),
906
795
                                 uint64_t *first_value,
907
796
                                 uint64_t *nb_reserved_values)
908
797
{
913
802
}
914
803
 
915
804
 
916
 
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
                                         uint32_t table_changes)
917
807
{
918
 
  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;
919
815
}
920
816
 
921
 
 
922
 
DRIZZLE_DECLARE_PLUGIN
 
817
mysql_declare_plugin(heap)
923
818
{
924
 
  DRIZZLE_VERSION_ID,
 
819
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
925
820
  "MEMORY",
926
821
  "1.0",
927
822
  "MySQL AB",
928
823
  "Hash based, stored in memory, useful for temporary tables",
929
824
  PLUGIN_LICENSE_GPL,
930
825
  heap_init,
 
826
  heap_deinit,
 
827
  NULL,                       /* status variables                */
931
828
  NULL,                       /* system variables                */
932
829
  NULL                        /* config options                  */
933
830
}
934
 
DRIZZLE_DECLARE_PLUGIN_END;
 
831
mysql_declare_plugin_end;