diff options
author | Georgi Kodinov <kgeorge@mysql.com> | 2008-07-23 14:25:00 +0300 |
---|---|---|
committer | Georgi Kodinov <kgeorge@mysql.com> | 2008-07-23 14:25:00 +0300 |
commit | dd85aa78ba8fbdd992139223aff9ef051f80694a (patch) | |
tree | ea66f61dad46c8910d1b367ad135c0f17b1ca94d /sql/opt_range.cc | |
parent | f5bbcba96f763d58dfd2d3e03d5c4dfd0b5f0eec (diff) | |
download | mariadb-git-dd85aa78ba8fbdd992139223aff9ef051f80694a.tar.gz |
Bug#37830 : ORDER BY ASC/DESC - no difference
Range scan in descending order for c <= <col> <= c type of
ranges was ignoring the DESC flag.
However some engines like InnoDB have the primary key parts
as a suffix for every secondary key.
When such primary key suffix is used for ordering ignoring
the DESC is not valid.
But we generally would like to do this because it's faster.
Fixed by performing only reverse scan if the primary key is used.
Removed some dead code in the process.
mysql-test/r/innodb_mysql.result:
Bug#37830 : test case
mysql-test/t/innodb_mysql.test:
Bug#37830 : test case
sql/opt_range.cc:
Bug#37830 :
- preserve and use used_key_parts to
distinguish when a primary key suffix is used
- removed some dead code
sql/opt_range.h:
Bug#37830 :
- preserve used_key_parts
- dead code removed
sql/sql_select.cc:
Bug#37830 : Do only reverse order traversal
if the primary key suffix is used.
Diffstat (limited to 'sql/opt_range.cc')
-rw-r--r-- | sql/opt_range.cc | 66 |
1 files changed, 12 insertions, 54 deletions
diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 95cda371673..7587db4e329 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7099,7 +7099,8 @@ bool QUICK_RANGE_SELECT::row_in_ranges() QUICK_SELECT_DESC::QUICK_SELECT_DESC(QUICK_RANGE_SELECT *q, uint used_key_parts_arg) - : QUICK_RANGE_SELECT(*q), rev_it(rev_ranges) + : QUICK_RANGE_SELECT(*q), rev_it(rev_ranges), + used_key_parts (used_key_parts_arg) { QUICK_RANGE *r; @@ -7141,10 +7142,11 @@ int QUICK_SELECT_DESC::get_next() int result; if (last_range) { // Already read through key - result = ((last_range->flag & EQ_RANGE) - ? file->index_next_same(record, (byte*) last_range->min_key, - last_range->min_length) : - file->index_prev(record)); + result = ((last_range->flag & EQ_RANGE && + used_key_parts <= head->key_info[index].key_parts) ? + file->index_next_same(record, (byte*) last_range->min_key, + last_range->min_length) : + file->index_prev(record)); if (!result) { if (cmp_prev(*rev_it.ref()) == 0) @@ -7168,7 +7170,9 @@ int QUICK_SELECT_DESC::get_next() continue; } - if (last_range->flag & EQ_RANGE) + if (last_range->flag & EQ_RANGE && + used_key_parts <= head->key_info[index].key_parts) + { result= file->index_read(record, (byte*) last_range->max_key, last_range->max_length, HA_READ_KEY_EXACT); @@ -7176,6 +7180,8 @@ int QUICK_SELECT_DESC::get_next() else { DBUG_ASSERT(last_range->flag & NEAR_MAX || + (last_range->flag & EQ_RANGE && + used_key_parts > head->key_info[index].key_parts) || range_reads_after_key(last_range)); result=file->index_read(record, (byte*) last_range->max_key, last_range->max_length, @@ -7273,54 +7279,6 @@ bool QUICK_SELECT_DESC::range_reads_after_key(QUICK_RANGE *range_arg) } -/* TRUE if we are reading over a key that may have a NULL value */ - -#ifdef NOT_USED -bool QUICK_SELECT_DESC::test_if_null_range(QUICK_RANGE *range_arg, - uint used_key_parts) -{ - uint offset, end; - KEY_PART *key_part = key_parts, - *key_part_end= key_part+used_key_parts; - - for (offset= 0, end = min(range_arg->min_length, range_arg->max_length) ; - offset < end && key_part != key_part_end ; - offset+= key_part++->store_length) - { - if (!memcmp((char*) range_arg->min_key+offset, - (char*) range_arg->max_key+offset, - key_part->store_length)) - continue; - - if (key_part->null_bit && range_arg->min_key[offset]) - return 1; // min_key is null and max_key isn't - // Range doesn't cover NULL. This is ok if there is no more null parts - break; - } - /* - If the next min_range is > NULL, then we can use this, even if - it's a NULL key - Example: SELECT * FROM t1 WHERE a = 2 AND b >0 ORDER BY a DESC,b DESC; - - */ - if (key_part != key_part_end && key_part->null_bit) - { - if (offset >= range_arg->min_length || range_arg->min_key[offset]) - return 1; // Could be null - key_part++; - } - /* - If any of the key parts used in the ORDER BY could be NULL, we can't - use the key to sort the data. - */ - for (; key_part != key_part_end ; key_part++) - if (key_part->null_bit) - return 1; // Covers null part - return 0; -} -#endif - - void QUICK_RANGE_SELECT::add_info_string(String *str) { KEY *key_info= head->key_info + index; |