Fix for ticket #142: Make sure we get the correct sort order even when the
columns being sorted contain NULLs. (CVS 730) FossilOrigin-Name: 45847390d007718a4b7a4e9fa445136d013113f8
This commit is contained in:
parent
d2df27e41d
commit
da30d3696b
16
manifest
16
manifest
@ -1,5 +1,5 @@
|
||||
C Version\s2.7.0\s(CVS\s729)
|
||||
D 2002-08-25T20:58:12
|
||||
C Fix\sfor\sticket\s#142:\sMake\ssure\swe\sget\sthe\scorrect\ssort\sorder\seven\swhen\sthe\ncolumns\sbeing\ssorted\scontain\sNULLs.\s(CVS\s730)
|
||||
D 2002-08-26T19:55:08
|
||||
F Makefile.in bcb81f40d9a17bd94f59e67157b1e1c54c046c2b
|
||||
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
|
||||
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
|
||||
@ -51,8 +51,8 @@ F src/threadtest.c 72bce0a284647314847bbea44616ceb056bfb77f
|
||||
F src/tokenize.c 8bd6251e5237c9a16d0bbfb9894925eb129985fa
|
||||
F src/trigger.c c90a292a4bef25e478fd5deda6d300319be6a023
|
||||
F src/update.c f07e6ed2c517c92871e54d3f5886d1cf56121b11
|
||||
F src/util.c 60bc91db77cf488618ec4720cb06eedb7f959268
|
||||
F src/vdbe.c 99b5714751b541a1c64c2c4dede83a474ca6b7e2
|
||||
F src/util.c c70d5da5357e01b58392faebae3c3620c1d71f14
|
||||
F src/vdbe.c ea41a3ac96511399e95ae18d16d32ec41ca91ec0
|
||||
F src/vdbe.h 52ec880c63c6ca74bb6377432149260b1b237873
|
||||
F src/where.c ce42cce65d7bf42341627f3fb0a17f69fea6a4f4
|
||||
F test/all.test efd958d048c70a3247997c482f0b33561f7759f0
|
||||
@ -93,7 +93,7 @@ F test/select3.test 3e98cec10e755226cbabdd7073ec37baab9ab148
|
||||
F test/select4.test 10ba54f24ef6ca7958a7045b001079378db2370c
|
||||
F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac
|
||||
F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85
|
||||
F test/sort.test f9744a81a488d6b448aeeb98d0546b5c802248ae
|
||||
F test/sort.test 876b76c5a837af5bead713146c7c65f85e84fbf5
|
||||
F test/subselect.test f0fea8cf9f386d416d64d152e3c65f9116d0f50f
|
||||
F test/table.test dedb4d3a73340d811e309672ca14537daa542fb1
|
||||
F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6
|
||||
@ -147,7 +147,7 @@ F www/speed.tcl a20a792738475b68756ea7a19321600f23d1d803
|
||||
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
|
||||
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
|
||||
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
|
||||
P e2d95f85a3c4beeb5f8e78498f52fc00475f38ed
|
||||
R 1887224d7be529eb62028d618058de77
|
||||
P 9e341d9c934c2111be6834743f1ce30463b095b6
|
||||
R c3833aec2102312b5a02d97350523f61
|
||||
U drh
|
||||
Z 2d9f1fc80b5f3e7813cac3b3ac44d578
|
||||
Z 83157ab4770270ac20f0733ba099c807
|
||||
|
@ -1 +1 @@
|
||||
9e341d9c934c2111be6834743f1ce30463b095b6
|
||||
45847390d007718a4b7a4e9fa445136d013113f8
|
31
src/util.c
31
src/util.c
@ -14,7 +14,7 @@
|
||||
** This file contains functions for allocating memory, comparing
|
||||
** strings, and stuff like that.
|
||||
**
|
||||
** $Id: util.c,v 1.49 2002/08/25 18:29:12 drh Exp $
|
||||
** $Id: util.c,v 1.50 2002/08/26 19:55:08 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <stdarg.h>
|
||||
@ -710,6 +710,10 @@ int sqliteCompare(const char *atext, const char *btext){
|
||||
**
|
||||
** Aone\000Dtwo\000Athree\000\000
|
||||
**
|
||||
** All elements begin with one of the characters "+-AD" and end with "\000"
|
||||
** with zero or more text elements in between. Except, NULL elements
|
||||
** consist of the special two-character sequence "N\000".
|
||||
**
|
||||
** Both arguments will have the same number of elements. This routine
|
||||
** returns negative, zero, or positive if the first argument is less
|
||||
** than, equal to, or greater than the first. (Result is a-b).
|
||||
@ -744,17 +748,26 @@ int sqliteSortCompare(const char *a, const char *b){
|
||||
int len;
|
||||
int res = 0;
|
||||
int isNumA, isNumB;
|
||||
int dir;
|
||||
|
||||
while( res==0 && *a && *b ){
|
||||
assert( a[0]==b[0] );
|
||||
if( a[1]==0 ){
|
||||
res = -1;
|
||||
break;
|
||||
}else if( b[1]==0 ){
|
||||
res = +1;
|
||||
if( a[0]=='N' || b[0]=='N' ){
|
||||
if( a[0]==b[0] ){
|
||||
a += 2;
|
||||
b += 2;
|
||||
continue;
|
||||
}
|
||||
if( a[0]=='N' ){
|
||||
dir = b[0];
|
||||
res = -1;
|
||||
}else{
|
||||
dir = a[0];
|
||||
res = +1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if( a[0]=='A' || a[0]=='D' ){
|
||||
assert( a[0]==b[0] );
|
||||
if( (dir=a[0])=='A' || a[0]=='D' ){
|
||||
res = strcmp(&a[1],&b[1]);
|
||||
if( res ) break;
|
||||
}else{
|
||||
@ -788,7 +801,7 @@ int sqliteSortCompare(const char *a, const char *b){
|
||||
a += len;
|
||||
b += len;
|
||||
}
|
||||
if( *a=='-' || *a=='D' ) res = -res;
|
||||
if( dir=='-' || dir=='D' ) res = -res;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
28
src/vdbe.c
28
src/vdbe.c
@ -30,7 +30,7 @@
|
||||
** But other routines are also provided to help in building up
|
||||
** a program instruction by instruction.
|
||||
**
|
||||
** $Id: vdbe.c,v 1.171 2002/08/25 19:20:40 drh Exp $
|
||||
** $Id: vdbe.c,v 1.172 2002/08/26 19:55:08 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include <ctype.h>
|
||||
@ -4393,11 +4393,13 @@ case OP_SortMakeRec: {
|
||||
** number of stack entries consumed is the number of characters in
|
||||
** the string P3. One character from P3 is prepended to each entry.
|
||||
** The first character of P3 is prepended to the element lowest in
|
||||
** the stack and the last character of P3 is appended to the top of
|
||||
** the stack and the last character of P3 is prepended to the top of
|
||||
** the stack. All stack entries are separated by a \000 character
|
||||
** in the result. The whole key is terminated by two \000 characters
|
||||
** in a row.
|
||||
**
|
||||
** "N" is substituted in place of the P3 character for NULL values.
|
||||
**
|
||||
** See also the MakeKey and MakeIdxKey opcodes.
|
||||
*/
|
||||
case OP_SortMakeKey: {
|
||||
@ -4410,18 +4412,28 @@ case OP_SortMakeKey: {
|
||||
VERIFY( if( p->tos+1<nField ) goto not_enough_stack; )
|
||||
nByte = 1;
|
||||
for(i=p->tos-nField+1; i<=p->tos; i++){
|
||||
if( Stringify(p, i) ) goto no_mem;
|
||||
nByte += aStack[i].n+2;
|
||||
if( (aStack[i].flags & STK_Null)!=0 ){
|
||||
nByte += 2;
|
||||
}else{
|
||||
if( Stringify(p, i) ) goto no_mem;
|
||||
nByte += aStack[i].n+2;
|
||||
}
|
||||
}
|
||||
zNewKey = sqliteMalloc( nByte );
|
||||
if( zNewKey==0 ) goto no_mem;
|
||||
j = 0;
|
||||
k = 0;
|
||||
for(i=p->tos-nField+1; i<=p->tos; i++){
|
||||
zNewKey[j++] = pOp->p3[k++];
|
||||
memcpy(&zNewKey[j], zStack[i], aStack[i].n-1);
|
||||
j += aStack[i].n-1;
|
||||
zNewKey[j++] = 0;
|
||||
if( (aStack[i].flags & STK_Null)!=0 ){
|
||||
zNewKey[j++] = 'N';
|
||||
zNewKey[j++] = 0;
|
||||
k++;
|
||||
}else{
|
||||
zNewKey[j++] = pOp->p3[k++];
|
||||
memcpy(&zNewKey[j], zStack[i], aStack[i].n-1);
|
||||
j += aStack[i].n-1;
|
||||
zNewKey[j++] = 0;
|
||||
}
|
||||
}
|
||||
zNewKey[j] = 0;
|
||||
assert( j<nByte );
|
||||
|
@ -11,7 +11,7 @@
|
||||
# This file implements regression tests for SQLite library. The
|
||||
# focus of this file is testing the CREATE TABLE statement.
|
||||
#
|
||||
# $Id: sort.test,v 1.6 2002/08/14 12:56:56 drh Exp $
|
||||
# $Id: sort.test,v 1.7 2002/08/26 19:55:11 drh Exp $
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
@ -217,6 +217,54 @@ do_test sort-4.8 {
|
||||
# }
|
||||
#} {-4000000000 -4221 -123 -3.141592653 -2.15 -2 0.0013442 1.6 2.7 11 50000000000 1.23456789012346e+18}
|
||||
|
||||
do_test sort-5.1 {
|
||||
execsql {
|
||||
create table t3(a,b);
|
||||
insert into t3 values(5,NULL);
|
||||
insert into t3 values(6,NULL);
|
||||
insert into t3 values(3,NULL);
|
||||
insert into t3 values(4,'cd');
|
||||
insert into t3 values(1,'ab');
|
||||
insert into t3 values(2,NULL);
|
||||
select a from t3 order by b, a;
|
||||
}
|
||||
} {2 3 5 6 1 4}
|
||||
do_test sort-5.2 {
|
||||
execsql {
|
||||
select a from t3 order by b, a desc;
|
||||
}
|
||||
} {6 5 3 2 1 4}
|
||||
do_test sort-5.3 {
|
||||
execsql {
|
||||
select a from t3 order by b desc, a;
|
||||
}
|
||||
} {4 1 2 3 5 6}
|
||||
do_test sort-5.4 {
|
||||
execsql {
|
||||
select a from t3 order by b desc, a desc;
|
||||
}
|
||||
} {4 1 6 5 3 2}
|
||||
|
||||
do_test sort-6.1 {
|
||||
execsql {
|
||||
create index i3 on t3(b,a);
|
||||
select a from t3 order by b, a;
|
||||
}
|
||||
} {2 3 5 6 1 4}
|
||||
do_test sort-6.2 {
|
||||
execsql {
|
||||
select a from t3 order by b, a desc;
|
||||
}
|
||||
} {6 5 3 2 1 4}
|
||||
do_test sort-6.3 {
|
||||
execsql {
|
||||
select a from t3 order by b desc, a;
|
||||
}
|
||||
} {4 1 2 3 5 6}
|
||||
do_test sort-6.4 {
|
||||
execsql {
|
||||
select a from t3 order by b desc, a desc;
|
||||
}
|
||||
} {4 1 6 5 3 2}
|
||||
|
||||
finish_test
|
||||
|
Loading…
x
Reference in New Issue
Block a user