~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
13
   along with this program; if not, write to the Free Software
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
16
#define DRIZZLE_SERVER 1
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
17
#include <drizzled/server_includes.h>
1 by brian
clean slate
18
#include "ha_heap.h"
19
#include "heapdef.h"
549 by Monty Taylor
Took gettext.h out of header files.
20
#include <drizzled/error.h>
1 by brian
clean slate
21
22
static handler *heap_create_handler(handlerton *hton,
23
                                    TABLE_SHARE *table, 
24
                                    MEM_ROOT *mem_root);
25
224.2.3 by Brian Aker
Fix for memory leak in shutdown/restart of an engine (not fixed in 5.1)
26
int heap_deinit(void *p __attribute__((unused)))
27
            
1 by brian
clean slate
28
{
224.2.3 by Brian Aker
Fix for memory leak in shutdown/restart of an engine (not fixed in 5.1)
29
  return hp_panic(HA_PANIC_CLOSE);
1 by brian
clean slate
30
}
31
32
33
int heap_init(void *p)
34
{
35
  handlerton *heap_hton;
36
37
  heap_hton= (handlerton *)p;
38
  heap_hton->state=      SHOW_OPTION_YES;
39
  heap_hton->create=     heap_create_handler;
40
  heap_hton->flags=      HTON_CAN_RECREATE;
41
42
  return 0;
43
}
44
45
static handler *heap_create_handler(handlerton *hton,
46
                                    TABLE_SHARE *table, 
47
                                    MEM_ROOT *mem_root)
48
{
49
  return new (mem_root) ha_heap(hton, table);
50
}
51
52
53
/*****************************************************************************
54
** HEAP tables
55
*****************************************************************************/
56
57
ha_heap::ha_heap(handlerton *hton, TABLE_SHARE *table_arg)
58
  :handler(hton, table_arg), file(0), records_changed(0), key_stat_version(0), 
59
  internal_table(0)
