Commit 92aafebd authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-11605 Assertion `(longlong) thd->status_var.local_memory_used >= 0 ||...

MDEV-11605 Assertion `(longlong) thd->status_var.local_memory_used >= 0 || !debug_assert_on_not_freed_memory' failed in my_malloc_size_cb_func

MyISAM in compute_vcols() - which is used only in mi_check code -
was computing indexed vcols into an internally allocated buffer
(not record[0]) and the buffer was calculated to be long enough to fit
every keyseg (a keyseg knows where its value in a record buffer is
and the length of the value).

This logic didn' work for prefix keys, because the keyseg length is the
length of a prefix, but the record buffer needs to fit the complete
value of a vcol. In this bug MyISAM was writing a 2K varchar
into a buffer too short.

Also it didn't work for repair-with-keycache, because that code
recalculats all vcols, not only indexed ones.

So, the buffer size (MYISAM_SHARE::vreclength) should include all
vcols' full lengths. But it was calculated in mi_open and low-level
MyISAM code has no knowledge of vcols.

As a fix we now recalculate MYISAM_SHARE::vreclength in
ha_myisam::setup_vcols_for_repair() which is always called
before compute_vcols().
parent f63007a3
This diff is collapsed.
This diff is collapsed.
...@@ -892,14 +892,27 @@ int ha_myisam::write_row(uchar *buf) ...@@ -892,14 +892,27 @@ int ha_myisam::write_row(uchar *buf)
void ha_myisam::setup_vcols_for_repair(HA_CHECK *param) void ha_myisam::setup_vcols_for_repair(HA_CHECK *param)
{ {
if (file->s->base.reclength < file->s->vreclength) DBUG_ASSERT(file->s->base.reclength <= file->s->vreclength);
if (!table->vfield)
return;
if (file->s->base.reclength == file->s->vreclength)
{ {
param->fix_record= compute_vcols; bool indexed_vcols= false;
table->use_all_columns(); ulong new_vreclength= file->s->vreclength;
table->vcol_set= &table->s->all_set; for (Field **vf= table->vfield; *vf; vf++)
{
uint vf_end= (*vf)->offset(table->record[0]) + (*vf)->pack_length_in_rec();
set_if_bigger(new_vreclength, vf_end);
indexed_vcols|= (*vf)->flags & PART_KEY_FLAG;
}
if (!indexed_vcols)
return;
file->s->vreclength= new_vreclength;
} }
else param->fix_record= compute_vcols;
DBUG_ASSERT(file->s->base.reclength == file->s->vreclength); table->use_all_columns();
table->vcol_set= &table->s->all_set;
} }
void ha_myisam::restore_vcos_after_repair() void ha_myisam::restore_vcos_after_repair()
......
...@@ -336,7 +336,6 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -336,7 +336,6 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
for (i=0 ; i < keys ; i++) for (i=0 ; i < keys ; i++)
{ {
MI_KEYDEF *keyinfo= share->keyinfo + i; MI_KEYDEF *keyinfo= share->keyinfo + i;
uint sp_segs;
keyinfo->share= share; keyinfo->share= share;
disk_pos=mi_keydef_read(disk_pos, keyinfo); disk_pos=mi_keydef_read(disk_pos, keyinfo);
disk_pos_assert(disk_pos + keyinfo->keysegs * HA_KEYSEG_SIZE, end_pos); disk_pos_assert(disk_pos + keyinfo->keysegs * HA_KEYSEG_SIZE, end_pos);
...@@ -344,11 +343,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -344,11 +343,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
have_rtree=1; have_rtree=1;
set_if_smaller(share->blocksize, keyinfo->block_length); set_if_smaller(share->blocksize, keyinfo->block_length);
keyinfo->seg= pos; keyinfo->seg= pos;
if (keyinfo->flag & HA_SPATIAL) for (j=0 ; j < keyinfo->keysegs; j++,pos++)
sp_segs= 2*SPDIMS;
else
sp_segs= 0;
for (j=0 ; j < keyinfo->keysegs; j++, pos++)
{ {
disk_pos=mi_keyseg_read(disk_pos, pos); disk_pos=mi_keyseg_read(disk_pos, pos);
if (pos->flag & HA_BLOB_PART && if (pos->flag & HA_BLOB_PART &&
...@@ -372,18 +367,11 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags) ...@@ -372,18 +367,11 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
} }
else if (pos->type == HA_KEYTYPE_BINARY) else if (pos->type == HA_KEYTYPE_BINARY)
pos->charset= &my_charset_bin; pos->charset= &my_charset_bin;
if (j < keyinfo->keysegs - sp_segs)
{
uint real_length= pos->flag & HA_BLOB_PART ? pos->bit_start
: pos->length;
if (pos->type == HA_KEYTYPE_BIT && pos->bit_length)
real_length--;
set_if_bigger(share->vreclength, pos->start + real_length);
}
} }
if (keyinfo->flag & HA_SPATIAL) if (keyinfo->flag & HA_SPATIAL)
{ {
#ifdef HAVE_SPATIAL #ifdef HAVE_SPATIAL
uint sp_segs= SPDIMS*2;
keyinfo->seg= pos - sp_segs; keyinfo->seg= pos - sp_segs;
DBUG_ASSERT(keyinfo->keysegs == sp_segs + 1); DBUG_ASSERT(keyinfo->keysegs == sp_segs + 1);
keyinfo->keysegs= sp_segs; keyinfo->keysegs= sp_segs;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment