~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/heap/ha_heap.cc

  • Committer: Brian Aker
  • Date: 2008-07-07 14:25:25 UTC
  • mto: (77.1.25 codestyle)
  • mto: This revision was merged to the branch mainline in revision 82.
  • Revision ID: brian@tangent.org-20080707142525-xzy2nl3ie2ebwfln
LL() cleanup

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
 
#define DRIZZLE_SERVER 1
17
 
#include <drizzled/server_includes.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>
18
24
#include "ha_heap.h"
19
25
#include "heapdef.h"
20
26
 
22
28
                                    TABLE_SHARE *table, 
23
29
                                    MEM_ROOT *mem_root);
24
30
 
25
 
int heap_deinit(void *p __attribute__((unused)))
26
 
            
 
31
int heap_panic(handlerton *hton, ha_panic_function flag)
27
32
{
28
 
  return hp_panic(HA_PANIC_CLOSE);
 
33
  return hp_panic(flag);
29
34
}
30
35
 
31
36
 
35
40
 
36
41
  heap_hton= (handlerton *)p;
37
42
  heap_hton->state=      SHOW_OPTION_YES;
 
43
  heap_hton->db_type=    DB_TYPE_HEAP;
38
44
  heap_hton->create=     heap_create_handler;
 
45
  heap_hton->panic=      heap_panic;
39
46
  heap_hton->flags=      HTON_CAN_RECREATE;
40
47
 
41
48
  return 0;
60
67
 
61
68
 
62
69
static const char *ha_heap_exts[] = {
63
 
  NULL
 
70
  NullS
64
71
};
65
72
 
66
73
const char **ha_heap::bas_ext() const
81
88
*/
82
89
#define HEAP_STATS_UPDATE_THRESHOLD 10
83
90
 