60
{}
61
62
63
static const char *ha_heap_exts[] = {
461 by Monty Taylor
Removed NullS. bu-bye.
64
  NULL
1 by brian
clean slate
65
};
66
67
const char **ha_heap::bas_ext() const
68
{
69
  return ha_heap_exts;
70
}
71
72
/*
73
  Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to 
74
  rec_per_key) after 1/HEAP_STATS_UPDATE_THRESHOLD fraction of table records 
75
  have been inserted/updated/deleted. delete_all_rows() and table flush cause 
76
  immediate update.
77
78
  NOTE
79
   hash index statistics must be updated when number of table records changes
80
   from 0 to non-zero value and vice versa. Otherwise records_in_range may 
81
   erroneously return 0 and 'range' may miss records.
82
*/
83
#define HEAP_STATS_UPDATE_THRESHOLD 10
84
482 by Brian Aker
Remove uint.
85
int ha_heap::open(const char *name, int mode, uint32_t test_if_locked)
1 by brian
clean slate
86
{
87
  if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
88
  {
89
    HA_CREATE_INFO create_info;
90
    internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
91
    memset(&create_info, 0, sizeof(create_info));
1 by brian
clean slate
92
    file= 0;
93
    if (!create(name, table, &create_info))
94
    {
95
        file= internal_table ?
96
          heap_open_from_share(internal_share, mode) :
97
          heap_open_from_share_and_register(internal_share, mode);
98
      if (!file)
99
      {
100
         /* Couldn't open table; Remove the newly created table */
101
        pthread_mutex_lock(&THR_LOCK_heap);
102
        hp_free(internal_share);
103
        pthread_mutex_unlock(&THR_LOCK_heap);
104
      }
105
      implicit_emptied= 1;
106
    }
107
  }
108
  ref_length= sizeof(HEAP_PTR);
109
  if (file)
110
  {
111
    /* Initialize variables for the opened table */
112
    set_keys_for_scanning();
113
    /*
114
      We cannot run update_key_stats() here because we do not have a
115
      lock on the table. The 'records' count might just be changed
116
      temporarily at this moment and we might get wrong statistics (Bug
117
      #10178). Instead we request for update. This will be done in
118
      ha_heap::info(), which is always called before key statistics are
119
      used.
120
    */
121
    key_stat_version= file->s->key_stat_version-1;
122
  }
123
  return (file ? 0 : 1);
124
}
125
126
int ha_heap::close(void)
127
{
128
  return internal_table ? hp_close(file) : heap_close(file);
129
}
130
131
132
/*
133
  Create a copy of this table
134
135
  DESCRIPTION
136
    Do same as default implementation but use file->s->name instead of 
137
    table->s->path. This is needed by Windows where the clone() call sees
138
    '/'-delimited path in table->s->path, while ha_peap::open() was called 
139
    with '\'-delimited path.
140
*/
141
142
handler *ha_heap::clone(MEM_ROOT *mem_root)
143
{
144
  handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
145
  if (new_handler && !new_handler->ha_open(table, file->s->name, table->db_stat,
146
                                           HA_OPEN_IGNORE_IF_LOCKED))
147
    return new_handler;
148
  return NULL;  /* purecov: inspected */
149
}
150
151
152
/*
153
  Compute which keys to use for scanning
154
155
  SYNOPSIS
156
    set_keys_for_scanning()
157
    no parameter
158
159
  DESCRIPTION
160
    Set the bitmap btree_keys, which is used when the upper layers ask
161
    which keys to use for scanning. For each btree index the
162
    corresponding bit is set.
163
164
  RETURN
165
    void
166
*/
167
168
void ha_heap::set_keys_for_scanning(void)
169
{
170
  btree_keys.clear_all();
482 by Brian Aker
Remove uint.
171
  for (uint32_t i= 0 ; i < table->s->keys ; i++)
1 by brian
clean slate
172
  {
173
    if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
174
      btree_keys.set_bit(i);
175
  }
176
}
177
178
179
void ha_heap::update_key_stats()
180
{
482 by Brian Aker
Remove uint.
181
  for (uint32_t i= 0; i < table->s->keys; i++)
1 by brian
clean slate
182
  {
183
    KEY *key=table->key_info+i;
184
    if (!key->rec_per_key)
185
      continue;
186
    if (key->algorithm != HA_KEY_ALG_BTREE)
187
    {
188
      if (key->flags & HA_NOSAME)
189
        key->rec_per_key[key->key_parts-1]= 1;
190
      else
191
      {
192
        ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
482 by Brian Aker
Remove uint.
193
        uint32_t no_records= hash_buckets ? (uint) (file->s->records/hash_buckets) : 2;
1 by brian
clean slate
194
        if (no_records < 2)
195
          no_records= 2;
196
        key->rec_per_key[key->key_parts-1]= no_records;
197
      }
198
    }
199
  }
200
  records_changed= 0;
201
  /* At the end of update_key_stats() we can proudly claim they are OK. */
202
  key_stat_version= file->s->key_stat_version;
203
}
204
205
481 by Brian Aker
Remove all of uchar.
206
int ha_heap::write_row(unsigned char * buf)
1 by brian
clean slate
207
{
208
  int res;
209
  ha_statistic_increment(&SSV::ha_write_count);
210
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
211
    table->timestamp_field->set_time();
212
  if (table->next_number_field && buf == table->record[0])
213
  {
214
    if ((res= update_auto_increment()))
215
      return res;
216
  }
217
  res= heap_write(file,buf);
218
  if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD > 
219
               file->s->records))
220
  {
221
    /*
222
       We can perform this safely since only one writer at the time is
223
       allowed on the table.
224
    */
225
    file->s->key_stat_version++;
226
  }
227
  return res;
228
}
229
481 by Brian Aker
Remove all of uchar.
230
int ha_heap::update_row(const unsigned char * old_data, unsigned char * new_data)
1 by brian
clean slate
231
{
232
  int res;
233
  ha_statistic_increment(&SSV::ha_update_count);
234
  if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
235
    table->timestamp_field->set_time();
236
  res= heap_update(file,old_data,new_data);
237
  if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > 
238
              file->s->records)
239
  {
240
    /*
241
       We can perform this safely since only one writer at the time is
242
       allowed on the table.
243
    */
244
    file->s->key_stat_version++;
245
  }
246
  return res;
