12
12
You should have received a copy of the GNU General Public License
13
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
16
16
#include "heap_priv.h"
17
17
#include <drizzled/error.h>
60
60
hp_panic(HA_PANIC_CLOSE);
63
virtual Cursor *create(Table &table)
63
virtual Cursor *create(TableShare &table)
65
65
return new ha_heap(*this, table);
93
93
const TableIdentifier &identifier,
94
94
message::Table &table_message);
96
/* Temp only engine, so do not return values. */
97
void doGetTableNames(CachedDirectory &, const SchemaIdentifier& , set<string>&) { };
96
99
uint32_t max_supported_keys() const { return MAX_KEY; }
97
100
uint32_t max_supported_key_part_length() const { return MAX_KEY_LENGTH; }
99
uint32_t index_flags(enum ha_key_alg ) const
102
uint32_t index_flags(enum ha_key_alg algorithm) const
101
return ( HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR);
104
return ((algorithm == HA_KEY_ALG_BTREE) ?
109
HA_ONLY_WHOLE_INDEX |
110
HA_KEY_SCAN_NOT_ROR);
104
113
bool doDoesTableExist(Session& session, const TableIdentifier &identifier);
105
114
void doGetTableIdentifiers(CachedDirectory &directory,
106
115
const SchemaIdentifier &schema_identifier,
107
TableIdentifier::vector &set_of_identifiers);
116
TableIdentifiers &set_of_identifiers);
110
119
void HeapEngine::doGetTableIdentifiers(CachedDirectory&,
111
120
const SchemaIdentifier&,
112
TableIdentifier::vector&)
116
125
bool HeapEngine::doDoesTableExist(Session& session, const TableIdentifier &identifier)
118
return session.getMessageCache().doesTableMessageExist(identifier);
127
return session.doesTableMessageExist(identifier);
121
130
int HeapEngine::doGetTableDefinition(Session &session,
122
131
const TableIdentifier &identifier,
123
132
message::Table &table_proto)
125
if (session.getMessageCache().getTableMessage(identifier, table_proto))
134
if (session.getTableMessage(identifier, table_proto))
134
143
int HeapEngine::doDropTable(Session &session, const TableIdentifier &identifier)
136
session.getMessageCache().removeTableMessage(identifier);
145
session.removeTableMessage(identifier);
138
147
int error= heap_delete_table(identifier.getPath().c_str());
158
167
*****************************************************************************/
160
169
ha_heap::ha_heap(plugin::StorageEngine &engine_arg,
170
TableShare &table_arg)
162
171
:Cursor(engine_arg, table_arg), file(0), records_changed(0), key_stat_version(0),
163
172
internal_table(0)
177
186
#define MEMORY_STATS_UPDATE_THRESHOLD 10
179
int ha_heap::doOpen(const drizzled::TableIdentifier &identifier, int mode, uint32_t test_if_locked)
188
int ha_heap::open(const char *name, int mode, uint32_t test_if_locked)
181
if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(identifier.getPath().c_str(), mode)) && errno == ENOENT))
190
if ((test_if_locked & HA_OPEN_INTERNAL_TABLE) || (!(file= heap_open(name, mode)) && errno == ENOENT))
183
192
internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
185
194
HP_SHARE *internal_share= NULL;
186
195
message::Table create_proto;
188
if (not heap_storage_engine->heap_create_table(getTable()->in_use,
189
identifier.getPath().c_str(),
197
if (!heap_storage_engine->heap_create_table(table->in_use, name, table,
195
202
file= internal_table ?
196
203
heap_open_from_share(internal_share, mode) :
241
248
Cursor *ha_heap::clone(memory::Root *)
243
Cursor *new_handler= getTable()->getMutableShare()->db_type()->getCursor(*getTable());
244
TableIdentifier identifier(getTable()->getShare()->getSchemaName(),
245
getTable()->getShare()->getTableName(),
246
getTable()->getShare()->getPath());
250
Cursor *new_handler= table->getMutableShare()->db_type()->getCursor(*(table->getMutableShare()));
251
TableIdentifier identifier(table->getShare()->getSchemaName(),
252
table->getShare()->getTableName(),
253
table->getShare()->getPath());
248
if (new_handler && !new_handler->ha_open(identifier, getTable()->db_stat,
255
if (new_handler && !new_handler->ha_open(identifier, table, file->getShare()->name.c_str(), table->db_stat,
249
256
HA_OPEN_IGNORE_IF_LOCKED))
250
257
return new_handler;
255
const char *ha_heap::index_type(uint32_t )
262
const char *ha_heap::index_type(uint32_t inx)
264
return ((table_share->getKeyInfo(inx).algorithm == HA_KEY_ALG_BTREE) ?
277
285
void ha_heap::set_keys_for_scanning(void)
288
for (uint32_t i= 0 ; i < table->getShare()->sizeKeys() ; i++)
290
if (table->key_info[i].algorithm == HA_KEY_ALG_BTREE)
282
296
void ha_heap::update_key_stats()
284
for (uint32_t i= 0; i < getTable()->getShare()->sizeKeys(); i++)
298
for (uint32_t i= 0; i < table->getShare()->sizeKeys(); i++)
286
KeyInfo *key= &getTable()->key_info[i];
300
KeyInfo *key= &table->key_info[i];
288
301
if (!key->rec_per_key)
303
if (key->algorithm != HA_KEY_ALG_BTREE)
292
305
if (key->flags & HA_NOSAME)
293
306
key->rec_per_key[key->key_parts-1]= 1;
310
323
int ha_heap::doInsertRecord(unsigned char * buf)
313
if (getTable()->next_number_field && buf == getTable()->getInsertRecord())
326
if (table->next_number_field && buf == table->getInsertRecord())
315
328
if ((res= update_auto_increment()))
352
365
res= heap_delete(file,buf);
353
if (!res && getTable()->getShare()->getType() == message::Table::STANDARD &&
366
if (!res && table->getShare()->getType() == message::Table::STANDARD &&
354
367
++records_changed*MEMORY_STATS_UPDATE_THRESHOLD > file->getShare()->records)
369
382
assert(inited==INDEX);
370
383
ha_statistic_increment(&system_status_var::ha_read_key_count);
371
384
int error = heap_rkey(file,buf,active_index, key, keypart_map, find_flag);
372
getTable()->status = error ? STATUS_NOT_FOUND : 0;
385
table->status = error ? STATUS_NOT_FOUND : 0;
380
393
ha_statistic_increment(&system_status_var::ha_read_key_count);
381
394
int error= heap_rkey(file, buf, active_index, key, keypart_map,
382
395
HA_READ_PREFIX_LAST);
383
getTable()->status= error ? STATUS_NOT_FOUND : 0;
396
table->status= error ? STATUS_NOT_FOUND : 0;
391
404
ha_statistic_increment(&system_status_var::ha_read_key_count);
392
405
int error = heap_rkey(file, buf, index, key, keypart_map, find_flag);
393
getTable()->status = error ? STATUS_NOT_FOUND : 0;
406
table->status = error ? STATUS_NOT_FOUND : 0;
399
412
assert(inited==INDEX);
400
413
ha_statistic_increment(&system_status_var::ha_read_next_count);
401
414
int error=heap_rnext(file,buf);
402
getTable()->status=error ? STATUS_NOT_FOUND: 0;
415
table->status=error ? STATUS_NOT_FOUND: 0;
408
421
assert(inited==INDEX);
409
422
ha_statistic_increment(&system_status_var::ha_read_prev_count);
410
423
int error=heap_rprev(file,buf);
411
getTable()->status=error ? STATUS_NOT_FOUND: 0;
424
table->status=error ? STATUS_NOT_FOUND: 0;
417
430
assert(inited==INDEX);
418
431
ha_statistic_increment(&system_status_var::ha_read_first_count);
419
432
int error=heap_rfirst(file, buf, active_index);
420
getTable()->status=error ? STATUS_NOT_FOUND: 0;
433
table->status=error ? STATUS_NOT_FOUND: 0;
426
439
assert(inited==INDEX);
427
440
ha_statistic_increment(&system_status_var::ha_read_last_count);
428
441
int error=heap_rlast(file, buf, active_index);
429
getTable()->status=error ? STATUS_NOT_FOUND: 0;
442
table->status=error ? STATUS_NOT_FOUND: 0;
440
453
ha_statistic_increment(&system_status_var::ha_read_rnd_next_count);
441
454
int error=heap_scan(file, buf);
442
getTable()->status=error ? STATUS_NOT_FOUND: 0;
455
table->status=error ? STATUS_NOT_FOUND: 0;
450
463
ha_statistic_increment(&system_status_var::ha_read_rnd_count);
451
464
memcpy(&heap_position, pos, sizeof(HEAP_PTR));
452
465
error=heap_rrnd(file, buf, heap_position);
453
getTable()->status=error ? STATUS_NOT_FOUND: 0;
466
table->status=error ? STATUS_NOT_FOUND: 0;
499
512
int ha_heap::delete_all_rows()
501
514
heap_clear(file);
502
if (getTable()->getShare()->getType() == message::Table::STANDARD)
515
if (table->getShare()->getType() == message::Table::STANDARD)
505
518
We can perform this safely since only one writer at the time is
627
640
int HeapEngine::doRenameTable(Session &session, const TableIdentifier &from, const TableIdentifier &to)
629
session.getMessageCache().renameTableMessage(from, to);
642
session.renameTableMessage(from, to);
630
643
return heap_rename(from.getPath().c_str(), to.getPath().c_str());
634
647
ha_rows ha_heap::records_in_range(uint32_t inx, key_range *min_key,
635
648
key_range *max_key)
637
KeyInfo *key= &getTable()->key_info[inx];
650
KeyInfo *key= &table->key_info[inx];
651
if (key->algorithm == HA_KEY_ALG_BTREE)
652
return hp_rb_records_in_range(file, inx, min_key, max_key);
639
654
if (!min_key || !max_key ||
640
655
min_key->length != max_key->length ||
685
700
uint32_t auto_key= 0, auto_key_type= 0;
686
701
uint32_t max_key_fieldnr = 0, key_part_size = 0, next_field_pos = 0;
687
702
uint32_t column_count= table_arg->getShare()->sizeFields();
703
std::vector<HP_COLUMNDEF> columndef;
688
704
std::vector<HP_KEYDEF> keydef;
705
char buff[FN_REFLEN];
690
707
bool found_real_auto_increment= 0;
699
716
if (num_rows > UINT32_MAX)
719
columndef.resize(column_count);
721
for (uint32_t column_idx= 0; column_idx < column_count; column_idx++)
723
Field* field= *(table_arg->getFields() + column_idx);
724
HP_COLUMNDEF* column= &columndef[column_idx];
725
column->type= (uint16_t)field->type();
726
column->length= field->pack_length();
727
column->offset= field->offset(field->getTable()->getInsertRecord());
731
column->null_bit= field->null_bit;
732
column->null_pos= (uint) (field->null_ptr - (unsigned char*) table_arg->getInsertRecord());
740
if (field->type() == DRIZZLE_TYPE_VARCHAR)
742
column->length_bytes= (uint8_t)(((Field_varstring*)field)->length_bytes);
746
column->length_bytes= 0;
702
750
for (key= parts= 0; key < keys; key++)
703
751
parts+= table_arg->key_info[key].key_parts;
717
765
keydef[key].flag= (pos->flags & (HA_NOSAME | HA_NULL_ARE_EQUAL));
718
766
keydef[key].seg= seg;
720
mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
768
switch (pos->algorithm) {
769
case HA_KEY_ALG_UNDEF:
770
case HA_KEY_ALG_HASH:
771
keydef[key].algorithm= HA_KEY_ALG_HASH;
772
mem_per_row_keys+= sizeof(char*) * 2; // = sizeof(HASH_INFO)
774
case HA_KEY_ALG_BTREE:
775
keydef[key].algorithm= HA_KEY_ALG_BTREE;
776
mem_per_row_keys+=sizeof(TREE_ELEMENT)+pos->key_length+sizeof(char*);
779
assert(0); // cannot happen
722
782
for (; key_part != key_part_end; key_part++, seg++)
724
784
Field *field= key_part->field;
786
if (pos->algorithm == HA_KEY_ALG_BTREE)
788
seg->type= field->key_type();
727
792
if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
728
793
seg->type != HA_KEYTYPE_VARTEXT1 &&
738
803
next_field_pos= seg->start + seg->length;
739
804
if (field->type() == DRIZZLE_TYPE_VARCHAR)
741
next_field_pos+= (uint8_t)(((Field_varstring*)field)->pack_length_no_ptr());
806
next_field_pos+= (uint8_t)(((Field_varstring*)field)->length_bytes);
744
809
if (next_field_pos > key_part_size) {
770
835
auto_key= key+ 1;
771
836
auto_key_type= field->key_type();
773
if ((uint)field->position() + 1 > max_key_fieldnr)
838
if ((uint)field->field_index + 1 > max_key_fieldnr)
775
840
/* Do not use seg->fieldnr as it's not reliable in case of temp tables */
776
max_key_fieldnr= field->position() + 1;
841
max_key_fieldnr= field->field_index + 1;
800
865
hp_create_info.with_auto_increment= found_real_auto_increment;
801
866
hp_create_info.internal_table= internal_table;
802
867
hp_create_info.max_chunk_size= table_arg->getShare()->block_size;
868
hp_create_info.is_dynamic= false;
804
error= heap_create(table_name,
808
table_arg->getShare()->getRecordLength(), mem_per_row_keys,
809
static_cast<uint32_t>(num_rows), /* We check for overflow above, so cast is fine here. */
811
&hp_create_info, internal_share);
870
error= heap_create(internal::fn_format(buff,table_name,"","",
871
MY_REPLACE_EXT|MY_UNPACK_FILENAME),
873
column_count, &columndef[0],
874
max_key_fieldnr, key_part_size,
875
table_arg->getShare()->getRecordLength(), mem_per_row_keys,
876
static_cast<uint32_t>(num_rows), /* We check for overflow above, so cast is fine here. */
878
&hp_create_info, internal_share);