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:
drh 2002-08-26 19:55:07 +00:00
parent d2df27e41d
commit da30d3696b
5 changed files with 100 additions and 27 deletions

View File

@ -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

View File

@ -1 +1 @@
9e341d9c934c2111be6834743f1ce30463b095b6
45847390d007718a4b7a4e9fa445136d013113f8

View File

@ -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;
}

View File

@ -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 );

View File

@ -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