84
 
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)
85
92
{
86
93
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
87
94
  {
88
95
    HA_CREATE_INFO create_info;
89
96
    internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
90
 
    memset(&create_info, 0, sizeof(create_info));
 
97
    bzero(&create_info, sizeof(create_info));
91
98
    file= 0;
92
99
    if (!create(name, table, &create_info))
93
100
    {
167
174
void ha_heap::set_keys_for_scanning(void)
168
175
{
169
176
  btree_keys.clear_all();
170
 
  for (uint32_t i= 0 ; i < table->s->keys ; i++)
 
177
  for (uint i= 0 ; i < table->s->keys ; i++)
171
178
  {
172
179
    if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
173
180
      btree_keys.set_bit(i);
177
184
 
178
185
void ha_heap::update_key_stats()
179
186
{
180
 
  for (uint32_t i= 0; i < table->s->keys; i++)
 
187
  for (uint i= 0; i < table->s->keys; i++)
181
188
  {
182
189
    KEY *key=table->key_info+i;
183
190
    if (!key->rec_per_key)
189
196
      else
190
197
      {
191
198
        ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
192
 
        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;
193
200
        if (no_records < 2)
194
201
          no_records= 2;
195
202
        key->rec_per_key[key->key_parts-1]= no_records;
202
209
}
203
210
 
204
211
 
205
 
int ha_heap::write_row(unsigned char * buf)
 
212
int ha_heap::write_row(uchar * buf)
206
213
{
207
214
  int res;
208
215
  ha_statistic_increment(&SSV::ha_write_count);
226
233
  return res;
227
234
}
228
235
 
229
 
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)
230
237
{
231
238
  int res;
232
239
  ha_statistic_increment(&SSV::ha_update_count);
245
252
  return res;
246
253
}
247
254
 
248
 
int ha_heap::delete_row(const unsigned char * buf)
 
255
int ha_heap::delete_row(const uchar * buf)
249
256
{
250
257
  int res;
251
258
  ha_statistic_increment(&SSV::ha_delete_count);
262
269
  return res;
263
270
}
264
271
 
265
 
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,
266
273
                            key_part_map keypart_map,
267
274
                            enum ha_rkey_function find_flag)
268
275
{
269
 
  assert(inited==INDEX);
 
276
  DBUG_ASSERT(inited==INDEX);
270
277
  ha_statistic_increment(&SSV::ha_read_key_count);
271
278
  int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
272
279
  table->status = error ? STATUS_NOT_FOUND : 0;
273
280
  return error;
274
281
}
275
282
 
276
 
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,
277
284
                                 key_part_map keypart_map)
278
285
{
279
 
  assert(inited==INDEX);
 
286
  DBUG_ASSERT(inited==INDEX);
280
287
  ha_statistic_increment(&SSV::ha_read_key_count);
281
288
  int error= heap_rkey(file, buf, active_index, key, keypart_map,
282
289
                       HA_READ_PREFIX_LAST);
284
291
  return error;
285
292
}
286
293
 
287
 
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,
288
295
                                key_part_map keypart_map,
289
296
                                enum ha_rkey_function find_flag)
290
297
{
294
301
  return error;
295
302
}
296
303
 
297
 
int ha_heap::index_next(unsigned char * buf)
 
304
int ha_heap::index_next(uchar * buf)
298
305
{
299
 
  assert(inited==INDEX);
 
306
  DBUG_ASSERT(inited==INDEX);
300
307
  ha_statistic_increment(&SSV::ha_read_next_count);
301
308
  int error=heap_rnext(file,buf);
302
309
  table->status=error ? STATUS_NOT_FOUND: 0;
303
310
  return error;
304
311
}
305
312
 
306
 
int ha_heap::index_prev(unsigned char * buf)
 
313
int ha_heap::index_prev(uchar * buf)
307
314
{
308
 
  assert(inited==INDEX);
 
315
  DBUG_ASSERT(inited==INDEX);
309
316
  ha_statistic_increment(&SSV::ha_read_prev_count);
310
317
  int error=heap_rprev(file,buf);
311
318
  table->status=error ? STATUS_NOT_FOUND: 0;
312
319
  return error;
313
320
}
314
321
 
315
 
int ha_heap::index_first(unsigned char * buf)
 
322
int ha_heap::index_first(uchar * buf)
316
323
{
317
 
  assert(inited==INDEX);
 
324
  DBUG_ASSERT(inited==INDEX);
318
325
  ha_statistic_increment(&SSV::ha_read_first_count);
319
326
  int error=heap_rfirst(file, buf, active_index);
320
327
  table->status=error ? STATUS_NOT_FOUND: 0;
321
328
  return error;
322
329
}
323
330
 
324
 
int ha_heap::index_last(unsigned char * buf)
 
331
int ha_heap::index_last(uchar * buf)
325
332
{
326
 
  assert(inited==INDEX);
 
333
  DBUG_ASSERT(inited==INDEX);
327
334
  ha_statistic_increment(&SSV::ha_read_last_count);
328
335
  int error=heap_rlast(file, buf, active_index);
329
336
  table->status=error ? STATUS_NOT_FOUND: 0;
335
342
  return scan ? heap_scan_init(file) : 0;
336
343
}
337
344
 
338
 
int ha_heap::rnd_next(unsigned char *buf)
 
345
int ha_heap::rnd_next(uchar *buf)
339
346
{
340
347
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
341
348
  int error=heap_scan(file, buf);
343
350
  return error;
344
351
}
345
352
 
346
 
int ha_heap::rnd_pos(unsigned char * buf, unsigned char *pos)
 
353
int ha_heap::rnd_pos(uchar * buf, uchar *pos)
347
354
{
348
355
  int error;
349
356
  HEAP_PTR heap_position;
350
357
  ha_statistic_increment(&SSV::ha_read_rnd_count);
351
 
  memcpy(&heap_position, pos, sizeof(HEAP_PTR));
 
358
  memcpy_fixed((char*) &heap_position, pos, sizeof(HEAP_PTR));
352
359
  error=heap_rrnd(file, buf, heap_position);
353
360
  table->status=error ? STATUS_NOT_FOUND: 0;
354
361
  return error;
355
362
}
356
363
 
357
 
void ha_heap::position(const unsigned char *record __attribute__((unused)))
 
364
void ha_heap::position(const uchar *record)
358
365
{
359
366
  *(HEAP_PTR*) ref= heap_position(file);        // Ref is aligned
360
367
}
361
368
 
362
 
int ha_heap::info(uint32_t flag)
 
369
int ha_heap::info(uint flag)
363
370
{
364
371
  HEAPINFO hp_info;
365
372
  (void) heap_info(file,&hp_info,flag);
385
392
}
386
393
 
387
394
 
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
 
 
396
395
int ha_heap::extra(enum ha_extra_function operation)
397
396
{
398
397
  return heap_extra(file,operation);
419
418
  return 0;
420
419
}
421
420
 
422
 
int ha_heap::external_lock(THD *thd __attribute__((unused)),
423
 
                           int lock_type __attribute__((unused)))
 
421
int ha_heap::external_lock(THD *thd, int lock_type)
424
422
{
425
423
  return 0;                                     // No external locking
426
424
}
450
448
    HA_ERR_WRONG_COMMAND  mode not implemented.
451
449
*/
452
450
 
453
 
int ha_heap::disable_indexes(uint32_t mode)
 
451
int ha_heap::disable_indexes(uint mode)
454
452
{
455
453
  int error;
456
454
 
497
495
    HA_ERR_WRONG_COMMAND  mode not implemented.
498
496
*/
499
497
 
500
 
int ha_heap::enable_indexes(uint32_t mode)
 
498
int ha_heap::enable_indexes(uint mode)
501
499
{
502
500
  int error;
503
501
 
533
531
  return heap_indexes_are_disabled(file);
534
532
}
535
533
 
536
 
THR_LOCK_DATA **ha_heap::store_lock(THD *thd __attribute__((unused)),
537
 
                                    THR_LOCK_DATA **to,
538
 
                                    enum thr_lock_type lock_type)
 
534
THR_LOCK_DATA **ha_heap::store_lock(THD *thd,
 
535
                                    THR_LOCK_DATA **to,
 
536
                                    enum thr_lock_type lock_type)
539
537
{
540
538
  if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
541
539
    file->lock.type=lock_type;
555
553
}
556
554
 
557
555
 
558
 
void ha_heap::drop_table(const char *name __attribute__((unused)))
 
556
void ha_heap::drop_table(const char *name)
559
557
{
560
558
  file->s->delete_on_close= 1;
561
559
  close();
568
566
}
569
567
 
570
568
 
571
 
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,
572
570
                                  key_range *max_key)
573
571
{
574
572
  KEY *key=table->key_info+inx;
586
584
    return stats.records;
587
585
 
588
586
  /* Assert that info() did run. We need current statistics here. */
589
 
  assert(key_stat_version == file->s->key_stat_version);
 
587
  DBUG_ASSERT(key_stat_version == file->s->key_stat_version);
590
588
  return key->rec_per_key[key->key_parts-1];
591
589
}
592
590
 
593
591
 
594
 
int ha_heap::create(const char *name, Table *table_arg,
 
592
int ha_heap::create(const char *name, TABLE *table_arg,
595
593
                    HA_CREATE_INFO *create_info)
596
594
{
597
 
  uint32_t key, parts, mem_per_row_keys= 0, keys= table_arg->s->keys;
598
 
  uint32_t auto_key= 0, auto_key_type= 0;
599
 
  uint32_t max_key_fieldnr = 0, key_part_size = 0, next_field_pos = 0;
600
 
  uint32_t column_idx, column_count= table_arg->s->fields;
601
 
  HP_COLUMNDEF *columndef;
 
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;
602
598
  HP_KEYDEF *keydef;
603
599
  HA_KEYSEG *seg;
604
 
  char buff[FN_REFLEN];
605
600
  int error;
606
601
  TABLE_SHARE *share= table_arg->s;
607
602
  bool found_real_auto_increment= 0;
608
603
 
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 - (unsigned char*) 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
 
  }
640
 
 
641
604
  for (key= parts= 0; key < keys; key++)
642
605
    parts+= table_arg->key_info[key].key_parts;
643
606
 
644
607
  if (!(keydef= (HP_KEYDEF*) my_malloc(keys * sizeof(HP_KEYDEF) +
645
608
                                       parts * sizeof(HA_KEYSEG),
646
609
                                       MYF(MY_WME))))
647
 
  {
648
 
    free((void *) columndef);
649
610
    return my_errno;
650
 
  }
651
 
 
652
 
  seg= reinterpret_cast<HA_KEYSEG*> (keydef + keys);
 
611
  seg= my_reinterpret_cast(HA_KEYSEG*) (keydef + keys);
653
612
  for (key= 0; key < keys; key++)
654
613
  {
655
614
    KEY *pos= table_arg->key_info+key;
664
623
    case HA_KEY_ALG_UNDEF:
665
624
    case HA_KEY_ALG_HASH:
666
625
      keydef[key].algorithm= HA_KEY_ALG_HASH;
667
 
      mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
 
626
      mem_per_row+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
668
627
      break;
669
628
    case HA_KEY_ALG_BTREE:
670
629
      keydef[key].algorithm= HA_KEY_ALG_BTREE;
671
 
      mem_per_row_keys+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
 
630
      mem_per_row+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
672
631
      break;
673
632
    default:
674
 
      assert(0); // cannot happen
 
633
      DBUG_ASSERT(0); // cannot happen
675
634
    }
676
635
 
677
636
    for (; key_part != key_part_end; key_part++, seg++)
693
652
      seg->length=  (uint) key_part->length;
694
653
      seg->flag=    key_part->key_part_flag;
695
654
 
696
 
      next_field_pos= seg->start + seg->length;
697
 
      if (field->type() == DRIZZLE_TYPE_VARCHAR)
698
 
      {
699
 
        next_field_pos+= (uint8_t)(((Field_varstring*)field)->length_bytes);
700
 
      }
701
 
 
702
 
      if (next_field_pos > key_part_size) {
703
 
        key_part_size= next_field_pos;
704
 
      }
705
 
 
706
655
      if (field->flags & (ENUM_FLAG | SET_FLAG))
707
656
        seg->charset= &my_charset_bin;
708
657
      else
710
659
      if (field->null_ptr)
711
660
      {
712
661
        seg->null_bit= field->null_bit;
713
 
        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]);
714
663
      }
715
664
      else
716
665
      {
728
677
        auto_key= key+ 1;
729
678
        auto_key_type= field->key_type();
730
679
      }
731
 
      if ((uint)field->field_index + 1 > max_key_fieldnr)
732
 
      {
733
 
        /* Do not use seg->fieldnr as it's not reliable in case of temp tables */
734
 
        max_key_fieldnr= field->field_index + 1;
735
 
      }
736
680
    }
737
681
  }
