mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
MDEV-6838: Using too big key for internal temp tables
This bug manifests due to wrong computation and evaluation of keyinfo->key_length. The issues were: * Using table->file->max_key_length() as an absolute value that must not be reached for a key, while it represents the maximum number of bytes possible for a table key. * Incorrectly computing the keyinfo->key_length size during KEY_PART_INFO creation. The metadata information regarding the key such the field length (for strings) was added twice.
This commit is contained in:
34
sql/table.cc
34
sql/table.cc
@@ -5968,18 +5968,32 @@ bool TABLE::alloc_keys(uint key_count)
|
||||
}
|
||||
|
||||
|
||||
void TABLE::create_key_part_by_field(KEY *keyinfo,
|
||||
KEY_PART_INFO *key_part_info,
|
||||
/**
|
||||
@brief
|
||||
Populate a KEY_PART_INFO structure with the data related to a field entry.
|
||||
|
||||
@param key_part_info The structure to fill.
|
||||
@param field The field entry that represents the key part.
|
||||
@param fleldnr The number of the field, count starting from 1.
|
||||
|
||||
TODO: This method does not make use of any table specific fields. It
|
||||
could be refactored to act as a constructor for KEY_PART_INFO instead.
|
||||
*/
|
||||
|
||||
void TABLE::create_key_part_by_field(KEY_PART_INFO *key_part_info,
|
||||
Field *field, uint fieldnr)
|
||||
{
|
||||
{
|
||||
key_part_info->null_bit= field->null_bit;
|
||||
key_part_info->null_offset= (uint) (field->null_ptr -
|
||||
(uchar*) record[0]);
|
||||
key_part_info->field= field;
|
||||
key_part_info->fieldnr= fieldnr;
|
||||
key_part_info->offset= field->offset(record[0]);
|
||||
key_part_info->length= (uint16) field->pack_length();
|
||||
keyinfo->key_length+= key_part_info->length;
|
||||
/*
|
||||
field->key_length() accounts for the raw length of the field, excluding
|
||||
any metadata such as length of field or the NULL flag.
|
||||
*/
|
||||
key_part_info->length= (uint16) field->key_length();
|
||||
key_part_info->key_part_flag= 0;
|
||||
/* TODO:
|
||||
The below method of computing the key format length of the
|
||||
@@ -5991,17 +6005,20 @@ void TABLE::create_key_part_by_field(KEY *keyinfo,
|
||||
*/
|
||||
key_part_info->store_length= key_part_info->length;
|
||||
|
||||
/*
|
||||
The total store length of the key part is the raw length of the field +
|
||||
any metadata information, such as its length for strings and/or the null
|
||||
flag.
|
||||
*/
|
||||
if (field->real_maybe_null())
|
||||
{
|
||||
key_part_info->store_length+= HA_KEY_NULL_LENGTH;
|
||||
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
|
||||
}
|
||||
if (field->type() == MYSQL_TYPE_BLOB ||
|
||||
field->type() == MYSQL_TYPE_GEOMETRY ||
|
||||
field->real_type() == MYSQL_TYPE_VARCHAR)
|
||||
{
|
||||
key_part_info->store_length+= HA_KEY_BLOB_LENGTH;
|
||||
keyinfo->key_length+= HA_KEY_BLOB_LENGTH; // ???
|
||||
key_part_info->key_part_flag|=
|
||||
field->type() == MYSQL_TYPE_BLOB ? HA_BLOB_PART: HA_VAR_LENGTH_PART;
|
||||
}
|
||||
@@ -6124,7 +6141,8 @@ bool TABLE::add_tmp_key(uint key, uint key_parts,
|
||||
if (key_start)
|
||||
(*reg_field)->key_start.set_bit(key);
|
||||
(*reg_field)->part_of_key.set_bit(key);
|
||||
create_key_part_by_field(keyinfo, key_part_info, *reg_field, fld_idx+1);
|
||||
create_key_part_by_field(key_part_info, *reg_field, fld_idx+1);
|
||||
keyinfo->key_length += key_part_info->store_length;
|
||||
(*reg_field)->flags|= PART_KEY_FLAG;
|
||||
key_start= FALSE;
|
||||
key_part_info++;
|
||||
|
Reference in New Issue
Block a user