1 /*
2 Copyright (c) 2000, 2011, Oracle and/or its affiliates
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA */
16
17
18 #ifdef USE_PRAGMA_IMPLEMENTATION
19 #pragma implementation // gcc: Class implementation
20 #endif
21
22 #define MYSQL_SERVER 1
23 #include "heapdef.h"
24 #include "sql_priv.h"
25 #include "sql_plugin.h"
26 #include "ha_heap.h"
27 #include "sql_base.h" // enum_tdc_remove_table_type
28
29 static handler *heap_create_handler(handlerton *, TABLE_SHARE *, MEM_ROOT *);
30 static int heap_prepare_hp_create_info(TABLE *, bool, HP_CREATE_INFO *);
31
32
heap_panic(handlerton * hton,ha_panic_function flag)33 int heap_panic(handlerton *hton, ha_panic_function flag)
34 {
35 return hp_panic(flag);
36 }
37
38
heap_init(void * p)39 int heap_init(void *p)
40 {
41 handlerton *heap_hton;
42
43 #ifdef HAVE_PSI_INTERFACE
44 init_heap_psi_keys();
45 #endif
46
47 heap_hton= (handlerton *)p;
48 heap_hton->state= SHOW_OPTION_YES;
49 heap_hton->db_type= DB_TYPE_HEAP;
50 heap_hton->create= heap_create_handler;
51 heap_hton->panic= heap_panic;
52 heap_hton->flags= HTON_CAN_RECREATE;
53
54 return 0;
55 }
56
heap_create_handler(handlerton * hton,TABLE_SHARE * table,MEM_ROOT * mem_root)57 static handler *heap_create_handler(handlerton *hton,
58 TABLE_SHARE *table,
59 MEM_ROOT *mem_root)
60 {
61 return new (mem_root) ha_heap(hton, table);
62 }
63
64
65 /*****************************************************************************
66 ** HEAP tables
67 *****************************************************************************/
68
ha_heap(handlerton * hton,TABLE_SHARE * table_arg)69 ha_heap::ha_heap(handlerton *hton, TABLE_SHARE *table_arg)
70 :handler(hton, table_arg), file(0), records_changed(0), key_stat_version(0),
71 internal_table(0)
72 {}
73
74 /*
75 Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to
76 rec_per_key) after 1/HEAP_STATS_UPDATE_THRESHOLD fraction of table records
77 have been inserted/updated/deleted. delete_all_rows() and table flush cause
78 immediate update.
79
80 NOTE
81 hash index statistics must be updated when number of table records changes
82 from 0 to non-zero value and vice versa. Otherwise records_in_range may
83 erroneously return 0 and 'range' may miss records.
84 */
85 #define HEAP_STATS_UPDATE_THRESHOLD 10
86
open(const char * name,int mode,uint test_if_locked)87 int ha_heap::open(const char *name, int mode, uint test_if_locked)
88 {
89 internal_table= MY_TEST(test_if_locked & HA_OPEN_INTERNAL_TABLE);
90 if (internal_table || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
91 {
92 HP_CREATE_INFO create_info;
93 my_bool created_new_share;
94 int rc;
95 file= 0;
96 if (heap_prepare_hp_create_info(table, internal_table, &create_info))
97 goto end;
98 create_info.pin_share= TRUE;
99
100 rc= heap_create(name, &create_info, &internal_share, &created_new_share);
101 my_free(create_info.keydef);
102 if (rc)
103 goto end;
104
105 implicit_emptied= MY_TEST(created_new_share);
106 if (internal_table)
107 file= heap_open_from_share(internal_share, mode);
108 else
109 file= heap_open_from_share_and_register(internal_share, mode);
110
111 if (!file)
112 {
113 heap_release_share(internal_share, internal_table);
114 goto end;
115 }
116 }
117
118 ref_length= sizeof(HEAP_PTR);
119 /* Initialize variables for the opened table */
120 set_keys_for_scanning();
121 /*
122 We cannot run update_key_stats() here because we do not have a
123 lock on the table. The 'records' count might just be changed
124 temporarily at this moment and we might get wrong statistics (Bug
125 #10178). Instead we request for update. This will be done in
126 ha_heap::info(), which is always called before key statistics are
127 used.
128 */
129 key_stat_version= file->s->key_stat_version-1;
130 end:
131 return (file ? 0 : 1);
132 }
133
close(void)134 int ha_heap::close(void)
135 {
136 return internal_table ? hp_close(file) : heap_close(file);
137 }
138
139
140 /*
141 Create a copy of this table
142
143 DESCRIPTION
144 Do same as default implementation but use file->s->name instead of
145 table->s->path. This is needed by Windows where the clone() call sees
146 '/'-delimited path in table->s->path, while ha_heap::open() was called
147 with '\'-delimited path.
148 */
149
clone(const char * name,MEM_ROOT * mem_root)150 handler *ha_heap::clone(const char *name, MEM_ROOT *mem_root)
151 {
152 handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
153 if (new_handler && !new_handler->ha_open(table, file->s->name, table->db_stat,
154 HA_OPEN_IGNORE_IF_LOCKED))
155 return new_handler;
156 return NULL; /* purecov: inspected */
157 }
158
159
160 /*
161 Compute which keys to use for scanning
162
163 SYNOPSIS
164 set_keys_for_scanning()
165 no parameter
166
167 DESCRIPTION
168 Set the bitmap btree_keys, which is used when the upper layers ask
169 which keys to use for scanning. For each btree index the
170 corresponding bit is set.
171
172 RETURN
173 void
174 */
175
set_keys_for_scanning(void)176 void ha_heap::set_keys_for_scanning(void)
177 {
178 btree_keys.clear_all();
179 for (uint i= 0 ; i < table->s->keys ; i++)
180 {
181 if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
182 btree_keys.set_bit(i);
183 }
184 }
185
186
can_continue_handler_scan()187 int ha_heap::can_continue_handler_scan()
188 {
189 int error= 0;
190 if ((file->key_version != file->s->key_version && inited == INDEX) ||
191 (file->file_version != file->s->file_version && inited == RND))
192 {
193 /* Data changed, not safe to do index or rnd scan */
194 error= HA_ERR_RECORD_CHANGED;
195 }
196 return error;
197 }
198
199
update_key_stats()200 void ha_heap::update_key_stats()
201 {
202 for (uint i= 0; i < table->s->keys; i++)
203 {
204 KEY *key=table->key_info+i;
205 if (!key->rec_per_key)
206 continue;
207 if (key->algorithm != HA_KEY_ALG_BTREE)
208 {
209 if (key->flags & HA_NOSAME)
210 key->rec_per_key[key->user_defined_key_parts-1]= 1;
211 else
212 {
213 ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
214 ulong no_records= hash_buckets ? (ulong)(file->s->records/hash_buckets) : 2;
215 if (no_records < 2)
216 no_records= 2;
217 key->rec_per_key[key->user_defined_key_parts-1]= no_records;
218 }
219 }
220 }
221 records_changed= 0;
222 /* At the end of update_key_stats() we can proudly claim they are OK. */
223 key_stat_version= file->s->key_stat_version;
224 }
225
226
write_row(uchar * buf)227 int ha_heap::write_row(uchar * buf)
228 {
229 int res;
230 if (table->next_number_field && buf == table->record[0])
231 {
232 if ((res= update_auto_increment()))
233 return res;
234 }
235 res= heap_write(file,buf);
236 if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
237 file->s->records))
238 {
239 /*
240 We can perform this safely since only one writer at the time is
241 allowed on the table.
242 */
243 records_changed= 0;
244 file->s->key_stat_version++;
245 }
246 return res;
247 }
248
update_row(const uchar * old_data,const uchar * new_data)249 int ha_heap::update_row(const uchar * old_data, const uchar * new_data)
250 {
251 int res;
252 res= heap_update(file,old_data,new_data);
253 if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
254 file->s->records)
255 {
256 /*
257 We can perform this safely since only one writer at the time is
258 allowed on the table.
259 */
260 records_changed= 0;
261 file->s->key_stat_version++;
262 }
263 return res;
264 }
265
delete_row(const uchar * buf)266 int ha_heap::delete_row(const uchar * buf)
267 {
268 int res;
269 res= heap_delete(file,buf);
270 if (!res && table->s->tmp_table == NO_TMP_TABLE &&
271 ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
272 {
273 /*
274 We can perform this safely since only one writer at the time is
275 allowed on the table.
276 */
277 records_changed= 0;
278 file->s->key_stat_version++;
279 }
280 return res;
281 }
282
index_read_map(uchar * buf,const uchar * key,key_part_map keypart_map,enum ha_rkey_function find_flag)283 int ha_heap::index_read_map(uchar *buf, const uchar *key,
284 key_part_map keypart_map,
285 enum ha_rkey_function find_flag)
286 {
287 DBUG_ASSERT(inited==INDEX);
288 int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
289 return error;
290 }
291
index_read_last_map(uchar * buf,const uchar * key,key_part_map keypart_map)292 int ha_heap::index_read_last_map(uchar *buf, const uchar *key,
293 key_part_map keypart_map)
294 {
295 DBUG_ASSERT(inited==INDEX);
296 int error= heap_rkey(file, buf, active_index, key, keypart_map,
297 HA_READ_PREFIX_LAST);
298 return error;
299 }
300
index_read_idx_map(uchar * buf,uint index,const uchar * key,key_part_map keypart_map,enum ha_rkey_function find_flag)301 int ha_heap::index_read_idx_map(uchar *buf, uint index, const uchar *key,
302 key_part_map keypart_map,
303 enum ha_rkey_function find_flag)
304 {
305 int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
306 return error;
307 }
308
index_next(uchar * buf)309 int ha_heap::index_next(uchar * buf)
310 {
311 DBUG_ASSERT(inited==INDEX);
312 int error=heap_rnext(file,buf);
313 return error;
314 }
315
index_prev(uchar * buf)316 int ha_heap::index_prev(uchar * buf)
317 {
318 DBUG_ASSERT(inited==INDEX);
319 int error=heap_rprev(file,buf);
320 return error;
321 }
322
index_first(uchar * buf)323 int ha_heap::index_first(uchar * buf)
324 {
325 DBUG_ASSERT(inited==INDEX);
326 int error=heap_rfirst(file, buf, active_index);
327 return error;
328 }
329
index_last(uchar * buf)330 int ha_heap::index_last(uchar * buf)
331 {
332 DBUG_ASSERT(inited==INDEX);
333 int error=heap_rlast(file, buf, active_index);
334 return error;
335 }
336
rnd_init(bool scan)337 int ha_heap::rnd_init(bool scan)
338 {
339 return scan ? heap_scan_init(file) : 0;
340 }
341
rnd_next(uchar * buf)342 int ha_heap::rnd_next(uchar *buf)
343 {
344 int error=heap_scan(file, buf);
345 return error;
346 }
347
rnd_pos(uchar * buf,uchar * pos)348 int ha_heap::rnd_pos(uchar * buf, uchar *pos)
349 {
350 int error;
351 HEAP_PTR heap_position;
352 memcpy(&heap_position, pos, sizeof(HEAP_PTR));
353 error=heap_rrnd(file, buf, heap_position);
354 return error;
355 }
356
position(const uchar * record)357 void ha_heap::position(const uchar *record)
358 {
359 *(HEAP_PTR*) ref= heap_position(file); // Ref is aligned
360 }
361
info(uint flag)362 int ha_heap::info(uint flag)
363 {
364 HEAPINFO hp_info;
365
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 stats.create_time= (ulong) hp_info.create_time;
377 if (flag & HA_STATUS_AUTO)
378 stats.auto_increment_value= hp_info.auto_increment;
379 /*
380 If info() is called for the first time after open(), we will still
381 have to update the key statistics. Hoping that a table lock is now
382 in place.
383 */
384 if (key_stat_version != file->s->key_stat_version)
385 update_key_stats();
386 return 0;
387 }
388
389
extra(enum ha_extra_function operation)390 int ha_heap::extra(enum ha_extra_function operation)
391 {
392 return heap_extra(file,operation);
393 }
394
395
reset()396 int ha_heap::reset()
397 {
398 return heap_reset(file);
399 }
400
401
delete_all_rows()402 int ha_heap::delete_all_rows()
403 {
404 heap_clear(file);
405 if (table->s->tmp_table == NO_TMP_TABLE)
406 {
407 /*
408 We can perform this safely since only one writer at the time is
409 allowed on the table.
410 */
411 file->s->key_stat_version++;
412 }
413 return 0;
414 }
415
416
reset_auto_increment(ulonglong value)417 int ha_heap::reset_auto_increment(ulonglong value)
418 {
419 file->s->auto_increment= value;
420 return 0;
421 }
422
423
external_lock(THD * thd,int lock_type)424 int ha_heap::external_lock(THD *thd, int lock_type)
425 {
426 #if !defined(DBUG_OFF) && defined(EXTRA_DEBUG)
427 if (lock_type == F_UNLCK && file->s->changed && heap_check_heap(file, 0))
428 return HA_ERR_CRASHED;
429 #endif
430 return 0; // No external locking
431 }
432
433
434 /*
435 Disable indexes.
436
437 SYNOPSIS
438 disable_indexes()
439 mode mode of operation:
440 HA_KEY_SWITCH_NONUNIQ disable all non-unique keys
441 HA_KEY_SWITCH_ALL disable all keys
442 HA_KEY_SWITCH_NONUNIQ_SAVE dis. non-uni. and make persistent
443 HA_KEY_SWITCH_ALL_SAVE dis. all keys and make persistent
444
445 DESCRIPTION
446 Disable indexes and clear keys to use for scanning.
447
448 IMPLEMENTATION
449 HA_KEY_SWITCH_NONUNIQ is not implemented.
450 HA_KEY_SWITCH_NONUNIQ_SAVE is not implemented with HEAP.
451 HA_KEY_SWITCH_ALL_SAVE is not implemented with HEAP.
452
453 RETURN
454 0 ok
455 HA_ERR_WRONG_COMMAND mode not implemented.
456 */
457
disable_indexes(uint mode)458 int ha_heap::disable_indexes(uint mode)
459 {
460 int error;
461
462 if (mode == HA_KEY_SWITCH_ALL)
463 {
464 if (!(error= heap_disable_indexes(file)))
465 set_keys_for_scanning();
466 }
467 else
468 {
469 /* mode not implemented */
470 error= HA_ERR_WRONG_COMMAND;
471 }
472 return error;
473 }
474
475
476 /*
477 Enable indexes.
478
479 SYNOPSIS
480 enable_indexes()
481 mode mode of operation:
482 HA_KEY_SWITCH_NONUNIQ enable all non-unique keys
483 HA_KEY_SWITCH_ALL enable all keys
484 HA_KEY_SWITCH_NONUNIQ_SAVE en. non-uni. and make persistent
485 HA_KEY_SWITCH_ALL_SAVE en. all keys and make persistent
486
487 DESCRIPTION
488 Enable indexes and set keys to use for scanning.
489 The indexes might have been disabled by disable_index() before.
490 The function works only if both data and indexes are empty,
491 since the heap storage engine cannot repair the indexes.
492 To be sure, call handler::delete_all_rows() before.
493
494 IMPLEMENTATION
495 HA_KEY_SWITCH_NONUNIQ is not implemented.
496 HA_KEY_SWITCH_NONUNIQ_SAVE is not implemented with HEAP.
497 HA_KEY_SWITCH_ALL_SAVE is not implemented with HEAP.
498
499 RETURN
500 0 ok
501 HA_ERR_CRASHED data or index is non-empty. Delete all rows and retry.
502 HA_ERR_WRONG_COMMAND mode not implemented.
503 */
504
enable_indexes(uint mode)505 int ha_heap::enable_indexes(uint mode)
506 {
507 int error;
508
509 if (mode == HA_KEY_SWITCH_ALL)
510 {
511 if (!(error= heap_enable_indexes(file)))
512 set_keys_for_scanning();
513 }
514 else
515 {
516 /* mode not implemented */
517 error= HA_ERR_WRONG_COMMAND;
518 }
519 return error;
520 }
521
522
523 /*
524 Test if indexes are disabled.
525
526 SYNOPSIS
527 indexes_are_disabled()
528 no parameters
529
530 RETURN
531 0 indexes are not disabled
532 1 all indexes are disabled
533 [2 non-unique indexes are disabled - NOT YET IMPLEMENTED]
534 */
535
indexes_are_disabled(void)536 int ha_heap::indexes_are_disabled(void)
537 {
538 return heap_indexes_are_disabled(file);
539 }
540
store_lock(THD * thd,THR_LOCK_DATA ** to,enum thr_lock_type lock_type)541 THR_LOCK_DATA **ha_heap::store_lock(THD *thd,
542 THR_LOCK_DATA **to,
543 enum thr_lock_type lock_type)
544 {
545 if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
546 file->lock.type=lock_type;
547 *to++= &file->lock;
548 return to;
549 }
550
551 /*
552 We have to ignore ENOENT entries as the HEAP table is created on open and
553 not when doing a CREATE on the table.
554 */
555
delete_table(const char * name)556 int ha_heap::delete_table(const char *name)
557 {
558 int error= heap_delete_table(name);
559 return error == ENOENT ? 0 : error;
560 }
561
562
drop_table(const char * name)563 void ha_heap::drop_table(const char *name)
564 {
565 file->s->delete_on_close= 1;
566 ha_close();
567 }
568
569
rename_table(const char * from,const char * to)570 int ha_heap::rename_table(const char * from, const char * to)
571 {
572 return heap_rename(from,to);
573 }
574
575
records_in_range(uint inx,key_range * min_key,key_range * max_key)576 ha_rows ha_heap::records_in_range(uint inx, key_range *min_key,
577 key_range *max_key)
578 {
579 KEY *key=table->key_info+inx;
580 if (key->algorithm == HA_KEY_ALG_BTREE)
581 return hp_rb_records_in_range(file, inx, min_key, max_key);
582
583 if (!min_key || !max_key ||
584 min_key->length != max_key->length ||
585 min_key->length != key->key_length ||
586 min_key->flag != HA_READ_KEY_EXACT ||
587 max_key->flag != HA_READ_AFTER_KEY)
588 return HA_POS_ERROR; // Can only use exact keys
589
590 if (stats.records <= 1)
591 return stats.records;
592
593 /* Assert that info() did run. We need current statistics here. */
594 DBUG_ASSERT(key_stat_version == file->s->key_stat_version);
595 return key->rec_per_key[key->user_defined_key_parts-1];
596 }
597
598
heap_prepare_hp_create_info(TABLE * table_arg,bool internal_table,HP_CREATE_INFO * hp_create_info)599 static int heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table,
600 HP_CREATE_INFO *hp_create_info)
601 {
602 TABLE_SHARE *share= table_arg->s;
603 uint key, parts, mem_per_row= 0, keys= share->keys;
604 uint auto_key= 0, auto_key_type= 0;
605 ha_rows max_rows;
606 HP_KEYDEF *keydef;
607 HA_KEYSEG *seg;
608 bool found_real_auto_increment= 0;
609
610 bzero(hp_create_info, sizeof(*hp_create_info));
611
612 for (key= parts= 0; key < keys; key++)
613 parts+= table_arg->key_info[key].user_defined_key_parts;
614
615 if (!my_multi_malloc(MYF(MY_WME | MY_THREAD_SPECIFIC),
616 &keydef, keys * sizeof(HP_KEYDEF),
617 &seg, parts * sizeof(HA_KEYSEG),
618 NULL))
619 return my_errno;
620 for (key= 0; key < keys; key++)
621 {
622 KEY *pos= table_arg->key_info+key;
623 KEY_PART_INFO *key_part= pos->key_part;
624 KEY_PART_INFO *key_part_end= key_part + pos->user_defined_key_parts;
625
626 keydef[key].keysegs= (uint) pos->user_defined_key_parts;
627 keydef[key].flag= (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
628 keydef[key].seg= seg;
629
630 switch (pos->algorithm) {
631 case HA_KEY_ALG_UNDEF:
632 case HA_KEY_ALG_HASH:
633 keydef[key].algorithm= HA_KEY_ALG_HASH;
634 mem_per_row+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
635 break;
636 case HA_KEY_ALG_BTREE:
637 keydef[key].algorithm= HA_KEY_ALG_BTREE;
638 mem_per_row+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
639 break;
640 default:
641 DBUG_ASSERT(0); // cannot happen
642 }
643
644 for (; key_part != key_part_end; key_part++, seg++)
645 {
646 Field *field= key_part->field;
647
648 if (pos->algorithm == HA_KEY_ALG_BTREE)
649 seg->type= field->key_type();
650 else
651 {
652 if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
653 seg->type != HA_KEYTYPE_VARTEXT1 &&
654 seg->type != HA_KEYTYPE_VARTEXT2 &&
655 seg->type != HA_KEYTYPE_VARBINARY1 &&
656 seg->type != HA_KEYTYPE_VARBINARY2 &&
657 seg->type != HA_KEYTYPE_BIT)
658 seg->type= HA_KEYTYPE_BINARY;
659 }
660 seg->start= (uint) key_part->offset;
661 seg->length= (uint) key_part->length;
662 seg->flag= key_part->key_part_flag;
663
664 if (field->flags & (ENUM_FLAG | SET_FLAG))
665 seg->charset= &my_charset_bin;
666 else
667 seg->charset= field->charset_for_protocol();
668 if (field->null_ptr)
669 {
670 seg->null_bit= field->null_bit;
671 seg->null_pos= (uint) (field->null_ptr - (uchar*) table_arg->record[0]);
672 }
673 else
674 {
675 seg->null_bit= 0;
676 seg->null_pos= 0;
677 }
678 if (field->flags & AUTO_INCREMENT_FLAG &&
679 table_arg->found_next_number_field &&
680 key == share->next_number_index)
681 {
682 /*
683 Store key number and type for found auto_increment key
684 We have to store type as seg->type can differ from it
685 */
686 auto_key= key+ 1;
687 auto_key_type= field->key_type();
688 }
689 if (seg->type == HA_KEYTYPE_BIT)
690 {
691 seg->bit_length= ((Field_bit *) field)->bit_len;
692 seg->bit_start= ((Field_bit *) field)->bit_ofs;
693 seg->bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
694 (uchar*) table_arg->record[0]);
695 }
696 else
697 {
698 seg->bit_length= seg->bit_start= 0;
699 seg->bit_pos= 0;
700 }
701 }
702 }
703 mem_per_row+= MY_ALIGN(MY_MAX(share->reclength, sizeof(char*)) + 1, sizeof(char*));
704 if (table_arg->found_next_number_field)
705 {
706 keydef[share->next_number_index].flag|= HA_AUTO_KEY;
707 found_real_auto_increment= share->next_number_key_offset == 0;
708 }
709 hp_create_info->auto_key= auto_key;
710 hp_create_info->auto_key_type= auto_key_type;
711 hp_create_info->max_table_size=current_thd->variables.max_heap_table_size;
712 hp_create_info->with_auto_increment= found_real_auto_increment;
713 hp_create_info->internal_table= internal_table;
714
715 max_rows= (ha_rows) (hp_create_info->max_table_size / mem_per_row);
716 if (share->max_rows && share->max_rows < max_rows)
717 max_rows= share->max_rows;
718
719 hp_create_info->max_records= (ulong) MY_MIN(max_rows, ULONG_MAX);
720 hp_create_info->min_records= (ulong) MY_MIN(share->min_rows, ULONG_MAX);
721 hp_create_info->keys= share->keys;
722 hp_create_info->reclength= share->reclength;
723 hp_create_info->keydef= keydef;
724 return 0;
725 }
726
727
create(const char * name,TABLE * table_arg,HA_CREATE_INFO * create_info)728 int ha_heap::create(const char *name, TABLE *table_arg,
729 HA_CREATE_INFO *create_info)
730 {
731 int error;
732 my_bool created;
733 HP_CREATE_INFO hp_create_info;
734
735 error= heap_prepare_hp_create_info(table_arg, internal_table,
736 &hp_create_info);
737 if (error)
738 return error;
739 hp_create_info.auto_increment= (create_info->auto_increment_value ?
740 create_info->auto_increment_value - 1 : 0);
741 error= heap_create(name, &hp_create_info, &internal_share, &created);
742 my_free(hp_create_info.keydef);
743 DBUG_ASSERT(file == 0);
744 return (error);
745 }
746
747
update_create_info(HA_CREATE_INFO * create_info)748 void ha_heap::update_create_info(HA_CREATE_INFO *create_info)
749 {
750 table->file->info(HA_STATUS_AUTO);
751 if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
752 create_info->auto_increment_value= stats.auto_increment_value;
753 }
754
get_auto_increment(ulonglong offset,ulonglong increment,ulonglong nb_desired_values,ulonglong * first_value,ulonglong * nb_reserved_values)755 void ha_heap::get_auto_increment(ulonglong offset, ulonglong increment,
756 ulonglong nb_desired_values,
757 ulonglong *first_value,
758 ulonglong *nb_reserved_values)
759 {
760 ha_heap::info(HA_STATUS_AUTO);
761 *first_value= stats.auto_increment_value;
762 /* such table has only table-level locking so reserves up to +inf */
763 *nb_reserved_values= ULONGLONG_MAX;
764 }
765
766
check_if_incompatible_data(HA_CREATE_INFO * info,uint table_changes)767 bool ha_heap::check_if_incompatible_data(HA_CREATE_INFO *info,
768 uint table_changes)
769 {
770 /* Check that auto_increment value was not changed */
771 if ((info->used_fields & HA_CREATE_USED_AUTO &&
772 info->auto_increment_value != 0) ||
773 table_changes == IS_EQUAL_NO ||
774 table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet
775 return COMPATIBLE_DATA_NO;
776 return COMPATIBLE_DATA_YES;
777 }
778
779
780 /**
781 Find record by unique index (used in temporary tables with the index)
782
783 @param record (IN|OUT) the record to find
784 @param unique_idx (IN) number of index (for this engine)
785
786 @note It is like hp_search but uses function for raw where hp_search
787 uses functions for index.
788
789 @retval 0 OK
790 @retval 1 Not found
791 @retval -1 Error
792 */
793
find_unique_row(uchar * record,uint unique_idx)794 int ha_heap::find_unique_row(uchar *record, uint unique_idx)
795 {
796 DBUG_ENTER("ha_heap::find_unique_row");
797 HP_SHARE *share= file->s;
798 DBUG_ASSERT(inited==NONE);
799 HP_KEYDEF *keyinfo= share->keydef + unique_idx;
800 DBUG_ASSERT(keyinfo->algorithm == HA_KEY_ALG_HASH);
801 DBUG_ASSERT(keyinfo->flag & HA_NOSAME);
802 if (!share->records)
803 DBUG_RETURN(1); // not found
804 HASH_INFO *pos= hp_find_hash(&keyinfo->block,
805 hp_mask(hp_rec_hashnr(keyinfo, record),
806 share->blength, share->records));
807 do
808 {
809 if (!hp_rec_key_cmp(keyinfo, pos->ptr_to_rec, record))
810 {
811 file->current_hash_ptr= pos;
812 file->current_ptr= pos->ptr_to_rec;
813 file->update = HA_STATE_AKTIV;
814 /*
815 We compare it only by record in the index, so better to read all
816 records.
817 */
818 memcpy(record, file->current_ptr, (size_t) share->reclength);
819
820 DBUG_RETURN(0); // found and position set
821 }
822 }
823 while ((pos= pos->next_key));
824 DBUG_RETURN(1); // not found
825 }
826
827 struct st_mysql_storage_engine heap_storage_engine=
828 { MYSQL_HANDLERTON_INTERFACE_VERSION };
829
mysql_declare_plugin(heap)830 mysql_declare_plugin(heap)
831 {
832 MYSQL_STORAGE_ENGINE_PLUGIN,
833 &heap_storage_engine,
834 "MEMORY",
835 "MySQL AB",
836 "Hash based, stored in memory, useful for temporary tables",
837 PLUGIN_LICENSE_GPL,
838 heap_init,
839 NULL,
840 0x0100, /* 1.0 */
841 NULL, /* status variables */
842 NULL, /* system variables */
843 NULL, /* config options */
844 0, /* flags */
845 }
846 mysql_declare_plugin_end;
maria_declare_plugin(heap)847 maria_declare_plugin(heap)
848 {
849 MYSQL_STORAGE_ENGINE_PLUGIN,
850 &heap_storage_engine,
851 "MEMORY",
852 "MySQL AB",
853 "Hash based, stored in memory, useful for temporary tables",
854 PLUGIN_LICENSE_GPL,
855 heap_init,
856 NULL,
857 0x0100, /* 1.0 */
858 NULL, /* status variables */
859 NULL, /* system variables */
860 "1.0", /* string version */
861 MariaDB_PLUGIN_MATURITY_STABLE /* maturity */
862 }
863 maria_declare_plugin_end;
864