738
 
  
739
 
  if (key_part_size < share->null_bytes + ((share->last_null_bit_pos+7) >> 3))
740
 
  {
741
 
    /* Make sure to include null fields regardless of the presense of keys */
742
 
    key_part_size = share->null_bytes + ((share->last_null_bit_pos+7) >> 3);
743
 
  }
744
 
 
745
 
  
746
 
  
 
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);
747
685
  if (table_arg->found_next_number_field)
748
686
  {
749
687
    keydef[share->next_number_index].flag|= HA_AUTO_KEY;
757
695
  hp_create_info.max_table_size=current_thd->variables.max_heap_table_size;
758
696
  hp_create_info.with_auto_increment= found_real_auto_increment;
759
697
  hp_create_info.internal_table= internal_table;
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
 
  free((unsigned char*) keydef);
772
 
  free((void *) columndef);
773
 
  assert(file == 0);
 
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);
774
707
  return (error);
775
708
}
776
709
 
780
713
  table->file->info(HA_STATUS_AUTO);
781
714
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
782
715
    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
716
}
791
717
 
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)),
 
718
void ha_heap::get_auto_increment(uint64_t offset, uint64_t increment,
 
719
                                 uint64_t nb_desired_values,
795
720
                                 uint64_t *first_value,
796
721
                                 uint64_t *nb_reserved_values)