247
}
248
481 by Brian Aker
Remove all of uchar.
249
int ha_heap::delete_row(const unsigned char * buf)
1 by brian
clean slate
250
{
251
  int res;
252
  ha_statistic_increment(&SSV::ha_delete_count);
253
  res= heap_delete(file,buf);
254
  if (!res && table->s->tmp_table == NO_TMP_TABLE && 
255
      ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
256
  {
257
    /*
258
       We can perform this safely since only one writer at the time is
259
       allowed on the table.
260
    */
261
    file->s->key_stat_version++;
262
  }
263
  return res;
264
}
265
481 by Brian Aker
Remove all of uchar.
266
int ha_heap::index_read_map(unsigned char *buf, const unsigned char *key,
1 by brian
clean slate
267
                            key_part_map keypart_map,
268
                            enum ha_rkey_function find_flag)
269
{
51.3.1 by Jay Pipes
Removed all DBUG symbols from heap storage engine
270
  assert(inited==INDEX);
1 by brian
clean slate
271
  ha_statistic_increment(&SSV::ha_read_key_count);
272
  int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
273
  table->status = error ? STATUS_NOT_FOUND : 0;
274
  return error;
275
}
276
481 by Brian Aker
Remove all of uchar.
277
int ha_heap::index_read_last_map(unsigned char *buf, const unsigned char *key,
1 by brian
clean slate
278
                                 key_part_map keypart_map)
279
{
51.3.1 by Jay Pipes
Removed all DBUG symbols from heap storage engine
280
  assert(inited==INDEX);
1 by brian
clean slate
281
  ha_statistic_increment(&SSV::ha_read_key_count);
282
  int error= heap_rkey(file, buf, active_index, key, keypart_map,
283
		       HA_READ_PREFIX_LAST);
284
  table->status= error ? STATUS_NOT_FOUND : 0;
285
  return error;
286
}
287
482 by Brian Aker
Remove uint.
288
int ha_heap::index_read_idx_map(unsigned char *buf, uint32_t index, const unsigned char *key,
1 by brian
clean slate
289
                                key_part_map keypart_map,
290
                                enum ha_rkey_function find_flag)
291
{
292
  ha_statistic_increment(&SSV::ha_read_key_count);
293
  int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
294
  table->status = error ? STATUS_NOT_FOUND : 0;
295
  return error;
296
}
297
481 by Brian Aker
Remove all of uchar.
298
int ha_heap::index_next(unsigned char * buf)
1 by brian
clean slate
299
{
51.3.1 by Jay Pipes
Removed all DBUG symbols from heap storage engine
300
  assert(inited==INDEX);
1 by brian
clean slate
301
  ha_statistic_increment(&SSV::ha_read_next_count);
302
  int error=heap_rnext(file,buf);
303
  table->status=error ? STATUS_NOT_FOUND: 0;
304
  return error;
305
}
306
481 by Brian Aker
Remove all of uchar.
307
int ha_heap::index_prev(unsigned char * buf)
1 by brian
clean slate
308
{
51.3.1 by Jay Pipes
Removed all DBUG symbols from heap storage engine
309
  assert(inited==INDEX);
1 by brian
clean slate
310
  ha_statistic_increment(&SSV::ha_read_prev_count);
311
  int error=heap_rprev(file,buf);
312
  table->status=error ? STATUS_NOT_FOUND: 0;
313
  return error;
314
}
315
481 by Brian Aker
Remove all of uchar.
316
int ha_heap::index_first(unsigned char * buf)
1 by brian
clean slate
317
{
51.3.1 by Jay Pipes
Removed all DBUG symbols from heap storage engine
318
  assert(inited==INDEX);
1 by brian
clean slate
319
  ha_statistic_increment(&SSV::ha_read_first_count);
320
  int error=heap_rfirst(file, buf, active_index);
321
  table->status=error ? STATUS_NOT_FOUND: 0;
322
  return error;
323
}
324
481 by Brian Aker
Remove all of uchar.
325
int ha_heap::index_last(unsigned char * buf)
1 by brian
clean slate
326
{
51.3.1 by Jay Pipes
Removed all DBUG symbols from heap storage engine
327
  assert(inited==INDEX);
1 by brian
clean slate
328
  ha_statistic_increment(&SSV::ha_read_last_count);
329
  int error=heap_rlast(file, buf, active_index);
330
  table->status=error ? STATUS_NOT_FOUND: 0;
331
  return error;
332
}
333
334
int ha_heap::rnd_init(bool scan)
335
{
336
  return scan ? heap_scan_init(file) : 0;
337
}
338
481 by Brian Aker
Remove all of uchar.
339
int ha_heap::rnd_next(unsigned char *buf)
1 by brian
clean slate
340
{
341
  ha_statistic_increment(&SSV::ha_read_rnd_next_count);
342
  int error=heap_scan(file, buf);
343
  table->status=error ? STATUS_NOT_FOUND: 0;
344
  return error;
345
}
346
481 by Brian Aker
Remove all of uchar.
347
int ha_heap::rnd_pos(unsigned char * buf, unsigned char *pos)
1 by brian
clean slate
348
{
349
  int error;
350
  HEAP_PTR heap_position;
351
  ha_statistic_increment(&SSV::ha_read_rnd_count);
212.6.8 by Mats Kindahl
Removing extreneous explicit casts for the heap storage engine.
352
  memcpy(&heap_position, pos, sizeof(HEAP_PTR));
1 by brian
clean slate
353
  error=heap_rrnd(file, buf, heap_position);
354
  table->status=error ? STATUS_NOT_FOUND: 0;
355
  return error;
356
}
357
481 by Brian Aker
Remove all of uchar.
358
void ha_heap::position(const unsigned char *record __attribute__((unused)))
1 by brian
clean slate
359
{
360
  *(HEAP_PTR*) ref= heap_position(file);	// Ref is aligned
361
}
362
482 by Brian Aker
Remove uint.
363
int ha_heap::info(uint32_t flag)
1 by brian
clean slate
364
{
365
  HEAPINFO hp_info;
366
  (void) heap_info(file,&hp_info,flag);
367
368
  errkey=                     hp_info.errkey;
369
  stats.records=              hp_info.records;
370
  stats.deleted=              hp_info.deleted;
371
  stats.mean_rec_length=      hp_info.reclength;
372
  stats.data_file_length=     hp_info.data_length;
373
  stats.index_file_length=    hp_info.index_length;
374
  stats.max_data_file_length= hp_info.max_records * hp_info.reclength;
375
  stats.delete_length=        hp_info.deleted * hp_info.reclength;
376
  if (flag & HA_STATUS_AUTO)
377
    stats.auto_increment_value= hp_info.auto_increment;
378
  /*
379
    If info() is called for the first time after open(), we will still
380
    have to update the key statistics. Hoping that a table lock is now
381
    in place.
382
  */
383
  if (key_stat_version != file->s->key_stat_version)
384
    update_key_stats();
385
  return 0;
386
}
387
388
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
389
enum row_type ha_heap::get_row_type() const
390
{
391
  if (file->s->recordspace.is_variable_size)
392
    return ROW_TYPE_DYNAMIC;
393
394
  return ROW_TYPE_FIXED;
395
}
396
1 by brian
clean slate
397
int ha_heap::extra(enum ha_extra_function operation)
398
{
399
  return heap_extra(file,operation);
400
}
401
402
403
int ha_heap::reset()
404
{
405
  return heap_reset(file);
406
}
407
408
409
int ha_heap::delete_all_rows()
410
{
411
  heap_clear(file);
412
  if (table->s->tmp_table == NO_TMP_TABLE)
413
  {
414
    /*
415
       We can perform this safely since only one writer at the time is
416
       allowed on the table.
417
    */
418
    file->s->key_stat_version++;
419
  }
420
  return 0;
421
}
422
520.1.22 by Brian Aker
Second pass of thd cleanup
423
int ha_heap::external_lock(Session *session __attribute__((unused)),
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
424
                           int lock_type __attribute__((unused)))
1 by brian
clean slate
425
{
426
  return 0;					// No external locking
427
}
428
429
430
/*
431
  Disable indexes.
432
433
  SYNOPSIS
434
    disable_indexes()
435
    mode        mode of operation:
436
                HA_KEY_SWITCH_NONUNIQ      disable all non-unique keys
437
                HA_KEY_SWITCH_ALL          disable all keys
438
                HA_KEY_SWITCH_NONUNIQ_SAVE dis. non-uni. and make persistent
439
                HA_KEY_SWITCH_ALL_SAVE     dis. all keys and make persistent
440
441
  DESCRIPTION
442
    Disable indexes and clear keys to use for scanning.
443
444
  IMPLEMENTATION
445
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
446
    HA_KEY_SWITCH_NONUNIQ_SAVE  is not implemented with HEAP.
447
    HA_KEY_SWITCH_ALL_SAVE      is not implemented with HEAP.
448
449
  RETURN
450
    0  ok
451
    HA_ERR_WRONG_COMMAND  mode not implemented.
452
*/
453
482 by Brian Aker
Remove uint.
454
int ha_heap::disable_indexes(uint32_t mode)
1 by brian
clean slate
455
{
456
  int error;
457
458
  if (mode == HA_KEY_SWITCH_ALL)
459
  {
460
    if (!(error= heap_disable_indexes(file)))
461
      set_keys_for_scanning();
462
  }
463
  else
464
  {
465
    /* mode not implemented */
466
    error= HA_ERR_WRONG_COMMAND;
467
  }
468
  return error;
469
}
470
471
472
/*
473
  Enable indexes.
474
475
  SYNOPSIS
476
    enable_indexes()
477
    mode        mode of operation:
478
                HA_KEY_SWITCH_NONUNIQ      enable all non-unique keys
479
                HA_KEY_SWITCH_ALL          enable all keys
480
                HA_KEY_SWITCH_NONUNIQ_SAVE en. non-uni. and make persistent
481
                HA_KEY_SWITCH_ALL_SAVE     en. all keys and make persistent
482
483
  DESCRIPTION
484
    Enable indexes and set keys to use for scanning.
485
    The indexes might have been disabled by disable_index() before.
486
    The function works only if both data and indexes are empty,
487
    since the heap storage engine cannot repair the indexes.
488
    To be sure, call handler::delete_all_rows() before.
489
490
  IMPLEMENTATION
491
    HA_KEY_SWITCH_NONUNIQ       is not implemented.
492
    HA_KEY_SWITCH_NONUNIQ_SAVE  is not implemented with HEAP.
493
    HA_KEY_SWITCH_ALL_SAVE      is not implemented with HEAP.
494
495
  RETURN
496
    0  ok
497
    HA_ERR_CRASHED  data or index is non-empty. Delete all rows and retry.
498
    HA_ERR_WRONG_COMMAND  mode not implemented.
499
*/
500
482 by Brian Aker
Remove uint.
501
int ha_heap::enable_indexes(uint32_t mode)
1 by brian
clean slate
502
{
503
  int error;
504
505
  if (mode == HA_KEY_SWITCH_ALL)
506
  {
507
    if (!(error= heap_enable_indexes(file)))
508
      set_keys_for_scanning();
509
  }
510
  else
511
  {
512
    /* mode not implemented */
513
    error= HA_ERR_WRONG_COMMAND;
514
  }
515
  return error;
516
}
517
518
519
/*
520
  Test if indexes are disabled.
521
522
  SYNOPSIS
523
    indexes_are_disabled()
524
    no parameters
525
526
  RETURN
527
    0  indexes are not disabled
528
    1  all indexes are disabled
529
   [2  non-unique indexes are disabled - NOT YET IMPLEMENTED]
530
*/
531
532
int ha_heap::indexes_are_disabled(void)
533
{
534
  return heap_indexes_are_disabled(file);
535
}
536
520.1.22 by Brian Aker
Second pass of thd cleanup
537
THR_LOCK_DATA **ha_heap::store_lock(Session *session __attribute__((unused)),
77.1.7 by Monty Taylor
Heap builds clean.
538
                                    THR_LOCK_DATA **to,
539
                                    enum thr_lock_type lock_type)
1 by brian
clean slate
540
{
541
  if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
542
    file->lock.type=lock_type;
543
  *to++= &file->lock;
544
  return to;
545
}
546
547
/*
548
  We have to ignore ENOENT entries as the HEAP table is created on open and
549
  not when doing a CREATE on the table.
550
*/
551
552
int ha_heap::delete_table(const char *name)
553
{
554
  int error= heap_delete_table(name);
555
  return error == ENOENT ? 0 : error;
556
}
557
558
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
559
void ha_heap::drop_table(const char *name __attribute__((unused)))
1 by brian
clean slate
560
{
561
  file->s->delete_on_close= 1;
562
  close();
563
}
564
565
566
int ha_heap::rename_table(const char * from, const char * to)
567
{
568
  return heap_rename(from,to);
569
}
570
571
482 by Brian Aker
Remove uint.
572
ha_rows ha_heap::records_in_range(uint32_t inx, key_range *min_key,
1 by brian
clean slate
573
                                  key_range *max_key)
574
{
575
  KEY *key=table->key_info+inx;
576
  if (key->algorithm == HA_KEY_ALG_BTREE)
577
    return hp_rb_records_in_range(file, inx, min_key, max_key);
578
579
  if (!min_key || !max_key ||
580
      min_key->length != max_key->length ||
581
      min_key->length != key->key_length ||
582
      min_key->flag != HA_READ_KEY_EXACT ||
583
      max_key->flag != HA_READ_AFTER_KEY)
584
    return HA_POS_ERROR;			// Can only use exact keys
585
586
  if (stats.records <= 1)
587
    return stats.records;
588
589
  /* Assert that info() did run. We need current statistics here. */
51.3.1 by Jay Pipes
Removed all DBUG symbols from heap storage engine
590
  assert(key_stat_version == file->s->key_stat_version);
1 by brian
clean slate
591
  return key->rec_per_key[key->key_parts-1];
592
}
593
594
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
595
int ha_heap::create(const char *name, Table *table_arg,
1 by brian
clean slate
596
		    HA_CREATE_INFO *create_info)
597
{
482 by Brian Aker
Remove uint.
598
  uint32_t key, parts, mem_per_row_keys= 0, keys= table_arg->s->keys;
599
  uint32_t auto_key= 0, auto_key_type= 0;
600
  uint32_t max_key_fieldnr = 0, key_part_size = 0, next_field_pos = 0;
601
  uint32_t column_idx, column_count= table_arg->s->fields;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
602
  HP_COLUMNDEF *columndef;
1 by brian
clean slate
603
  HP_KEYDEF *keydef;
604
  HA_KEYSEG *seg;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
605
  char buff[FN_REFLEN];
1 by brian
clean slate
606
  int error;
607
  TABLE_SHARE *share= table_arg->s;
608
  bool found_real_auto_increment= 0;
609
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
610
  if (!(columndef= (HP_COLUMNDEF*) my_malloc(column_count * sizeof(HP_COLUMNDEF), MYF(MY_WME))))
611
    return my_errno;
612
613
  for (column_idx= 0; column_idx < column_count; column_idx++)
614
  {
615
    Field* field= *(table_arg->field + column_idx);
616
    HP_COLUMNDEF* column= columndef + column_idx;
617
    column->type= (uint16_t)field->type();
618
    column->length= field->pack_length();
619
    column->offset= field->offset(field->table->record[0]);
620
621
    if (field->null_bit)
622
    {
623
      column->null_bit= field->null_bit;
481 by Brian Aker
Remove all of uchar.
624
      column->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->record[0]);
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
625
    }
626
    else
627
    {
628
      column->null_bit= 0;
629
      column->null_pos= 0;
630
    }
631
632
    if (field->type() == DRIZZLE_TYPE_VARCHAR)
633
    {
634
      column->length_bytes= (uint8_t)(((Field_varstring*)field)->length_bytes);
635
    }
636
    else
637
    {
638
      column->length_bytes= 0;
639
    }
640
  }
641
1 by brian
clean slate
642
  for (key= parts= 0; key < keys; key++)
643
    parts+= table_arg->key_info[key].key_parts;
644
645
  if (!(keydef= (HP_KEYDEF*) my_malloc(keys * sizeof(HP_KEYDEF) +
646
				       parts * sizeof(HA_KEYSEG),
647
				       MYF(MY_WME))))
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
648
  {
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
649
    free((void *) columndef);
1 by brian
clean slate
650
    return my_errno;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
651
  }
652
451 by Monty Taylor
Removed my_reinterpret_cast. It's not GNU specific.
653
  seg= reinterpret_cast<HA_KEYSEG*> (keydef + keys);
1 by brian
clean slate
654
  for (key= 0; key < keys; key++)
655
  {
656
    KEY *pos= table_arg->key_info+key;
657
    KEY_PART_INFO *key_part=     pos->key_part;
658
    KEY_PART_INFO *key_part_end= key_part + pos->key_parts;
659
660
    keydef[key].keysegs=   (uint) pos->key_parts;
661
    keydef[key].flag=      (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
662
    keydef[key].seg=       seg;
663
664
    switch (pos->algorithm) {
665
    case HA_KEY_ALG_UNDEF:
666
    case HA_KEY_ALG_HASH:
667
      keydef[key].algorithm= HA_KEY_ALG_HASH;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
668
      mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
1 by brian
clean slate
669
      break;
670
    case HA_KEY_ALG_BTREE:
671
      keydef[key].algorithm= HA_KEY_ALG_BTREE;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
672
      mem_per_row_keys+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
1 by brian
clean slate
673
      break;
674
    default:
51.3.1 by Jay Pipes
Removed all DBUG symbols from heap storage engine
675
      assert(0); // cannot happen
1 by brian
clean slate
676
    }
677
678
    for (; key_part != key_part_end; key_part++, seg++)
679
    {
680
      Field *field= key_part->field;
681
682
      if (pos->algorithm == HA_KEY_ALG_BTREE)
683
	seg->type= field->key_type();
684
      else
685
      {
686
        if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
687
            seg->type != HA_KEYTYPE_VARTEXT1 &&
688
            seg->type != HA_KEYTYPE_VARTEXT2 &&
689
            seg->type != HA_KEYTYPE_VARBINARY1 &&
690
            seg->type != HA_KEYTYPE_VARBINARY2)
691
          seg->type= HA_KEYTYPE_BINARY;
692
      }
693
      seg->start=   (uint) key_part->offset;
694
      seg->length=  (uint) key_part->length;
695
      seg->flag=    key_part->key_part_flag;
696
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
697
      next_field_pos= seg->start + seg->length;
698
      if (field->type() == DRIZZLE_TYPE_VARCHAR)
699
      {
700
        next_field_pos+= (uint8_t)(((Field_varstring*)field)->length_bytes);
701
      }
702
703
      if (next_field_pos > key_part_size) {
704
        key_part_size= next_field_pos;
705
      }
706
1 by brian
clean slate
707
      if (field->flags & (ENUM_FLAG | SET_FLAG))
708
        seg->charset= &my_charset_bin;
709
      else
710
        seg->charset= field->charset();
711
      if (field->null_ptr)
712
      {
713
	seg->null_bit= field->null_bit;
481 by Brian Aker
Remove all of uchar.
714
	seg->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->record[0]);
1 by brian
clean slate
715
      }
716
      else
717
      {
718
	seg->null_bit= 0;
719
	seg->null_pos= 0;
720
      }
721
      if (field->flags & AUTO_INCREMENT_FLAG &&
722
          table_arg->found_next_number_field &&
723
          key == share->next_number_index)
724
      {
725
        /*
726
          Store key number and type for found auto_increment key
727
          We have to store type as seg->type can differ from it
728
        */
729
        auto_key= key+ 1;
730
	auto_key_type= field->key_type();
731
      }
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
732
      if ((uint)field->field_index + 1 > max_key_fieldnr)
733
      {
734
        /* Do not use seg->fieldnr as it's not reliable in case of temp tables */
735
        max_key_fieldnr= field->field_index + 1;
736
      }
1 by brian
clean slate
737
    }
738
  }
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
739
  
