| Index: third_party/sqlite/src/test/sort.test | 
| diff --git a/third_party/sqlite/src/test/sort.test b/third_party/sqlite/src/test/sort.test | 
| index 08d496b2596a0380455034930d974f4e20a816c2..be2a6f531c05826cf85fbd1f60044ca62f9d0650 100644 | 
| --- a/third_party/sqlite/src/test/sort.test | 
| +++ b/third_party/sqlite/src/test/sort.test | 
| @@ -8,13 +8,14 @@ | 
| #    May you share freely, never taking more than you give. | 
| # | 
| #*********************************************************************** | 
| +# | 
| # This file implements regression tests for SQLite library.  The | 
| -# focus of this file is testing the CREATE TABLE statement. | 
| +# focus of this file is testing the sorter (code in vdbesort.c). | 
| # | 
| -# $Id: sort.test,v 1.25 2005/11/14 22:29:06 drh Exp $ | 
|  | 
| set testdir [file dirname $argv0] | 
| source $testdir/tester.tcl | 
| +set testprefix sort | 
|  | 
| # Create a bunch of data to sort against | 
| # | 
| @@ -464,4 +465,175 @@ do_test sort-12.1 { | 
| } | 
| } {1 2 xxx 1 3 yyy 1 1 zzz} | 
|  | 
| +#------------------------------------------------------------------------- | 
| +# Check that the sorter in vdbesort.c sorts in a stable fashion. | 
| +# | 
| +do_execsql_test sort-13.0 { | 
| +  CREATE TABLE t10(a, b); | 
| +} | 
| +do_test sort-13.1 { | 
| +  db transaction { | 
| +    for {set i 0} {$i < 100000} {incr i} { | 
| +      execsql { INSERT INTO t10 VALUES( $i/10, $i%10 ) } | 
| +    } | 
| +  } | 
| +} {} | 
| +do_execsql_test sort-13.2 { | 
| +  SELECT a, b FROM t10 ORDER BY a; | 
| +} [db eval {SELECT a, b FROM t10 ORDER BY a, b}] | 
| +do_execsql_test sort-13.3 { | 
| +  PRAGMA cache_size = 5; | 
| +  SELECT a, b FROM t10 ORDER BY a; | 
| +} [db eval {SELECT a, b FROM t10 ORDER BY a, b}] | 
| + | 
| +#------------------------------------------------------------------------- | 
| +# Sort some large ( > 4KiB) records. | 
| +# | 
| +proc cksum {x} { | 
| +  set i1 1 | 
| +  set i2 2 | 
| +  binary scan $x c* L | 
| +  foreach {a b} $L { | 
| +    set i1 [expr (($i2<<3) + $a) & 0x7FFFFFFF] | 
| +    set i2 [expr (($i1<<3) + $b) & 0x7FFFFFFF] | 
| +  } | 
| +  list $i1 $i2 | 
| +} | 
| +db func cksum cksum | 
| + | 
| +do_execsql_test sort-14.0 { | 
| +  PRAGMA cache_size = 5; | 
| +  CREATE TABLE t11(a, b); | 
| +  INSERT INTO t11 VALUES(randomblob(5000), NULL); | 
| +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --2 | 
| +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --3 | 
| +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --4 | 
| +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --5 | 
| +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --6 | 
| +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --7 | 
| +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --8 | 
| +  INSERT INTO t11 SELECT randomblob(5000), NULL FROM t11; --9 | 
| +  UPDATE t11 SET b = cksum(a); | 
| +} | 
| + | 
| +foreach {tn mmap_limit} { | 
| +  1 0 | 
| +  2 1000000 | 
| +} { | 
| +  do_test sort-14.$tn { | 
| +    sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $mmap_limit | 
| +    set prev "" | 
| +    db eval { SELECT * FROM t11 ORDER BY b } { | 
| +      if {$b != [cksum $a]} {error "checksum failed"} | 
| +      if {[string compare $b $prev] < 0} {error "sort failed"} | 
| +      set prev $b | 
| +    } | 
| +    set {} {} | 
| +  } {} | 
| +} | 
| + | 
| +#------------------------------------------------------------------------- | 
| +# | 
| +foreach {tn mmap_limit nWorker tmpstore coremutex fakeheap softheaplimit} { | 
| +          1          0       3     file      true    false             0 | 
| +          2          0       3     file      true     true             0 | 
| +          3          0       0     file      true    false             0 | 
| +          4    1000000       3     file      true    false             0 | 
| +          5          0       0   memory     false     true             0 | 
| +          6          0       0     file     false     true       1000000 | 
| +          7          0       0     file     false     true         10000 | 
| +} { | 
| +  db close | 
| +  sqlite3_shutdown | 
| +  if {$coremutex} { | 
| +    sqlite3_config multithread | 
| +  } else { | 
| +    sqlite3_config singlethread | 
| +  } | 
| +  sqlite3_initialize | 
| +  sorter_test_fakeheap $fakeheap | 
| +  sqlite3_soft_heap_limit $softheaplimit | 
| + | 
| +  reset_db | 
| +  sqlite3_test_control SQLITE_TESTCTRL_SORTER_MMAP db $mmap_limit | 
| +  execsql "PRAGMA temp_store = $tmpstore; PRAGMA threads = $nWorker" | 
| + | 
| + | 
| +  set ten [string repeat X 10300] | 
| +  set one [string repeat y   200] | 
| + | 
| +  if {$softheaplimit} { | 
| +    execsql { PRAGMA cache_size = 20 }; | 
| +  } else { | 
| +    execsql { PRAGMA cache_size = 5 }; | 
| +  } | 
| + | 
| +  do_execsql_test 15.$tn.1 { | 
| +    WITH rr AS ( | 
| +      SELECT 4, $ten UNION ALL | 
| +      SELECT 2, $one UNION ALL | 
| +      SELECT 1, $ten UNION ALL | 
| +      SELECT 3, $one | 
| +    ) | 
| +    SELECT * FROM rr ORDER BY 1; | 
| +  } [list 1 $ten 2 $one 3 $one 4 $ten] | 
| + | 
| +  do_execsql_test 15.$tn.2 { | 
| +    CREATE TABLE t1(a); | 
| +    INSERT INTO t1 VALUES(4); | 
| +    INSERT INTO t1 VALUES(5); | 
| +    INSERT INTO t1 VALUES(3); | 
| +    INSERT INTO t1 VALUES(2); | 
| +    INSERT INTO t1 VALUES(6); | 
| +    INSERT INTO t1 VALUES(1); | 
| +    CREATE INDEX i1 ON t1(a); | 
| +    SELECT * FROM t1 ORDER BY a; | 
| +  } {1 2 3 4 5 6} | 
| + | 
| +  do_execsql_test 15.$tn.3 { | 
| +    WITH rr AS ( | 
| +      SELECT 4, $ten UNION ALL | 
| +      SELECT 2, $one | 
| +    ) | 
| +    SELECT * FROM rr ORDER BY 1; | 
| +  } [list 2 $one 4 $ten] | 
| + | 
| +  sorter_test_fakeheap 0 | 
| +} | 
| + | 
| +db close | 
| +sqlite3_shutdown | 
| +set t(0) singlethread | 
| +set t(1) multithread | 
| +set t(2) serialized | 
| +sqlite3_config $t($sqlite_options(threadsafe)) | 
| +sqlite3_initialize | 
| +sqlite3_soft_heap_limit 0 | 
| + | 
| +reset_db | 
| +do_catchsql_test 16.1 { | 
| +  CREATE TABLE t1(a, b, c); | 
| +  INSERT INTO t1 VALUES(1, 2, 3); | 
| +  INSERT INTO t1 VALUES(1, NULL, 3); | 
| +  INSERT INTO t1 VALUES(NULL, 2, 3); | 
| +  INSERT INTO t1 VALUES(1, 2, NULL); | 
| +  INSERT INTO t1 VALUES(4, 5, 6); | 
| +  CREATE UNIQUE INDEX i1 ON t1(b, a, c); | 
| +} {0 {}} | 
| +reset_db | 
| +do_catchsql_test 16.2 { | 
| +  CREATE TABLE t1(a, b, c); | 
| +  INSERT INTO t1 VALUES(1, 2, 3); | 
| +  INSERT INTO t1 VALUES(1, NULL, 3); | 
| +  INSERT INTO t1 VALUES(1, 2, 3); | 
| +  INSERT INTO t1 VALUES(1, 2, NULL); | 
| +  INSERT INTO t1 VALUES(4, 5, 6); | 
| +  CREATE UNIQUE INDEX i1 ON t1(b, a, c); | 
| +} {1 {UNIQUE constraint failed: t1.b, t1.a, t1.c}} | 
| + | 
| +reset_db | 
| +do_execsql_test 17.1 { | 
| +  SELECT * FROM sqlite_master ORDER BY sql; | 
| +} {} | 
| + | 
| finish_test | 
|  |