797
722
{
798
723
  ha_heap::info(HA_STATUS_AUTO);
799
724
  *first_value= stats.auto_increment_value;
800
725
  /* such table has only table-level locking so reserves up to +inf */
801
 
  *nb_reserved_values= UINT64_MAX;
 
726
  *nb_reserved_values= ULONGLONG_MAX;
802
727
}
803
728
 
804
729
 
805
730
bool ha_heap::check_if_incompatible_data(HA_CREATE_INFO *info,
806
 
                                         uint32_t table_changes)
 
731
                                         uint table_changes)
807
732
{
808
733
  /* Check that auto_increment value was not changed */
809
734
  if ((info->used_fields & HA_CREATE_USED_AUTO &&
814
739
  return COMPATIBLE_DATA_YES;
815
740
}
816
741
 
 
742
struct st_mysql_storage_engine heap_storage_engine=
 
743
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
 
744
 
817
745
mysql_declare_plugin(heap)
818
746
{
819
 
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
 
747
  MYSQL_STORAGE_ENGINE_PLUGIN,
 
748
  &heap_storage_engine,
820
749
  "MEMORY",
821
 
  "1.0",
822
750
  "MySQL AB",
823
751
  "Hash based, stored in memory, useful for temporary tables",
824
752
  PLUGIN_LICENSE_GPL,
825
753
  heap_init,
826
 
  heap_deinit,
 
754
  NULL,
 
755
  0x0100, /* 1.0 */
827
756
  NULL,                       /* status variables                */
828
757
  NULL,                       /* system variables                */
829
758
  NULL                        /* config options                  */