summaryrefslogtreecommitdiff
path: root/mysys/queues.c
diff options
context:
space:
mode:
authorunknown <holyfoot/hf@mysql.com/hfmain.(none)>2007-11-14 22:20:31 +0400
committerunknown <holyfoot/hf@mysql.com/hfmain.(none)>2007-11-14 22:20:31 +0400
commitc33c92d0f2d94e796aa403b80b29477e3400659b (patch)
tree9915b8eef2d14bebd9f577b361e1dd99b46f9d13 /mysys/queues.c
parentd68b313dbc9af3f5924db977c12eff5e88f296be (diff)
downloadmariadb-git-c33c92d0f2d94e796aa403b80b29477e3400659b.tar.gz
Bug #31890 Partitions: ORDER BY DESC in InnoDB not working.
It's not InnoDB specific bug. Error is in QUEUE code, about the way we handle queue->max_at_top. It's either '0' or '-2' and we do '^' operation to get the proper direction. Though queue->compare() function can return '-2' as a result of comparison sometimes. So we'll get queue->compare() ^ queue->max_at_top == 0 (when max_at_top is -2) and _downheap() function code will go wrong way here: ... if (next_index < elements && (queue->compare(queue->first_cmp_arg, queue->root[next_index]+offset_to_key, queue->root[next_index+1]+offset_to_key) ^ queue->max_at_top) > 0) next_index++; ... Fixed by changing max_at_top to be either 1 or -1, doing '* max_at_top' to get proper direction. include/queues.h: Bug #31890 Partitions: ORDER BY DESC in InnoDB not working max_at_top policy changed mysql-test/r/partition.result: Bug #31890 Partitions: ORDER BY DESC in InnoDB not working test result mysql-test/t/partition.test: Bug #31890 Partitions: ORDER BY DESC in InnoDB not working test case mysys/queues.c: Bug #31890 Partitions: ORDER BY DESC in InnoDB not working. queue->max_at_top policy changed - now it can either be '1' or '-1'. We multiply comparison result on max_at_top to get the proper direction.
Diffstat (limited to 'mysys/queues.c')
-rw-r--r--mysys/queues.c36
1 files changed, 15 insertions, 21 deletions
diff --git a/mysys/queues.c b/mysys/queues.c
index d8a7ca19bee..c0561e41dce 100644
--- a/mysys/queues.c
+++ b/mysys/queues.c
@@ -61,7 +61,7 @@ int init_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
queue->first_cmp_arg=first_cmp_arg;
queue->max_elements=max_elements;
queue->offset_to_key=offset_to_key;
- queue->max_at_top= max_at_top ? (-1 ^ 1) : 0;
+ queue_set_max_at_top(queue, max_at_top);
DBUG_RETURN(0);
}
@@ -137,7 +137,7 @@ int reinit_queue(QUEUE *queue, uint max_elements, uint offset_to_key,
queue->compare=compare;
queue->first_cmp_arg=first_cmp_arg;
queue->offset_to_key=offset_to_key;
- queue->max_at_top= max_at_top ? (-1 ^ 1) : 0;
+ queue_set_max_at_top(queue, max_at_top);
resize_queue(queue, max_elements);
DBUG_RETURN(0);
}
@@ -208,16 +208,14 @@ void delete_queue(QUEUE *queue)
void queue_insert(register QUEUE *queue, uchar *element)
{
reg2 uint idx, next;
- int cmp;
DBUG_ASSERT(queue->elements < queue->max_elements);
queue->root[0]= element;
idx= ++queue->elements;
/* max_at_top swaps the comparison if we want to order by desc */
- while ((cmp= queue->compare(queue->first_cmp_arg,
- element + queue->offset_to_key,
- queue->root[(next= idx >> 1)] +
- queue->offset_to_key)) &&
- (cmp ^ queue->max_at_top) < 0)
+ while ((queue->compare(queue->first_cmp_arg,
+ element + queue->offset_to_key,
+ queue->root[(next= idx >> 1)] +
+ queue->offset_to_key) * queue->max_at_top) < 0)
{
queue->root[idx]= queue->root[next];
idx= next;
@@ -287,19 +285,17 @@ void _downheap(register QUEUE *queue, uint idx)
while (idx <= half_queue)
{
- int cmp;
next_index=idx+idx;
if (next_index < elements &&
(queue->compare(queue->first_cmp_arg,
queue->root[next_index]+offset_to_key,
- queue->root[next_index+1]+offset_to_key) ^
+ queue->root[next_index+1]+offset_to_key) *
queue->max_at_top) > 0)
next_index++;
if (first &&
- (((cmp=queue->compare(queue->first_cmp_arg,
- queue->root[next_index]+offset_to_key,
- element+offset_to_key)) == 0) ||
- ((cmp ^ queue->max_at_top) > 0)))
+ (((queue->compare(queue->first_cmp_arg,
+ queue->root[next_index]+offset_to_key,
+ element+offset_to_key) * queue->max_at_top) >= 0)))
{
queue->root[idx]= element;
return;
@@ -314,7 +310,7 @@ void _downheap(register QUEUE *queue, uint idx)
{
if ((queue->compare(queue->first_cmp_arg,
queue->root[next_index]+offset_to_key,
- element+offset_to_key) ^
+ element+offset_to_key) *
queue->max_at_top) < 0)
break;
queue->root[idx]=queue->root[next_index];
@@ -334,7 +330,6 @@ void _downheap(register QUEUE *queue, uint idx)
{
uchar *element;
uint elements,half_queue,next_index,offset_to_key;
- int cmp;
offset_to_key=queue->offset_to_key;
element=queue->root[idx];
@@ -346,13 +341,12 @@ void _downheap(register QUEUE *queue, uint idx)
if (next_index < elements &&
(queue->compare(queue->first_cmp_arg,
queue->root[next_index]+offset_to_key,
- queue->root[next_index+1]+offset_to_key) ^
+ queue->root[next_index+1]+offset_to_key) *
queue->max_at_top) > 0)
next_index++;
- if ((cmp=queue->compare(queue->first_cmp_arg,
- queue->root[next_index]+offset_to_key,
- element+offset_to_key)) == 0 ||
- (cmp ^ queue->max_at_top) > 0)
+ if ((queue->compare(queue->first_cmp_arg,
+ queue->root[next_index]+offset_to_key,
+ element+offset_to_key) * queue->max_at_top) >= 0)
break;
queue->root[idx]=queue->root[next_index];
idx=next_index;