740
  if (key_part_size < share->null_bytes + ((share->last_null_bit_pos+7) >> 3))
741
  {
742
    /* Make sure to include null fields regardless of the presense of keys */
743
    key_part_size = share->null_bytes + ((share->last_null_bit_pos+7) >> 3);
744
  }
745
746
  
747
  
1 by brian
clean slate
748
  if (table_arg->found_next_number_field)
749
  {
750
    keydef[share->next_number_index].flag|= HA_AUTO_KEY;
751
    found_real_auto_increment= share->next_number_key_offset == 0;
752
  }
753
  HP_CREATE_INFO hp_create_info;
754
  hp_create_info.auto_key= auto_key;
755
  hp_create_info.auto_key_type= auto_key_type;
756
  hp_create_info.auto_increment= (create_info->auto_increment_value ?
757
				  create_info->auto_increment_value - 1 : 0);
520.1.22 by Brian Aker
Second pass of thd cleanup
758
  hp_create_info.max_table_size=current_session->variables.max_heap_table_size;
1 by brian
clean slate
759
  hp_create_info.with_auto_increment= found_real_auto_increment;
760
  hp_create_info.internal_table= internal_table;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
761
  hp_create_info.max_chunk_size= share->block_size;
762
  hp_create_info.is_dynamic= (share->row_type == ROW_TYPE_DYNAMIC);
