bug: ha_heap was unilaterally increasing reclength

proper fix replacing the hack from b80fa4000d6

don't confuse length of the data area (reclength) with the
offset to the "deleted" mark.
This commit is contained in:
Sergei Golubchik 2018-01-25 14:25:48 +01:00
parent 7a63ffab71
commit 7c6cf7fefe
9 changed files with 15 additions and 21 deletions

View File

@ -144,6 +144,7 @@ typedef struct st_heap_share
uint key_version; /* Updated on key change */
uint file_version; /* Update on clear */
uint reclength; /* Length of one record */
uint visible; /* Offset to the visible/deleted mark */
uint changed;
uint keys,max_key_length;
uint currently_disabled_keys; /* saved value from "keys" when disabled */

View File

@ -79,7 +79,7 @@ int heap_check_heap(HP_INFO *info, my_bool print_status)
}
hp_find_record(info,pos);
if (!info->current_ptr[share->reclength])
if (!info->current_ptr[share->visible])
deleted++;
else
records++;

View File

@ -100,15 +100,6 @@ const char **ha_heap::bas_ext() const
int ha_heap::open(const char *name, int mode, uint test_if_locked)
{
if (table->s->reclength < sizeof (char*))
{
MEM_UNDEFINED(table->s->default_values + table->s->reclength,
sizeof(char*) - table->s->reclength);
table->s->reclength= sizeof(char*);
MEM_UNDEFINED(table->record[0], table->s->reclength);
MEM_UNDEFINED(table->record[1], table->s->reclength);
}
internal_table= test(test_if_locked & HA_OPEN_INTERNAL_TABLE);
if (internal_table || (!(file= heap_open(name, mode)) && my_errno == ENOENT))
{
@ -736,7 +727,7 @@ heap_prepare_hp_create_info(TABLE *table_arg, bool internal_table,
}
}
}
mem_per_row+= MY_ALIGN(share->reclength + 1, sizeof(char*));
mem_per_row+= MY_ALIGN(max(share->reclength, sizeof(char*)) + 1, sizeof(char*));
if (table_arg->found_next_number_field)
{
keydef[share->next_number_index].flag|= HA_AUTO_KEY;

View File

@ -33,6 +33,7 @@ int heap_create(const char *name, HP_CREATE_INFO *create_info,
uint keys= create_info->keys;
ulong min_records= create_info->min_records;
ulong max_records= create_info->max_records;
uint visible_offset;
DBUG_ENTER("heap_create");
if (!create_info->internal_table)
@ -58,9 +59,9 @@ int heap_create(const char *name, HP_CREATE_INFO *create_info,
/*
We have to store sometimes uchar* del_link in records,
so the record length should be at least sizeof(uchar*)
so the visible_offset must be least at sizeof(uchar*)
*/
set_if_bigger(reclength, sizeof (uchar*));
visible_offset= max(reclength, sizeof (char*));
for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
{
@ -152,7 +153,7 @@ int heap_create(const char *name, HP_CREATE_INFO *create_info,
share->keydef= (HP_KEYDEF*) (share + 1);
share->key_stat_version= 1;
keyseg= (HA_KEYSEG*) (share->keydef + keys);
init_block(&share->block, reclength + 1, min_records, max_records);
init_block(&share->block, visible_offset + 1, min_records, max_records);
/* Fix keys */
memcpy(share->keydef, keydef, (size_t) (sizeof(keydef[0]) * keys));
for (i= 0, keyinfo= share->keydef; i < keys; i++, keyinfo++)
@ -192,6 +193,7 @@ int heap_create(const char *name, HP_CREATE_INFO *create_info,
share->max_table_size= create_info->max_table_size;
share->data_length= share->index_length= 0;
share->reclength= reclength;
share->visible= visible_offset;
share->blength= 1;
share->keys= keys;
share->max_key_length= max_length;

View File

@ -45,7 +45,7 @@ int heap_delete(HP_INFO *info, const uchar *record)
info->update=HA_STATE_DELETED;
*((uchar**) pos)=share->del_link;
share->del_link=pos;
pos[share->reclength]=0; /* Record deleted */
pos[share->visible]=0; /* Record deleted */
share->deleted++;
share->key_version++;
#if !defined(DBUG_OFF) && defined(EXTRA_HEAP_DEBUG)

View File

@ -37,7 +37,7 @@ int heap_rrnd(register HP_INFO *info, uchar *record, uchar *pos)
info->update= 0;
DBUG_RETURN(my_errno= HA_ERR_END_OF_FILE);
}
if (!info->current_ptr[share->reclength])
if (!info->current_ptr[share->visible])
{
info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND;
DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);
@ -91,7 +91,7 @@ int heap_rrnd_old(register HP_INFO *info, uchar *record, ulong pos)
hp_find_record(info, pos);
end:
if (!info->current_ptr[share->reclength])
if (!info->current_ptr[share->visible])
{
info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND;
DBUG_RETURN(my_errno=HA_ERR_RECORD_DELETED);

View File

@ -32,7 +32,7 @@ int heap_rsame(register HP_INFO *info, uchar *record, int inx)
DBUG_ENTER("heap_rsame");
test_active(info);
if (info->current_ptr[share->reclength])
if (info->current_ptr[share->visible])
{
if (inx < -1 || inx >= (int) share->keys)
{

View File

@ -62,7 +62,7 @@ int heap_scan(register HP_INFO *info, uchar *record)
}
hp_find_record(info, pos);
}
if (!info->current_ptr[share->reclength])
if (!info->current_ptr[share->visible])
{
DBUG_PRINT("warning",("Found deleted record"));
info->update= HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND;

View File

@ -54,7 +54,7 @@ int heap_write(HP_INFO *info, const uchar *record)
}
memcpy(pos,record,(size_t) share->reclength);
pos[share->reclength]=1; /* Mark record as not deleted */
pos[share->visible]= 1; /* Mark record as not deleted */
if (++share->records == share->blength)
share->blength+= share->blength;
info->s->key_version++;
@ -92,7 +92,7 @@ err:
share->deleted++;
*((uchar**) pos)=share->del_link;
share->del_link=pos;
pos[share->reclength]=0; /* Record deleted */
pos[share->visible]= 0; /* Record deleted */
DBUG_RETURN(my_errno);
} /* heap_write */