]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix for ticket #142: Make sure we get the correct sort order even when the
authordrh <drh@noemail.net>
Mon, 26 Aug 2002 19:55:07 +0000 (19:55 +0000)
committerdrh <drh@noemail.net>
Mon, 26 Aug 2002 19:55:07 +0000 (19:55 +0000)
columns being sorted contain NULLs. (CVS 730)

FossilOrigin-Name: 45847390d007718a4b7a4e9fa445136d013113f8

manifest
manifest.uuid
src/util.c
src/vdbe.c
test/sort.test

index 8a852eeac5cfa9590b75f5a52658dfd94f2da712..54e5fbb1087710e25b8d547418628e63eaf40eb8 100644 (file)
--- a/manifest
+++ b/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
index 3752548f31b6d9caee6fb1b3b5c7390dc7cedc7c..07ec281392d533261afe97ed8cef87b1480124ce 100644 (file)
@@ -1 +1 @@
-9e341d9c934c2111be6834743f1ce30463b095b6
\ No newline at end of file
+45847390d007718a4b7a4e9fa445136d013113f8
\ No newline at end of file
index 200a14c376a0ff77f17220adbc0a70648be3523a..b4dca2af0d8fbc28372a8d9def8ef382886dcc62 100644 (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;
 }
 
index cfd0810bb06469cd1d15b7ef29798b87f4807fb2..dd6c973046612cb52a23f2eada746e3fde03dbe4 100644 (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 );
index a6d05d6fbe1fa43d5e32763b6d2acf658e937ea0..97b1f41750893afdc19343bc598851a8c85f0b7d 100644 (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