18 #define MYSQL_SERVER 1
20 #include "probes_mysql.h"
21 #include "sql_plugin.h"
30 heap_prepare_hp_create_info(
TABLE *table_arg,
bool internal_table,
34 int heap_panic(
handlerton *hton, ha_panic_function flag)
36 return hp_panic(flag);
40 int heap_init(
void *p)
44 #ifdef HAVE_PSI_INTERFACE
49 heap_hton->state= SHOW_OPTION_YES;
50 heap_hton->db_type= DB_TYPE_HEAP;
51 heap_hton->create= heap_create_handler;
52 heap_hton->panic= heap_panic;
53 heap_hton->flags= HTON_CAN_RECREATE;
62 return new (mem_root)
ha_heap(hton, table);
71 :
handler(hton, table_arg),
file(0), records_changed(0), key_stat_version(0),
76 static const char *ha_heap_exts[] = {
96 #define HEAP_STATS_UPDATE_THRESHOLD 10
98 int ha_heap::open(
const char *
name,
int mode, uint test_if_locked)
100 internal_table=
test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
101 if (internal_table || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
104 my_bool created_new_share;
107 if (heap_prepare_hp_create_info(table, internal_table, &create_info))
109 create_info.pin_share= TRUE;
111 rc= heap_create(name, &create_info, &internal_share, &created_new_share);
112 my_free(create_info.keydef);
116 implicit_emptied=
test(created_new_share);
118 file= heap_open_from_share(internal_share, mode);
120 file= heap_open_from_share_and_register(internal_share, mode);
124 heap_release_share(internal_share, internal_table);
131 set_keys_for_scanning();
140 key_stat_version= file->s->key_stat_version-1;
142 return (file ? 0 : 1);
145 int ha_heap::close(
void)
147 return internal_table ? hp_close(file) : heap_close(file);
163 handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
164 if (new_handler && !new_handler->
ha_open(table, file->s->name, table->db_stat,
165 HA_OPEN_IGNORE_IF_LOCKED))
187 void ha_heap::set_keys_for_scanning(
void)
189 btree_keys.clear_all();
190 for (uint
i= 0 ;
i < table->s->keys ;
i++)
192 if (table->key_info[
i].algorithm == HA_KEY_ALG_BTREE)
193 btree_keys.set_bit(
i);
198 void ha_heap::update_key_stats()
200 for (uint
i= 0;
i < table->s->keys;
i++)
202 KEY *key=table->key_info+
i;
205 if (key->algorithm != HA_KEY_ALG_BTREE)
207 if (key->
flags & HA_NOSAME)
211 ha_rows hash_buckets= file->s->keydef[
i].hash_buckets;
212 uint no_records= hash_buckets ? (uint) (file->s->records/hash_buckets) : 2;
221 key_stat_version= file->s->key_stat_version;
225 int ha_heap::write_row(uchar *
buf)
228 ha_statistic_increment(&SSV::ha_write_count);
229 if (table->next_number_field && buf == table->record[0])
231 if ((res= update_auto_increment()))
234 res= heap_write(file,buf);
235 if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
242 file->s->key_stat_version++;
247 int ha_heap::update_row(
const uchar * old_data, uchar * new_data)
250 ha_statistic_increment(&SSV::ha_update_count);
251 res= heap_update(file,old_data,new_data);
252 if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD >
259 file->s->key_stat_version++;
264 int ha_heap::delete_row(
const uchar * buf)
267 ha_statistic_increment(&SSV::ha_delete_count);
268 res= heap_delete(file,buf);
269 if (!res && table->s->tmp_table == NO_TMP_TABLE &&
270 ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
276 file->s->key_stat_version++;
282 key_part_map keypart_map,
283 enum ha_rkey_function find_flag)
285 MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
286 DBUG_ASSERT(inited==INDEX);
287 ha_statistic_increment(&SSV::ha_read_key_count);
288 int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
289 table->status = error ? STATUS_NOT_FOUND : 0;
290 MYSQL_INDEX_READ_ROW_DONE(error);
295 key_part_map keypart_map)
297 MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
298 DBUG_ASSERT(inited==INDEX);
299 ha_statistic_increment(&SSV::ha_read_key_count);
300 int error= heap_rkey(file, buf, active_index, key, keypart_map,
301 HA_READ_PREFIX_LAST);
302 table->status= error ? STATUS_NOT_FOUND : 0;
303 MYSQL_INDEX_READ_ROW_DONE(error);
308 key_part_map keypart_map,
309 enum ha_rkey_function find_flag)
311 MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
312 ha_statistic_increment(&SSV::ha_read_key_count);
313 int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
314 table->status = error ? STATUS_NOT_FOUND : 0;
315 MYSQL_INDEX_READ_ROW_DONE(error);
321 MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
322 DBUG_ASSERT(inited==INDEX);
323 ha_statistic_increment(&SSV::ha_read_next_count);
324 int error=heap_rnext(file,buf);
325 table->status=error ? STATUS_NOT_FOUND: 0;
326 MYSQL_INDEX_READ_ROW_DONE(error);
332 MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
333 DBUG_ASSERT(inited==INDEX);
334 ha_statistic_increment(&SSV::ha_read_prev_count);
335 int error=heap_rprev(file,buf);
336 table->status=error ? STATUS_NOT_FOUND: 0;
337 MYSQL_INDEX_READ_ROW_DONE(error);
343 MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
344 DBUG_ASSERT(inited==INDEX);
345 ha_statistic_increment(&SSV::ha_read_first_count);
346 int error=heap_rfirst(file, buf, active_index);
347 table->status=error ? STATUS_NOT_FOUND: 0;
348 MYSQL_INDEX_READ_ROW_DONE(error);
354 MYSQL_INDEX_READ_ROW_START(table_share->db.str, table_share->table_name.str);
355 DBUG_ASSERT(inited==INDEX);
356 ha_statistic_increment(&SSV::ha_read_last_count);
357 int error=heap_rlast(file, buf, active_index);
358 table->status=error ? STATUS_NOT_FOUND: 0;
359 MYSQL_INDEX_READ_ROW_DONE(error);
365 return scan ? heap_scan_init(file) : 0;
370 MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str,
372 ha_statistic_increment(&SSV::ha_read_rnd_next_count);
373 int error=heap_scan(file, buf);
374 table->status=error ? STATUS_NOT_FOUND: 0;
375 MYSQL_READ_ROW_DONE(error);
382 HEAP_PTR heap_position;
383 MYSQL_READ_ROW_START(table_share->db.str, table_share->table_name.str,
385 ha_statistic_increment(&SSV::ha_read_rnd_count);
386 memcpy(&heap_position, pos,
sizeof(HEAP_PTR));
387 error=heap_rrnd(file, buf, heap_position);
388 table->status=error ? STATUS_NOT_FOUND: 0;
389 MYSQL_READ_ROW_DONE(error);
393 void ha_heap::position(
const uchar *
record)
395 *(HEAP_PTR*) ref= heap_position(file);
398 int ha_heap::info(uint flag)
401 (void) heap_info(file,&hp_info,flag);
403 errkey= hp_info.errkey;
404 stats.records= hp_info.records;
405 stats.deleted= hp_info.deleted;
406 stats.mean_rec_length= hp_info.reclength;
407 stats.data_file_length= hp_info.data_length;
408 stats.index_file_length= hp_info.index_length;
409 stats.max_data_file_length= hp_info.max_records * hp_info.reclength;
410 stats.delete_length= hp_info.deleted * hp_info.reclength;
411 stats.create_time= (ulong) hp_info.create_time;
412 if (flag & HA_STATUS_AUTO)
413 stats.auto_increment_value= hp_info.auto_increment;
419 if (key_stat_version != file->s->key_stat_version)
425 int ha_heap::extra(
enum ha_extra_function operation)
427 return heap_extra(file,operation);
433 return heap_reset(file);
440 if (table->s->tmp_table == NO_TMP_TABLE)
446 file->s->key_stat_version++;
461 file->s->auto_increment= value;
466 int ha_heap::external_lock(THD *thd,
int lock_type)
496 int ha_heap::disable_indexes(uint mode)
500 if (mode == HA_KEY_SWITCH_ALL)
502 if (!(error= heap_disable_indexes(file)))
503 set_keys_for_scanning();
508 error= HA_ERR_WRONG_COMMAND;
543 int ha_heap::enable_indexes(uint mode)
547 if (mode == HA_KEY_SWITCH_ALL)
549 if (!(error= heap_enable_indexes(file)))
550 set_keys_for_scanning();
555 error= HA_ERR_WRONG_COMMAND;
574 int ha_heap::indexes_are_disabled(
void)
576 return heap_indexes_are_disabled(file);
581 enum thr_lock_type lock_type)
583 if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
584 file->lock.type=lock_type;
596 int error= heap_delete_table(name);
597 return error == ENOENT ? 0 : error;
601 void ha_heap::drop_table(
const char *name)
603 file->s->delete_on_close= 1;
610 return heap_rename(from,to);
614 ha_rows ha_heap::records_in_range(uint inx,
key_range *min_key,
617 KEY *key=table->key_info+inx;
618 if (key->algorithm == HA_KEY_ALG_BTREE)
619 return hp_rb_records_in_range(file, inx, min_key, max_key);
621 if (!min_key || !max_key ||
622 min_key->length != max_key->length ||
624 min_key->flag != HA_READ_KEY_EXACT ||
625 max_key->flag != HA_READ_AFTER_KEY)
628 if (
stats.records <= 1)
629 return stats.records;
632 DBUG_ASSERT(key_stat_version == file->s->key_stat_version);
638 heap_prepare_hp_create_info(
TABLE *table_arg,
bool internal_table,
641 uint key, parts, mem_per_row= 0, keys= table_arg->s->keys;
642 uint auto_key= 0, auto_key_type= 0;
647 bool found_real_auto_increment= 0;
649 memset(hp_create_info, 0,
sizeof(*hp_create_info));
651 for (key= parts= 0; key < keys; key++)
658 seg=
reinterpret_cast<HA_KEYSEG*
>(keydef + keys);
659 for (key= 0; key < keys; key++)
661 KEY *pos= table_arg->key_info+key;
666 keydef[key].flag= (pos->
flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
667 keydef[key].seg= seg;
669 switch (pos->algorithm) {
670 case HA_KEY_ALG_UNDEF:
671 case HA_KEY_ALG_HASH:
672 keydef[key].algorithm= HA_KEY_ALG_HASH;
673 mem_per_row+=
sizeof(
char*) * 2;
675 case HA_KEY_ALG_BTREE:
676 keydef[key].algorithm= HA_KEY_ALG_BTREE;
683 for (; key_part != key_part_end; key_part++, seg++)
685 Field *field= key_part->field;
687 if (pos->algorithm == HA_KEY_ALG_BTREE)
688 seg->type= field->key_type();
691 if ((seg->type = field->key_type()) != (
int) HA_KEYTYPE_TEXT &&
692 seg->type != HA_KEYTYPE_VARTEXT1 &&
693 seg->type != HA_KEYTYPE_VARTEXT2 &&
694 seg->type != HA_KEYTYPE_VARBINARY1 &&
695 seg->type != HA_KEYTYPE_VARBINARY2)
696 seg->type= HA_KEYTYPE_BINARY;
698 seg->start= (uint) key_part->offset;
699 seg->length= (uint) key_part->length;
700 seg->flag= key_part->key_part_flag;
702 if (field->flags & (ENUM_FLAG | SET_FLAG))
703 seg->charset= &my_charset_bin;
705 seg->charset= field->charset_for_protocol();
708 seg->null_bit= field->null_bit;
709 seg->null_pos= field->null_offset();
716 if (field->flags & AUTO_INCREMENT_FLAG &&
717 table_arg->found_next_number_field &&
718 key == share->next_number_index)
725 auto_key_type= field->key_type();
729 mem_per_row+= MY_ALIGN(share->reclength + 1,
sizeof(
char*));
730 if (table_arg->found_next_number_field)
732 keydef[share->next_number_index].flag|= HA_AUTO_KEY;
733 found_real_auto_increment= share->next_number_key_offset == 0;
735 hp_create_info->auto_key= auto_key;
736 hp_create_info->auto_key_type= auto_key_type;
737 hp_create_info->max_table_size=current_thd->variables.max_heap_table_size;
738 hp_create_info->with_auto_increment= found_real_auto_increment;
739 hp_create_info->internal_table= internal_table;
741 max_rows= (ha_rows) (hp_create_info->max_table_size / mem_per_row);
742 if (share->max_rows && share->max_rows < max_rows)
743 max_rows= share->max_rows;
745 hp_create_info->max_records= (ulong) max_rows;
746 hp_create_info->min_records= (ulong) share->min_rows;
747 hp_create_info->keys= share->keys;
748 hp_create_info->reclength= share->reclength;
749 hp_create_info->keydef= keydef;
754 int ha_heap::create(
const char *name,
TABLE *table_arg,
761 error= heap_prepare_hp_create_info(table_arg, internal_table,
765 hp_create_info.auto_increment= (create_info->auto_increment_value ?
766 create_info->auto_increment_value - 1 : 0);
767 error= heap_create(name, &hp_create_info, &internal_share, &created);
768 my_free(hp_create_info.keydef);
769 DBUG_ASSERT(file == 0);
776 table->file->info(HA_STATUS_AUTO);
777 if (!(create_info->used_fields & HA_CREATE_USED_AUTO))
778 create_info->auto_increment_value=
stats.auto_increment_value;
782 ulonglong nb_desired_values,
783 ulonglong *first_value,
784 ulonglong *nb_reserved_values)
786 ha_heap::info(HA_STATUS_AUTO);
787 *first_value=
stats.auto_increment_value;
789 *nb_reserved_values= ULONGLONG_MAX;
797 if ((info->used_fields & HA_CREATE_USED_AUTO &&
798 info->auto_increment_value != 0) ||
799 table_changes == IS_EQUAL_NO ||
800 table_changes & IS_EQUAL_PACK_LENGTH)
801 return COMPATIBLE_DATA_NO;
802 return COMPATIBLE_DATA_YES;
806 { MYSQL_HANDLERTON_INTERFACE_VERSION };
808 mysql_declare_plugin(
heap)
810 MYSQL_STORAGE_ENGINE_PLUGIN,
811 &heap_storage_engine,
814 "Hash based, stored in memory, useful for temporary tables",
824 mysql_declare_plugin_end;