summaryrefslogtreecommitdiff
path: root/sql/key.cc
diff options
context:
space:
mode:
authorunknown <timour@mysql.com>2004-08-27 16:37:13 +0300
committerunknown <timour@mysql.com>2004-08-27 16:37:13 +0300
commitd9450332927128073e353f11269eba5f0e4ad941 (patch)
tree7af5a09192d2042b9d236d1b98634b8b14be9601 /sql/key.cc
parent7bba8128ed65a5d841679fceb8c6c8dd5cac008c (diff)
downloadmariadb-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.cc113
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 */
+}
/*