From: Date: November 14 2007 7:20pm Subject: bk commit into 5.1 tree (holyfoot:1.2648) BUG#31890 List-Archive: http://lists.mysql.com/commits/37764 X-Bug: 31890 Message-Id: <20071114182035.B072D2C380A5@hfmain.localdomain> Below is the list of changes that have just been committed into a local 5.1 repository of hf. When hf does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-11-14 22:20:31+04:00, holyfoot@stripped +4 -0 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@stripped, 2007-11-14 22:20:28+04:00, holyfoot@stripped +3 -3 Bug #31890 Partitions: ORDER BY DESC in InnoDB not working max_at_top policy changed mysql-test/r/partition.result@stripped, 2007-11-14 22:20:28+04:00, holyfoot@stripped +35 -0 Bug #31890 Partitions: ORDER BY DESC in InnoDB not working test result mysql-test/t/partition.test@stripped, 2007-11-14 22:20:29+04:00, holyfoot@stripped +27 -0 Bug #31890 Partitions: ORDER BY DESC in InnoDB not working test case mysys/queues.c@stripped, 2007-11-14 22:20:29+04:00, holyfoot@stripped +15 -21 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. diff -Nrup a/include/queues.h b/include/queues.h --- a/include/queues.h 2007-05-10 14:59:24 +05:00 +++ b/include/queues.h 2007-11-14 22:20:28 +04:00 @@ -31,8 +31,8 @@ typedef struct st_queue { void *first_cmp_arg; uint elements; uint max_elements; - uint offset_to_key; /* compare is done on element+offset */ - int max_at_top; /* Set if queue_top gives max */ + uint offset_to_key; /* compare is done on element+offset */ + int max_at_top; /* Normally 1, set to -1 if queue_top gives max */ int (*compare)(void *, uchar *,uchar *); uint auto_extent; } QUEUE; @@ -43,7 +43,7 @@ typedef struct st_queue { #define queue_replaced(queue) _downheap(queue,1) #define queue_set_cmp_arg(queue, set_arg) (queue)->first_cmp_arg= set_arg #define queue_set_max_at_top(queue, set_arg) \ - (queue)->max_at_top= set_arg ? (-1 ^ 1) : 0 + (queue)->max_at_top= set_arg ? -1 : 1 typedef int (*queue_compare)(void *,uchar *, uchar *); int init_queue(QUEUE *queue,uint max_elements,uint offset_to_key, diff -Nrup a/mysql-test/r/partition.result b/mysql-test/r/partition.result --- a/mysql-test/r/partition.result 2007-11-13 23:16:45 +04:00 +++ b/mysql-test/r/partition.result 2007-11-14 22:20:28 +04:00 @@ -1296,4 +1296,39 @@ create table t1 partition by key(s1) partitions 3; insert into t1 values (null,null); drop table t1; +CREATE TABLE t1 +(int_column INT, char_column CHAR(5), +PRIMARY KEY(char_column,int_column)) +PARTITION BY KEY(char_column,int_column) +PARTITIONS 101; +INSERT INTO t1 (int_column, char_column) VALUES +( 39868 ,'zZZRW'), +( 545592 ,'zZzSD'), +( 4936 ,'zzzsT'), +( 9274 ,'ZzZSX'), +( 970185 ,'ZZzTN'), +( 786036 ,'zZzTO'), +( 37240 ,'zZzTv'), +( 313801 ,'zzzUM'), +( 782427 ,'ZZZva'), +( 907955 ,'zZZvP'), +( 453491 ,'zzZWV'), +( 756594 ,'ZZZXU'), +( 718061 ,'ZZzZH'); +SELECT * FROM t1 ORDER BY char_column DESC; +int_column char_column +718061 ZZzZH +756594 ZZZXU +453491 zzZWV +907955 zZZvP +782427 ZZZva +313801 zzzUM +37240 zZzTv +786036 zZzTO +970185 ZZzTN +9274 ZzZSX +4936 zzzsT +545592 zZzSD +39868 zZZRW +DROP TABLE t1; End of 5.1 tests diff -Nrup a/mysql-test/t/partition.test b/mysql-test/t/partition.test --- a/mysql-test/t/partition.test 2007-11-13 23:16:45 +04:00 +++ b/mysql-test/t/partition.test 2007-11-14 22:20:29 +04:00 @@ -1549,4 +1549,31 @@ while ($cnt) --enable_query_log drop table t1; + +# +# Bug #31890 Partitions: ORDER BY DESC in InnoDB not working +# + +CREATE TABLE t1 +(int_column INT, char_column CHAR(5), +PRIMARY KEY(char_column,int_column)) +PARTITION BY KEY(char_column,int_column) +PARTITIONS 101; +INSERT INTO t1 (int_column, char_column) VALUES +( 39868 ,'zZZRW'), +( 545592 ,'zZzSD'), +( 4936 ,'zzzsT'), +( 9274 ,'ZzZSX'), +( 970185 ,'ZZzTN'), +( 786036 ,'zZzTO'), +( 37240 ,'zZzTv'), +( 313801 ,'zzzUM'), +( 782427 ,'ZZZva'), +( 907955 ,'zZZvP'), +( 453491 ,'zzZWV'), +( 756594 ,'ZZZXU'), +( 718061 ,'ZZzZH'); +SELECT * FROM t1 ORDER BY char_column DESC; +DROP TABLE t1; + --echo End of 5.1 tests diff -Nrup a/mysys/queues.c b/mysys/queues.c --- a/mysys/queues.c 2007-05-10 14:59:26 +05:00 +++ b/mysys/queues.c 2007-11-14 22:20:29 +04:00 @@ -61,7 +61,7 @@ int init_queue(QUEUE *queue, uint max_el 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_ 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, ui 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, ui { 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, ui { 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, ui 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;