diff options
author | unknown <timour@mysql.com> | 2004-08-27 16:37:13 +0300 |
---|---|---|
committer | unknown <timour@mysql.com> | 2004-08-27 16:37:13 +0300 |
commit | d9450332927128073e353f11269eba5f0e4ad941 (patch) | |
tree | 7af5a09192d2042b9d236d1b98634b8b14be9601 /sql/key.cc | |
parent | 7bba8128ed65a5d841679fceb8c6c8dd5cac008c (diff) | |
download | mariadb-git-d9450332927128073e353f11269eba5f0e4ad941.tar.gz |
WL#1724 "Min/Max Optimization for Queries with Group By Clause"
- after-review changes
- merged with the source tree from 204-08-27
mysql-test/r/distinct.result:
Different plans due to group-by optimization.
sql/ha_myisam.cc:
More general interface to key_copy.
sql/handler.cc:
More general interface to key_copy.
sql/item.cc:
New method to collect all Item_field objects. Used by Item::walk.
sql/item.h:
Several methods to collect different kinds of items from expression trees.
Used by Item::walk.
sql/item_sum.cc:
Added helper to collect Item_sum objects.
sql/item_sum.h:
Methods to collect and test Item_sum objects.
sql/key.cc:
More general interface to key_copy and key_restore.
sql/mysql_priv.h:
More general interface to key_copy and key_restore.
sql/opt_range.cc:
Complete implementaion of WL#1724 "Min/Max Optimization for Queries with Group By Clause".
sql/opt_range.h:
Complete implementaion of WL#1724 "Min/Max Optimization for Queries with Group By Clause".
sql/opt_sum.cc:
simple_pred is re-used in opt_range.cc
sql/sql_acl.cc:
More general interface to key_copy and key_restore.
sql/sql_handler.cc:
More general interface to key_copy.
sql/sql_insert.cc:
More general interface to key_copy.
sql/sql_select.cc:
Changes to hook the new QUICK_GROUP_MIN_MAX_SELECT due to two differences from all other
quick selects:
1)
This quick select may be created (and used) even if there is no WHERE clause.
Several places assumed that a QUICK_SELECT is constructed only if there is a WHERE clause,
which had to be changed so that QUICK_GROUP_MIN_MAX can be used.
2)
Unlike all other quick selects, this QUICK_GROUP_MIN_MAX_SELECT operates for GROUP BY queries.
Since for the caller the quick select already produces one result tuple per group, there is
no need to call end_send_group, instead we have to call end_send as for a regular quick select.
sql/sql_select.h:
simple_pred is re-used in opt_range.cc
Diffstat (limited to 'sql/key.cc')
-rw-r--r-- | sql/key.cc | 113 |
1 files changed, 70 insertions, 43 deletions
diff --git a/sql/key.cc b/sql/key.cc index 9425a368669..90b8177a3a7 100644 --- a/sql/key.cc +++ b/sql/key.cc @@ -66,94 +66,121 @@ int find_ref_key(TABLE *table,Field *field, uint *key_length) } - /* Copy a key from record to some buffer */ - /* if length == 0 then copy whole key */ +/* + Copy part of a record that forms a key or key prefix to a buffer. + + SYNOPSIS + key_copy() + to_key buffer that will be used as a key + from_record full record to be copied from + key_info descriptor of the index + key_length specifies length of all keyparts that will be copied + + DESCRIPTION + The function takes a complete table record (as e.g. retrieved by + handler::index_read()), and a description of an index on the same table, + and extracts the first key_length bytes of the record which are part of a + key into to_key. If length == 0 then copy all bytes from the record that + form a key. + + RETURN + None +*/ -void key_copy(byte *key,TABLE *table,uint idx,uint key_length) +void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length) { uint length; - KEY *key_info=table->key_info+idx; KEY_PART_INFO *key_part; if (key_length == 0) - key_length=key_info->key_length; - for (key_part=key_info->key_part; - (int) key_length > 0 ; - key_part++) + key_length= key_info->key_length; + for (key_part= key_info->key_part; (int) key_length > 0; key_part++) { if (key_part->null_bit) { - *key++= test(table->record[0][key_part->null_offset] & + *to_key++= test(from_record[key_part->null_offset] & key_part->null_bit); key_length--; } if (key_part->key_part_flag & HA_BLOB_PART) { char *pos; - ulong blob_length=((Field_blob*) key_part->field)->get_length(); - key_length-=2; + ulong blob_length= ((Field_blob*) key_part->field)->get_length(); + key_length-= 2; ((Field_blob*) key_part->field)->get_ptr(&pos); - length=min(key_length,key_part->length); - set_if_smaller(blob_length,length); - int2store(key,(uint) blob_length); - key+=2; // Skip length info - memcpy(key,pos,blob_length); + length=min(key_length, key_part->length); + set_if_smaller(blob_length, length); + int2store(to_key, (uint) blob_length); + to_key+= 2; // Skip length info + memcpy(to_key, pos, blob_length); } else { - length=min(key_length,key_part->length); - memcpy(key,table->record[0]+key_part->offset,(size_t) length); + length= min(key_length, key_part->length); + memcpy(to_key, from_record + key_part->offset, (size_t) length); } - key+=length; - key_length-=length; + to_key+= length; + key_length-= length; } -} /* key_copy */ +} - /* restore a key from some buffer to record */ +/* + Restore a key from some buffer to record. + + SYNOPSIS + key_restore() + to_record record buffer where the key will be restored to + from_key buffer that contains a key + key_info descriptor of the index + key_length specifies length of all keyparts that will be restored + + DESCRIPTION + This function converts a key into record format. It can be used in cases + when we want to return a key as a result row. + + RETURN + None +*/ -void key_restore(TABLE *table,byte *key,uint idx,uint key_length) +void key_restore(byte *to_record, byte *from_key, KEY *key_info, + uint key_length) { uint length; - KEY *key_info=table->key_info+idx; KEY_PART_INFO *key_part; if (key_length == 0) { - if (idx == (uint) -1) - return; - key_length=key_info->key_length; + key_length= key_info->key_length; } - for (key_part=key_info->key_part; - (int) key_length > 0 ; - key_part++) + for (key_part= key_info->key_part ; (int) key_length > 0 ; key_part++) { if (key_part->null_bit) { - if (*key++) - table->record[0][key_part->null_offset]|= key_part->null_bit; + if (*from_key++) + to_record[key_part->null_offset]|= key_part->null_bit; else - table->record[0][key_part->null_offset]&= ~key_part->null_bit; + to_record[key_part->null_offset]&= ~key_part->null_bit; key_length--; } if (key_part->key_part_flag & HA_BLOB_PART) { - uint blob_length=uint2korr(key); - key+=2; - key_length-=2; + uint blob_length= uint2korr(from_key); + from_key+= 2; + key_length-= 2; ((Field_blob*) key_part->field)->set_ptr((ulong) blob_length, - (char*) key); - length=key_part->length; + (char*) from_key); + length= key_part->length; } else { - length=min(key_length,key_part->length); - memcpy(table->record[0]+key_part->offset,key,(size_t) length); + length= min(key_length, key_part->length); + memcpy(to_record + key_part->offset, from_key, (size_t) length); } - key+=length; - key_length-=length; + from_key+= length; + key_length-= length; } -} /* key_restore */ +} /* |