diff options
author | unknown <brian@zim.(none)> | 2006-08-19 08:02:52 -0700 |
---|---|---|
committer | unknown <brian@zim.(none)> | 2006-08-19 08:02:52 -0700 |
commit | 39f1d9f411160beb20f367fec4d01f9721d7a513 (patch) | |
tree | bff4aef57437dbbbcad1f67836d2d87629079ee4 /sql/ha_heap.cc | |
parent | b470b3ab87743a13470098b8446da3fe2e100c9e (diff) | |
download | mariadb-git-39f1d9f411160beb20f367fec4d01f9721d7a513.tar.gz |
Moved heap into its own directory.
storage/heap/ha_heap.h:
Rename: sql/ha_heap.h -> storage/heap/ha_heap.h
libmysqld/Makefile.am:
Heap changes
sql/CMakeLists.txt:
Removed ha_heap
sql/Makefile.am:
Removed heap
sql/handler.cc:
Removed unneeded include call
storage/heap/Makefile.am:
Adjusted heap Makefile.am to include ha_heap.cc
storage/heap/ha_heap.cc:
Added plugin header
Diffstat (limited to 'sql/ha_heap.cc')
-rw-r--r-- | sql/ha_heap.cc | 712 |
1 files changed, 0 insertions, 712 deletions
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc deleted file mode 100644 index 3a2027afaba..00000000000 --- a/sql/ha_heap.cc +++ /dev/null @@ -1,712 +0,0 @@ -/* Copyright (C) 2000,2004 MySQL AB & MySQL Finland AB & TCX DataKonsult AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - - -#ifdef USE_PRAGMA_IMPLEMENTATION -#pragma implementation // gcc: Class implementation -#endif - -#include "mysql_priv.h" -#include <myisampack.h> -#include "ha_heap.h" - - -static handler *heap_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root); - -handlerton heap_hton; - -int heap_init() -{ - heap_hton.state= SHOW_OPTION_YES; - heap_hton.db_type= DB_TYPE_HEAP; - heap_hton.create= heap_create_handler; - heap_hton.panic= heap_panic; - heap_hton.flags= HTON_CAN_RECREATE; - return 0; -} - -static handler *heap_create_handler(TABLE_SHARE *table, MEM_ROOT *mem_root) -{ - return new (mem_root) ha_heap(table); -} - - -/***************************************************************************** -** HEAP tables -*****************************************************************************/ - -ha_heap::ha_heap(TABLE_SHARE *table_arg) - :handler(&heap_hton, table_arg), file(0), records_changed(0), - key_stat_version(0) -{} - - -static const char *ha_heap_exts[] = { - NullS -}; - -const char **ha_heap::bas_ext() const -{ - return ha_heap_exts; -} - -/* - Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to - rec_per_key) after 1/HEAP_STATS_UPDATE_THRESHOLD fraction of table records - have been inserted/updated/deleted. delete_all_rows() and table flush cause - immediate update. - - NOTE - hash index statistics must be updated when number of table records changes - from 0 to non-zero value and vice versa. Otherwise records_in_range may - erroneously return 0 and 'range' may miss records. -*/ -#define HEAP_STATS_UPDATE_THRESHOLD 10 - -int ha_heap::open(const char *name, int mode, uint test_if_locked) -{ - if (!(file= heap_open(name, mode)) && my_errno == ENOENT) - { - HA_CREATE_INFO create_info; - bzero(&create_info, sizeof(create_info)); - if (!create(name, table, &create_info)) - { - file= heap_open(name, mode); - implicit_emptied= 1; - } - } - ref_length= sizeof(HEAP_PTR); - if (file) - { - /* Initialize variables for the opened table */ - set_keys_for_scanning(); - /* - We cannot run update_key_stats() here because we do not have a - lock on the table. The 'records' count might just be changed - temporarily at this moment and we might get wrong statistics (Bug - #10178). Instead we request for update. This will be done in - ha_heap::info(), which is always called before key statistics are - used. - */ - key_stat_version= file->s->key_stat_version-1; - } - return (file ? 0 : 1); -} - -int ha_heap::close(void) -{ - return heap_close(file); -} - - -/* - Compute which keys to use for scanning - - SYNOPSIS - set_keys_for_scanning() - no parameter - - DESCRIPTION - Set the bitmap btree_keys, which is used when the upper layers ask - which keys to use for scanning. For each btree index the - corresponding bit is set. - - RETURN - void -*/ - -void ha_heap::set_keys_for_scanning(void) -{ - btree_keys.clear_all(); - for (uint i= 0 ; i < table->s->keys ; i++) - { - if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE) - btree_keys.set_bit(i); - } -} - - -void ha_heap::update_key_stats() -{ - for (uint i= 0; i < table->s->keys; i++) - { - KEY *key=table->key_info+i; - if (!key->rec_per_key) - continue; - if (key->algorithm != HA_KEY_ALG_BTREE) - { - if (key->flags & HA_NOSAME) - key->rec_per_key[key->key_parts-1]= 1; - else - { - ha_rows hash_buckets= file->s->keydef[i].hash_buckets; - uint no_records= hash_buckets ? file->s->records/hash_buckets : 2; - if (no_records < 2) - no_records= 2; - key->rec_per_key[key->key_parts-1]= no_records; - } - } - } - records_changed= 0; - /* At the end of update_key_stats() we can proudly claim they are OK. */ - key_stat_version= file->s->key_stat_version; -} - - -int ha_heap::write_row(byte * buf) -{ - int res; - statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT) - table->timestamp_field->set_time(); - if (table->next_number_field && buf == table->record[0]) - update_auto_increment(); - res= heap_write(file,buf); - if (!res && (++records_changed*HEAP_STATS_UPDATE_THRESHOLD > - file->s->records)) - { - /* - We can perform this safely since only one writer at the time is - allowed on the table. - */ - file->s->key_stat_version++; - } - return res; -} - -int ha_heap::update_row(const byte * old_data, byte * new_data) -{ - int res; - statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status); - if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE) - table->timestamp_field->set_time(); - res= heap_update(file,old_data,new_data); - if (!res && ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > - file->s->records) - { - /* - We can perform this safely since only one writer at the time is - allowed on the table. - */ - file->s->key_stat_version++; - } - return res; -} - -int ha_heap::delete_row(const byte * buf) -{ - int res; - statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status); - res= heap_delete(file,buf); - if (!res && table->s->tmp_table == NO_TMP_TABLE && - ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records) - { - /* - We can perform this safely since only one writer at the time is - allowed on the table. - */ - file->s->key_stat_version++; - } - return res; -} - -int ha_heap::index_read(byte * buf, const byte * key, uint key_len, - enum ha_rkey_function find_flag) -{ - DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); - int error = heap_rkey(file,buf,active_index, key, key_len, find_flag); - table->status = error ? STATUS_NOT_FOUND : 0; - return error; -} - -int ha_heap::index_read_last(byte *buf, const byte *key, uint key_len) -{ - DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); - int error= heap_rkey(file, buf, active_index, key, key_len, - HA_READ_PREFIX_LAST); - table->status= error ? STATUS_NOT_FOUND : 0; - return error; -} - -int ha_heap::index_read_idx(byte * buf, uint index, const byte * key, - uint key_len, enum ha_rkey_function find_flag) -{ - statistic_increment(table->in_use->status_var.ha_read_key_count, - &LOCK_status); - int error = heap_rkey(file, buf, index, key, key_len, find_flag); - table->status = error ? STATUS_NOT_FOUND : 0; - return error; -} - -int ha_heap::index_next(byte * buf) -{ - DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_next_count, - &LOCK_status); - int error=heap_rnext(file,buf); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -int ha_heap::index_prev(byte * buf) -{ - DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_prev_count, - &LOCK_status); - int error=heap_rprev(file,buf); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -int ha_heap::index_first(byte * buf) -{ - DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_first_count, - &LOCK_status); - int error=heap_rfirst(file, buf, active_index); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -int ha_heap::index_last(byte * buf) -{ - DBUG_ASSERT(inited==INDEX); - statistic_increment(table->in_use->status_var.ha_read_last_count, - &LOCK_status); - int error=heap_rlast(file, buf, active_index); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -int ha_heap::rnd_init(bool scan) -{ - return scan ? heap_scan_init(file) : 0; -} - -int ha_heap::rnd_next(byte *buf) -{ - statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, - &LOCK_status); - int error=heap_scan(file, buf); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -int ha_heap::rnd_pos(byte * buf, byte *pos) -{ - int error; - HEAP_PTR position; - statistic_increment(table->in_use->status_var.ha_read_rnd_count, - &LOCK_status); - memcpy_fixed((char*) &position,pos,sizeof(HEAP_PTR)); - error=heap_rrnd(file, buf, position); - table->status=error ? STATUS_NOT_FOUND: 0; - return error; -} - -void ha_heap::position(const byte *record) -{ - *(HEAP_PTR*) ref= heap_position(file); // Ref is aligned -} - -void ha_heap::info(uint flag) -{ - HEAPINFO info; - (void) heap_info(file,&info,flag); - - errkey= info.errkey; - stats.records = info.records; - stats.deleted = info.deleted; - stats.mean_rec_length=info.reclength; - stats.data_file_length=info.data_length; - stats.index_file_length=info.index_length; - stats.max_data_file_length= info.max_records* info.reclength; - stats.delete_length= info.deleted * info.reclength; - if (flag & HA_STATUS_AUTO) - stats.auto_increment_value= info.auto_increment; - /* - If info() is called for the first time after open(), we will still - have to update the key statistics. Hoping that a table lock is now - in place. - */ - if (key_stat_version != file->s->key_stat_version) - update_key_stats(); -} - - -int ha_heap::extra(enum ha_extra_function operation) -{ - return heap_extra(file,operation); -} - - -int ha_heap::reset() -{ - return heap_reset(file); -} - - -int ha_heap::delete_all_rows() -{ - heap_clear(file); - if (table->s->tmp_table == NO_TMP_TABLE) - { - /* - We can perform this safely since only one writer at the time is - allowed on the table. - */ - file->s->key_stat_version++; - } - return 0; -} - -int ha_heap::external_lock(THD *thd, int lock_type) -{ - return 0; // No external locking -} - - -/* - Disable indexes. - - SYNOPSIS - disable_indexes() - mode mode of operation: - HA_KEY_SWITCH_NONUNIQ disable all non-unique keys - HA_KEY_SWITCH_ALL disable all keys - HA_KEY_SWITCH_NONUNIQ_SAVE dis. non-uni. and make persistent - HA_KEY_SWITCH_ALL_SAVE dis. all keys and make persistent - - DESCRIPTION - Disable indexes and clear keys to use for scanning. - - IMPLEMENTATION - HA_KEY_SWITCH_NONUNIQ is not implemented. - HA_KEY_SWITCH_NONUNIQ_SAVE is not implemented with HEAP. - HA_KEY_SWITCH_ALL_SAVE is not implemented with HEAP. - - RETURN - 0 ok - HA_ERR_WRONG_COMMAND mode not implemented. -*/ - -int ha_heap::disable_indexes(uint mode) -{ - int error; - - if (mode == HA_KEY_SWITCH_ALL) - { - if (!(error= heap_disable_indexes(file))) - set_keys_for_scanning(); - } - else - { - /* mode not implemented */ - error= HA_ERR_WRONG_COMMAND; - } - return error; -} - - -/* - Enable indexes. - - SYNOPSIS - enable_indexes() - mode mode of operation: - HA_KEY_SWITCH_NONUNIQ enable all non-unique keys - HA_KEY_SWITCH_ALL enable all keys - HA_KEY_SWITCH_NONUNIQ_SAVE en. non-uni. and make persistent - HA_KEY_SWITCH_ALL_SAVE en. all keys and make persistent - - DESCRIPTION - Enable indexes and set keys to use for scanning. - The indexes might have been disabled by disable_index() before. - The function works only if both data and indexes are empty, - since the heap storage engine cannot repair the indexes. - To be sure, call handler::delete_all_rows() before. - - IMPLEMENTATION - HA_KEY_SWITCH_NONUNIQ is not implemented. - HA_KEY_SWITCH_NONUNIQ_SAVE is not implemented with HEAP. - HA_KEY_SWITCH_ALL_SAVE is not implemented with HEAP. - - RETURN - 0 ok - HA_ERR_CRASHED data or index is non-empty. Delete all rows and retry. - HA_ERR_WRONG_COMMAND mode not implemented. -*/ - -int ha_heap::enable_indexes(uint mode) -{ - int error; - - if (mode == HA_KEY_SWITCH_ALL) - { - if (!(error= heap_enable_indexes(file))) - set_keys_for_scanning(); - } - else - { - /* mode not implemented */ - error= HA_ERR_WRONG_COMMAND; - } - return error; -} - - -/* - Test if indexes are disabled. - - SYNOPSIS - indexes_are_disabled() - no parameters - - RETURN - 0 indexes are not disabled - 1 all indexes are disabled - [2 non-unique indexes are disabled - NOT YET IMPLEMENTED] -*/ - -int ha_heap::indexes_are_disabled(void) -{ - return heap_indexes_are_disabled(file); -} - -THR_LOCK_DATA **ha_heap::store_lock(THD *thd, - THR_LOCK_DATA **to, - enum thr_lock_type lock_type) -{ - if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK) - file->lock.type=lock_type; - *to++= &file->lock; - return to; -} - -/* - We have to ignore ENOENT entries as the HEAP table is created on open and - not when doing a CREATE on the table. -*/ - -int ha_heap::delete_table(const char *name) -{ - int error= heap_delete_table(name); - return error == ENOENT ? 0 : error; -} - - -void ha_heap::drop_table(const char *name) -{ - heap_drop_table(file); - close(); -} - - -int ha_heap::rename_table(const char * from, const char * to) -{ - return heap_rename(from,to); -} - - -ha_rows ha_heap::records_in_range(uint inx, key_range *min_key, - key_range *max_key) -{ - KEY *key=table->key_info+inx; - if (key->algorithm == HA_KEY_ALG_BTREE) - return hp_rb_records_in_range(file, inx, min_key, max_key); - - if (!min_key || !max_key || - min_key->length != max_key->length || - min_key->length != key->key_length || - min_key->flag != HA_READ_KEY_EXACT || - max_key->flag != HA_READ_AFTER_KEY) - return HA_POS_ERROR; // Can only use exact keys - - if (stats.records <= 1) - return stats.records; - - /* Assert that info() did run. We need current statistics here. */ - DBUG_ASSERT(key_stat_version == file->s->key_stat_version); - return key->rec_per_key[key->key_parts-1]; -} - - -int ha_heap::create(const char *name, TABLE *table_arg, - HA_CREATE_INFO *create_info) -{ - uint key, parts, mem_per_row= 0, keys= table_arg->s->keys; - uint auto_key= 0, auto_key_type= 0; - ha_rows max_rows; - HP_KEYDEF *keydef; - HA_KEYSEG *seg; - int error; - TABLE_SHARE *share= table_arg->s; - bool found_real_auto_increment= 0; - - for (key= parts= 0; key < keys; key++) - parts+= table_arg->key_info[key].key_parts; - - if (!(keydef= (HP_KEYDEF*) my_malloc(keys * sizeof(HP_KEYDEF) + - parts * sizeof(HA_KEYSEG), - MYF(MY_WME)))) - return my_errno; - seg= my_reinterpret_cast(HA_KEYSEG*) (keydef + keys); - for (key= 0; key < keys; key++) - { - KEY *pos= table_arg->key_info+key; - KEY_PART_INFO *key_part= pos->key_part; - KEY_PART_INFO *key_part_end= key_part + pos->key_parts; - - keydef[key].keysegs= (uint) pos->key_parts; - keydef[key].flag= (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL)); - keydef[key].seg= seg; - - switch (pos->algorithm) { - case HA_KEY_ALG_UNDEF: - case HA_KEY_ALG_HASH: - keydef[key].algorithm= HA_KEY_ALG_HASH; - mem_per_row+= sizeof(char*) * 2; // = sizeof(HASH_INFO) - break; - case HA_KEY_ALG_BTREE: - keydef[key].algorithm= HA_KEY_ALG_BTREE; - mem_per_row+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*); - break; - default: - DBUG_ASSERT(0); // cannot happen - } - - for (; key_part != key_part_end; key_part++, seg++) - { - Field *field= key_part->field; - - if (pos->algorithm == HA_KEY_ALG_BTREE) - seg->type= field->key_type(); - else - { - if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT && - seg->type != HA_KEYTYPE_VARTEXT1 && - seg->type != HA_KEYTYPE_VARTEXT2 && - seg->type != HA_KEYTYPE_VARBINARY1 && - seg->type != HA_KEYTYPE_VARBINARY2) - seg->type= HA_KEYTYPE_BINARY; - } - seg->start= (uint) key_part->offset; - seg->length= (uint) key_part->length; - seg->flag= key_part->key_part_flag; - - seg->charset= field->charset(); - if (field->null_ptr) - { - seg->null_bit= field->null_bit; - seg->null_pos= (uint) (field->null_ptr - (uchar*) table_arg->record[0]); - } - else - { - seg->null_bit= 0; - seg->null_pos= 0; - } - if (field->flags & AUTO_INCREMENT_FLAG && - table_arg->found_next_number_field && - key == share->next_number_index) - { - /* - Store key number and type for found auto_increment key - We have to store type as seg->type can differ from it - */ - auto_key= key+ 1; - auto_key_type= field->key_type(); - } - } - } - mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*)); - max_rows = (ha_rows) (table_arg->in_use->variables.max_heap_table_size / - mem_per_row); - if (table_arg->found_next_number_field) - { - keydef[share->next_number_index].flag|= HA_AUTO_KEY; - found_real_auto_increment= share->next_number_key_offset == 0; - } - HP_CREATE_INFO hp_create_info; - hp_create_info.auto_key= auto_key; - hp_create_info.auto_key_type= auto_key_type; - hp_create_info.auto_increment= (create_info->auto_increment_value ? - create_info->auto_increment_value - 1 : 0); - hp_create_info.max_table_size=current_thd->variables.max_heap_table_size; - hp_create_info.with_auto_increment= found_real_auto_increment; - max_rows = (ha_rows) (hp_create_info.max_table_size / mem_per_row); - error= heap_create(name, - keys, keydef, share->reclength, - (ulong) ((share->max_rows < max_rows && - share->max_rows) ? - share->max_rows : max_rows), - (ulong) share->min_rows, &hp_create_info); - my_free((gptr) keydef, MYF(0)); - if (file) - info(HA_STATUS_NO_LOCK | HA_STATUS_CONST | HA_STATUS_VARIABLE); - return (error); -} - - -void ha_heap::update_create_info(HA_CREATE_INFO *create_info) -{ - table->file->info(HA_STATUS_AUTO); - if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) - create_info->auto_increment_value= stats.auto_increment_value; -} - -void ha_heap::get_auto_increment(ulonglong offset, ulonglong increment, - ulonglong nb_desired_values, - ulonglong *first_value, - ulonglong *nb_reserved_values) -{ - ha_heap::info(HA_STATUS_AUTO); - *first_value= stats.auto_increment_value; - /* such table has only table-level locking so reserves up to +inf */ - *nb_reserved_values= ULONGLONG_MAX; -} - - -bool ha_heap::check_if_incompatible_data(HA_CREATE_INFO *info, - uint table_changes) -{ - /* Check that auto_increment value was not changed */ - if ((table_changes != IS_EQUAL_YES && - info->used_fields & HA_CREATE_USED_AUTO) && - info->auto_increment_value != 0) - return COMPATIBLE_DATA_NO; - return COMPATIBLE_DATA_YES; -} - -struct st_mysql_storage_engine heap_storage_engine= -{ MYSQL_HANDLERTON_INTERFACE_VERSION, &heap_hton}; - -mysql_declare_plugin(heap) -{ - MYSQL_STORAGE_ENGINE_PLUGIN, - &heap_storage_engine, - "MEMORY", - "MySQL AB", - "Hash based, stored in memory, useful for temporary tables", - heap_init, - NULL, - 0x0100, /* 1.0 */ - 0 -} -mysql_declare_plugin_end; |