Bug#22351 - handler::index_next_same() call to key_cmp_if_same() uses

            the wrong buffer

handler::index_next_same() did not take into account that the
internally called function key_cmp_if_same() uses the fixed
buffer table->record[0] for key comparison instead of the
buffer provided by the caller of handler::index_next_same().

Added code to temporarily redirect table->record[0] and the fields
used for the key to the record buffer provided by the caller of
handler::index_next_same().

The test case is in partition.test already.
parent c08ffb6b
...@@ -2522,15 +2522,56 @@ int ha_enable_transaction(THD *thd, bool on) ...@@ -2522,15 +2522,56 @@ int ha_enable_transaction(THD *thd, bool on)
int handler::index_next_same(uchar *buf, const uchar *key, uint keylen) int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
{ {
int error; int error;
DBUG_ENTER("index_next_same");
if (!(error=index_next(buf))) if (!(error=index_next(buf)))
{ {
my_ptrdiff_t ptrdiff= buf - table->record[0];
uchar *save_record_0;
KEY *key_info;
KEY_PART_INFO *key_part;
KEY_PART_INFO *key_part_end;
LINT_INIT(save_record_0);
LINT_INIT(key_info);
LINT_INIT(key_part);
LINT_INIT(key_part_end);
/*
key_cmp_if_same() compares table->record[0] against 'key'.
In parts it uses table->record[0] directly, in parts it uses
field objects with their local pointers into table->record[0].
If 'buf' is distinct from table->record[0], we need to move
all record references. This is table->record[0] itself and
the field pointers of the fields used in this key.
*/
if (ptrdiff)
{
save_record_0= table->record[0];
table->record[0]= buf;
key_info= table->key_info + active_index;
key_part= key_info->key_part;
key_part_end= key_part + key_info->key_parts;
for (; key_part < key_part_end; key_part++)
{
DBUG_ASSERT(key_part->field);
key_part->field->move_field_offset(ptrdiff);
}
}
if (key_cmp_if_same(table, key, active_index, keylen)) if (key_cmp_if_same(table, key, active_index, keylen))
{ {
table->status=STATUS_NOT_FOUND; table->status=STATUS_NOT_FOUND;
error=HA_ERR_END_OF_FILE; error=HA_ERR_END_OF_FILE;
} }
/* Move back if necessary. */
if (ptrdiff)
{
table->record[0]= save_record_0;
for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
key_part->field->move_field_offset(-ptrdiff);
}
} }
return error; DBUG_RETURN(error);
} }
......
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