763
  error= heap_create(fn_format(buff,name,"","",
764
                               MY_REPLACE_EXT|MY_UNPACK_FILENAME),
765
                   keys, keydef,
766
         column_count, columndef,
767
         max_key_fieldnr, key_part_size,
768
         share->reclength, mem_per_row_keys,
291 by Brian Aker
Head ulong conversion.
769
         (uint32_t) share->max_rows, (uint32_t) share->min_rows,
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
770
         &hp_create_info, &internal_share);
771
  
481 by Brian Aker
Remove all of uchar.
772
  free((unsigned char*) keydef);
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
773
  free((void *) columndef);
51.3.1 by Jay Pipes
Removed all DBUG symbols from heap storage engine
774
  assert(file == 0);
1 by brian
clean slate
775
  return (error);
776
}
777
778
779
void ha_heap::update_create_info(HA_CREATE_INFO *create_info)
780
{
781
  table->file->info(HA_STATUS_AUTO);
782
  if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
783
    create_info->auto_increment_value= stats.auto_increment_value;
244.1.1 by Harrison Fisk
Port Ebay/Google memory storage engine variable width columns.
784
  if (!(create_info->used_fields & HA_CREATE_USED_BLOCK_SIZE))
785
  {
786
    if (file->s->recordspace.is_variable_size)
787
      create_info->block_size= file->s->recordspace.chunk_length;
788
    else
789
      create_info->block_size= 0;
790
  }
1 by brian
clean slate
791
}
792
212.1.3 by Monty Taylor
Renamed __attribute__((__unused__)) to __attribute__((unused)).
793
void ha_heap::get_auto_increment(uint64_t offset __attribute__((unused)),
794
                                 uint64_t increment __attribute__((unused)),
795
                                 uint64_t nb_desired_values __attribute__((unused)),
1 by brian
clean slate
796
                                 uint64_t *first_value,
797
                                 uint64_t *nb_reserved_values)
798
{
799
  ha_heap::info(HA_STATUS_AUTO);
800
  *first_value= stats.auto_increment_value;
801
  /* such table has only table-level locking so reserves up to +inf */
163 by Brian Aker
Merge Monty's code.
802
  *nb_reserved_values= UINT64_MAX;
1 by brian
clean slate
803
}
804
805
806
bool ha_heap::check_if_incompatible_data(HA_CREATE_INFO *info,
482 by Brian Aker
Remove uint.
807
					 uint32_t table_changes)
1 by brian
clean slate
808
{
809
  /* Check that auto_increment value was not changed */
810
  if ((info->used_fields & HA_CREATE_USED_AUTO &&
811
       info->auto_increment_value != 0) ||
812
      table_changes == IS_EQUAL_NO ||
813
      table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
814
    return COMPATIBLE_DATA_NO;
815
  return COMPATIBLE_DATA_YES;
816
}
817
818
mysql_declare_plugin(heap)
819
{
319.1.1 by Grant Limberg
renamed all instances of MYSQL_ to DRIZZLE_
820
  DRIZZLE_STORAGE_ENGINE_PLUGIN,
1 by brian
clean slate
821
  "MEMORY",
177.4.3 by mark
ripped out more plugin ABI and API version checking, and plugin versions are now strings
822
  "1.0",
1 by brian
clean slate
823
  "MySQL AB",
824
  "Hash based, stored in memory, useful for temporary tables",
825
  PLUGIN_LICENSE_GPL,
826
  heap_init,
224.2.3 by Brian Aker
Fix for memory leak in shutdown/restart of an engine (not fixed in 5.1)
827
  heap_deinit,
1 by brian
clean slate
828
  NULL,                       /* status variables                */
829
  NULL,                       /* system variables                */
830
  NULL                        /* config options                  */
831
}
832
mysql_declare_plugin_end;