| OLD | NEW | 
 | (Empty) | 
|    1 # 2001 September 15 |  | 
|    2 # |  | 
|    3 # The author disclaims copyright to this source code.  In place of |  | 
|    4 # a legal notice, here is a blessing: |  | 
|    5 # |  | 
|    6 #    May you do good and not evil. |  | 
|    7 #    May you find forgiveness for yourself and forgive others. |  | 
|    8 #    May you share freely, never taking more than you give. |  | 
|    9 # |  | 
|   10 #*********************************************************************** |  | 
|   11 # This file implements regression tests for SQLite library.  The |  | 
|   12 # focus of this script is in-memory database backend. |  | 
|   13 # |  | 
|   14 # $Id: memdb.test,v 1.19 2009/05/18 16:04:38 danielk1977 Exp $ |  | 
|   15  |  | 
|   16  |  | 
|   17 set testdir [file dirname $argv0] |  | 
|   18 source $testdir/tester.tcl |  | 
|   19  |  | 
|   20 ifcapable memorydb { |  | 
|   21  |  | 
|   22 # In the following sequence of tests, compute the MD5 sum of the content |  | 
|   23 # of a table, make lots of modifications to that table, then do a rollback. |  | 
|   24 # Verify that after the rollback, the MD5 checksum is unchanged. |  | 
|   25 # |  | 
|   26 # These tests were browed from trans.tcl. |  | 
|   27 # |  | 
|   28 do_test memdb-1.1 { |  | 
|   29   db close |  | 
|   30   sqlite3 db :memory: |  | 
|   31   # sqlite3 db test.db |  | 
|   32   execsql { |  | 
|   33     BEGIN; |  | 
|   34     CREATE TABLE t3(x TEXT); |  | 
|   35     INSERT INTO t3 VALUES(randstr(10,400)); |  | 
|   36     INSERT INTO t3 VALUES(randstr(10,400)); |  | 
|   37     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|   38     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|   39     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|   40     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|   41     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|   42     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|   43     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|   44     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|   45     INSERT INTO t3 SELECT randstr(10,400) FROM t3; |  | 
|   46     COMMIT; |  | 
|   47     SELECT count(*) FROM t3; |  | 
|   48   } |  | 
|   49 } {1024} |  | 
|   50  |  | 
|   51 # The following procedure computes a "signature" for table "t3".  If |  | 
|   52 # T3 changes in any way, the signature should change.   |  | 
|   53 # |  | 
|   54 # This is used to test ROLLBACK.  We gather a signature for t3, then |  | 
|   55 # make lots of changes to t3, then rollback and take another signature. |  | 
|   56 # The two signatures should be the same. |  | 
|   57 # |  | 
|   58 proc signature {{fn {}}} { |  | 
|   59   set rx [db eval {SELECT x FROM t3}] |  | 
|   60   # set r1 [md5 $rx\n] |  | 
|   61   if {$fn!=""} { |  | 
|   62     # set fd [open $fn w] |  | 
|   63     # puts $fd $rx |  | 
|   64     # close $fd |  | 
|   65   } |  | 
|   66   # set r [db eval {SELECT count(*), md5sum(x) FROM t3}] |  | 
|   67   # puts "SIG($fn)=$r1" |  | 
|   68   return [list [string length $rx] $rx] |  | 
|   69 } |  | 
|   70  |  | 
|   71 # Do rollbacks.  Make sure the signature does not change. |  | 
|   72 # |  | 
|   73 set limit 10 |  | 
|   74 for {set i 2} {$i<=$limit} {incr i} { |  | 
|   75   set ::sig [signature one] |  | 
|   76   # puts "sig=$sig" |  | 
|   77   set cnt [lindex $::sig 0] |  | 
|   78   if {$i%2==0} { |  | 
|   79     execsql {PRAGMA synchronous=FULL} |  | 
|   80   } else { |  | 
|   81     execsql {PRAGMA synchronous=NORMAL} |  | 
|   82   } |  | 
|   83   do_test memdb-1.$i.1-$cnt { |  | 
|   84      execsql { |  | 
|   85        BEGIN; |  | 
|   86        DELETE FROM t3 WHERE random()%10!=0; |  | 
|   87        INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; |  | 
|   88        INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; |  | 
|   89        ROLLBACK; |  | 
|   90      } |  | 
|   91      set sig2 [signature two] |  | 
|   92   } $sig |  | 
|   93   # puts "sig2=$sig2" |  | 
|   94   # if {$sig2!=$sig} exit |  | 
|   95   do_test memdb-1.$i.2-$cnt { |  | 
|   96      execsql { |  | 
|   97        BEGIN; |  | 
|   98        DELETE FROM t3 WHERE random()%10!=0; |  | 
|   99        INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; |  | 
|  100        DELETE FROM t3 WHERE random()%10!=0; |  | 
|  101        INSERT INTO t3 SELECT randstr(10,10)||x FROM t3; |  | 
|  102        ROLLBACK; |  | 
|  103      } |  | 
|  104      signature |  | 
|  105   } $sig |  | 
|  106   if {$i<$limit} { |  | 
|  107     do_test memdb-1.$i.9-$cnt { |  | 
|  108        execsql { |  | 
|  109          INSERT INTO t3 SELECT randstr(10,400) FROM t3 WHERE random()%10==0; |  | 
|  110        } |  | 
|  111     } {} |  | 
|  112   } |  | 
|  113   set ::pager_old_format 0 |  | 
|  114 } |  | 
|  115  |  | 
|  116 integrity_check memdb-2.1 |  | 
|  117  |  | 
|  118 do_test memdb-3.1 { |  | 
|  119   execsql { |  | 
|  120     CREATE TABLE t4(a,b,c,d); |  | 
|  121     BEGIN; |  | 
|  122     INSERT INTO t4 VALUES(1,2,3,4); |  | 
|  123     SELECT * FROM t4; |  | 
|  124   } |  | 
|  125 } {1 2 3 4} |  | 
|  126 do_test memdb-3.2 { |  | 
|  127   execsql { |  | 
|  128     SELECT name FROM sqlite_master WHERE type='table'; |  | 
|  129   } |  | 
|  130 } {t3 t4} |  | 
|  131 do_test memdb-3.3 { |  | 
|  132   execsql { |  | 
|  133     DROP TABLE t4; |  | 
|  134     SELECT name FROM sqlite_master WHERE type='table'; |  | 
|  135   } |  | 
|  136 } {t3} |  | 
|  137 do_test memdb-3.4 { |  | 
|  138   execsql { |  | 
|  139     ROLLBACK; |  | 
|  140     SELECT name FROM sqlite_master WHERE type='table'; |  | 
|  141   } |  | 
|  142 } {t3 t4} |  | 
|  143  |  | 
|  144 # Create tables for the first group of tests. |  | 
|  145 # |  | 
|  146 do_test memdb-4.0 { |  | 
|  147   execsql { |  | 
|  148     CREATE TABLE t1(a, b, c, UNIQUE(a,b)); |  | 
|  149     CREATE TABLE t2(x); |  | 
|  150     SELECT c FROM t1 ORDER BY c; |  | 
|  151   } |  | 
|  152 } {} |  | 
|  153  |  | 
|  154 # Six columns of configuration data as follows: |  | 
|  155 # |  | 
|  156 #   i      The reference number of the test |  | 
|  157 #   conf   The conflict resolution algorithm on the BEGIN statement |  | 
|  158 #   cmd    An INSERT or REPLACE command to execute against table t1 |  | 
|  159 #   t0     True if there is an error from $cmd |  | 
|  160 #   t1     Content of "c" column of t1 assuming no error in $cmd |  | 
|  161 #   t2     Content of "x" column of t2 |  | 
|  162 # |  | 
|  163 foreach {i conf cmd t0 t1 t2} { |  | 
|  164   1 {}       INSERT                  1 {}  1 |  | 
|  165   2 {}       {INSERT OR IGNORE}      0 3   1 |  | 
|  166   3 {}       {INSERT OR REPLACE}     0 4   1 |  | 
|  167   4 {}       REPLACE                 0 4   1 |  | 
|  168   5 {}       {INSERT OR FAIL}        1 {}  1 |  | 
|  169   6 {}       {INSERT OR ABORT}       1 {}  1 |  | 
|  170   7 {}       {INSERT OR ROLLBACK}    1 {}  {} |  | 
|  171 } { |  | 
|  172  |  | 
|  173   # All tests after test 1 depend on conflict resolution. So end the |  | 
|  174   # loop if that is not available in this build. |  | 
|  175   ifcapable !conflict {if {$i>1} break} |  | 
|  176  |  | 
|  177   do_test memdb-4.$i { |  | 
|  178     if {$conf!=""} {set conf "ON CONFLICT $conf"} |  | 
|  179     set r0 [catch {execsql [subst { |  | 
|  180       DELETE FROM t1; |  | 
|  181       DELETE FROM t2; |  | 
|  182       INSERT INTO t1 VALUES(1,2,3); |  | 
|  183       BEGIN $conf; |  | 
|  184       INSERT INTO t2 VALUES(1);  |  | 
|  185       $cmd INTO t1 VALUES(1,2,4); |  | 
|  186     }]} r1] |  | 
|  187     catch {execsql {COMMIT}} |  | 
|  188     if {$r0} {set r1 {}} {set r1 [execsql {SELECT c FROM t1}]} |  | 
|  189     set r2 [execsql {SELECT x FROM t2}] |  | 
|  190     list $r0 $r1 $r2 |  | 
|  191   } [list $t0 $t1 $t2] |  | 
|  192 } |  | 
|  193  |  | 
|  194 do_test memdb-5.0 { |  | 
|  195   execsql { |  | 
|  196     DROP TABLE t2; |  | 
|  197     DROP TABLE t3; |  | 
|  198     CREATE TABLE t2(a,b,c); |  | 
|  199     INSERT INTO t2 VALUES(1,2,1); |  | 
|  200     INSERT INTO t2 VALUES(2,3,2); |  | 
|  201     INSERT INTO t2 VALUES(3,4,1); |  | 
|  202     INSERT INTO t2 VALUES(4,5,4); |  | 
|  203     SELECT c FROM t2 ORDER BY b; |  | 
|  204     CREATE TABLE t3(x); |  | 
|  205     INSERT INTO t3 VALUES(1); |  | 
|  206   } |  | 
|  207 } {1 2 1 4} |  | 
|  208  |  | 
|  209 # Six columns of configuration data as follows: |  | 
|  210 # |  | 
|  211 #   i      The reference number of the test |  | 
|  212 #   conf1  The conflict resolution algorithm on the UNIQUE constraint |  | 
|  213 #   conf2  The conflict resolution algorithm on the BEGIN statement |  | 
|  214 #   cmd    An UPDATE command to execute against table t1 |  | 
|  215 #   t0     True if there is an error from $cmd |  | 
|  216 #   t1     Content of "b" column of t1 assuming no error in $cmd |  | 
|  217 #   t2     Content of "x" column of t3 |  | 
|  218 # |  | 
|  219 foreach {i conf1 conf2 cmd t0 t1 t2} { |  | 
|  220   1 {}       {}       UPDATE                  1 {6 7 8 9}  1 |  | 
|  221   2 REPLACE  {}       UPDATE                  0 {7 6 9}    1 |  | 
|  222   3 IGNORE   {}       UPDATE                  0 {6 7 3 9}  1 |  | 
|  223   4 FAIL     {}       UPDATE                  1 {6 7 3 4}  1 |  | 
|  224   5 ABORT    {}       UPDATE                  1 {1 2 3 4}  1 |  | 
|  225   6 ROLLBACK {}       UPDATE                  1 {1 2 3 4}  0 |  | 
|  226   7 REPLACE  {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1 |  | 
|  227   8 IGNORE   {}       {UPDATE OR REPLACE}     0 {7 6 9}    1 |  | 
|  228   9 FAIL     {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1 |  | 
|  229  10 ABORT    {}       {UPDATE OR REPLACE}     0 {7 6 9}    1 |  | 
|  230  11 ROLLBACK {}       {UPDATE OR IGNORE}      0 {6 7 3 9}   1 |  | 
|  231  12 {}       {}       {UPDATE OR IGNORE}      0 {6 7 3 9}  1 |  | 
|  232  13 {}       {}       {UPDATE OR REPLACE}     0 {7 6 9}    1 |  | 
|  233  14 {}       {}       {UPDATE OR FAIL}        1 {6 7 3 4}  1 |  | 
|  234  15 {}       {}       {UPDATE OR ABORT}       1 {1 2 3 4}  1 |  | 
|  235  16 {}       {}       {UPDATE OR ROLLBACK}    1 {1 2 3 4}  0 |  | 
|  236 } { |  | 
|  237   # All tests after test 1 depend on conflict resolution. So end the |  | 
|  238   # loop if that is not available in this build. |  | 
|  239   ifcapable !conflict { |  | 
|  240     if {$i>1} break |  | 
|  241   } |  | 
|  242  |  | 
|  243   if {$t0} {set t1 {column a is not unique}} |  | 
|  244   do_test memdb-5.$i { |  | 
|  245     if {$conf1!=""} {set conf1 "ON CONFLICT $conf1"} |  | 
|  246     if {$conf2!=""} {set conf2 "ON CONFLICT $conf2"} |  | 
|  247     set r0 [catch {execsql " |  | 
|  248       DROP TABLE t1; |  | 
|  249       CREATE TABLE t1(a,b,c, UNIQUE(a) $conf1); |  | 
|  250       INSERT INTO t1 SELECT * FROM t2; |  | 
|  251       UPDATE t3 SET x=0; |  | 
|  252       BEGIN $conf2; |  | 
|  253       $cmd t3 SET x=1; |  | 
|  254       $cmd t1 SET b=b*2; |  | 
|  255       $cmd t1 SET a=c+5; |  | 
|  256     "} r1] |  | 
|  257     catch {execsql {COMMIT}} |  | 
|  258     if {!$r0} {set r1 [execsql {SELECT a FROM t1 ORDER BY b}]} |  | 
|  259     set r2 [execsql {SELECT x FROM t3}] |  | 
|  260     list $r0 $r1 $r2 |  | 
|  261   } [list $t0 $t1 $t2] |  | 
|  262 } |  | 
|  263  |  | 
|  264 do_test memdb-6.1 { |  | 
|  265   execsql { |  | 
|  266     SELECT * FROM t2; |  | 
|  267   } |  | 
|  268 } {1 2 1 2 3 2 3 4 1 4 5 4} |  | 
|  269 do_test memdb-6.2 { |  | 
|  270   execsql { |  | 
|  271     BEGIN; |  | 
|  272     DROP TABLE t2; |  | 
|  273     SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1; |  | 
|  274   } |  | 
|  275 } {t1 t3 t4} |  | 
|  276 do_test memdb-6.3 { |  | 
|  277   execsql { |  | 
|  278     ROLLBACK; |  | 
|  279     SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1; |  | 
|  280   } |  | 
|  281 } {t1 t2 t3 t4} |  | 
|  282 do_test memdb-6.4 { |  | 
|  283   execsql { |  | 
|  284     SELECT * FROM t2; |  | 
|  285   } |  | 
|  286 } {1 2 1 2 3 2 3 4 1 4 5 4} |  | 
|  287 ifcapable compound { |  | 
|  288 do_test memdb-6.5 { |  | 
|  289   execsql { |  | 
|  290     SELECT a FROM t2 UNION SELECT b FROM t2 ORDER BY 1; |  | 
|  291   } |  | 
|  292 } {1 2 3 4 5} |  | 
|  293 } ;# ifcapable compound  |  | 
|  294 do_test memdb-6.6 { |  | 
|  295   execsql { |  | 
|  296     CREATE INDEX i2 ON t2(c); |  | 
|  297     SELECT a FROM t2 ORDER BY c; |  | 
|  298   } |  | 
|  299 } {1 3 2 4} |  | 
|  300 do_test memdb-6.6 { |  | 
|  301   execsql { |  | 
|  302     SELECT a FROM t2 ORDER BY c DESC; |  | 
|  303   } |  | 
|  304 } {4 2 3 1} |  | 
|  305 do_test memdb-6.7 { |  | 
|  306   execsql { |  | 
|  307     BEGIN; |  | 
|  308     CREATE TABLE t5(x,y); |  | 
|  309     INSERT INTO t5 VALUES(1,2); |  | 
|  310     SELECT * FROM t5; |  | 
|  311   } |  | 
|  312 } {1 2} |  | 
|  313 do_test memdb-6.8 { |  | 
|  314   execsql { |  | 
|  315     SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1; |  | 
|  316   } |  | 
|  317 } {t1 t2 t3 t4 t5} |  | 
|  318 do_test memdb-6.9 { |  | 
|  319   execsql { |  | 
|  320     ROLLBACK; |  | 
|  321     SELECT name FROM sqlite_master WHERE type='table' ORDER BY 1; |  | 
|  322   } |  | 
|  323 } {t1 t2 t3 t4} |  | 
|  324 do_test memdb-6.10 { |  | 
|  325   execsql { |  | 
|  326     CREATE TABLE t5(x PRIMARY KEY, y UNIQUE); |  | 
|  327     SELECT * FROM t5; |  | 
|  328   } |  | 
|  329 } {} |  | 
|  330 do_test memdb-6.11 { |  | 
|  331   execsql { |  | 
|  332     SELECT * FROM t5 ORDER BY y DESC; |  | 
|  333   } |  | 
|  334 } {} |  | 
|  335  |  | 
|  336 ifcapable conflict { |  | 
|  337   do_test memdb-6.12 { |  | 
|  338     execsql { |  | 
|  339       INSERT INTO t5 VALUES(1,2); |  | 
|  340       INSERT INTO t5 VALUES(3,4); |  | 
|  341       REPLACE INTO t5 VALUES(1,4); |  | 
|  342       SELECT rowid,* FROM t5; |  | 
|  343     } |  | 
|  344   } {3 1 4} |  | 
|  345   do_test memdb-6.13 { |  | 
|  346     execsql { |  | 
|  347       DELETE FROM t5 WHERE x>5; |  | 
|  348       SELECT * FROM t5; |  | 
|  349     } |  | 
|  350   } {1 4} |  | 
|  351   do_test memdb-6.14 { |  | 
|  352     execsql { |  | 
|  353       DELETE FROM t5 WHERE y<3; |  | 
|  354       SELECT * FROM t5; |  | 
|  355     } |  | 
|  356   } {1 4} |  | 
|  357 } |  | 
|  358  |  | 
|  359 do_test memdb-6.15 { |  | 
|  360   execsql { |  | 
|  361     DELETE FROM t5 WHERE x>0; |  | 
|  362     SELECT * FROM t5; |  | 
|  363   } |  | 
|  364 } {} |  | 
|  365  |  | 
|  366 ifcapable subquery { |  | 
|  367   do_test memdb-7.1 { |  | 
|  368     execsql { |  | 
|  369       CREATE TABLE t6(x); |  | 
|  370       INSERT INTO t6 VALUES(1); |  | 
|  371       INSERT INTO t6 SELECT x+1 FROM t6; |  | 
|  372       INSERT INTO t6 SELECT x+2 FROM t6; |  | 
|  373       INSERT INTO t6 SELECT x+4 FROM t6; |  | 
|  374       INSERT INTO t6 SELECT x+8 FROM t6; |  | 
|  375       INSERT INTO t6 SELECT x+16 FROM t6; |  | 
|  376       INSERT INTO t6 SELECT x+32 FROM t6; |  | 
|  377       INSERT INTO t6 SELECT x+64 FROM t6; |  | 
|  378       INSERT INTO t6 SELECT x+128 FROM t6; |  | 
|  379       SELECT count(*) FROM (SELECT DISTINCT x FROM t6); |  | 
|  380     } |  | 
|  381   } {256} |  | 
|  382   for {set i 1} {$i<=256} {incr i} { |  | 
|  383     do_test memdb-7.2.$i { |  | 
|  384        execsql "DELETE FROM t6 WHERE x=\ |  | 
|  385                 (SELECT x FROM t6 ORDER BY random() LIMIT 1)" |  | 
|  386        execsql {SELECT count(*) FROM t6} |  | 
|  387     } [expr {256-$i}] |  | 
|  388   } |  | 
|  389 } |  | 
|  390  |  | 
|  391 # Ticket #1524 |  | 
|  392 # |  | 
|  393 do_test memdb-8.1 { |  | 
|  394   db close |  | 
|  395   sqlite3 db {:memory:} |  | 
|  396   execsql { |  | 
|  397     PRAGMA auto_vacuum=TRUE; |  | 
|  398     CREATE TABLE t1(a); |  | 
|  399     INSERT INTO t1 VALUES(randstr(5000,6000)); |  | 
|  400     INSERT INTO t1 VALUES(randstr(5000,6000)); |  | 
|  401     INSERT INTO t1 VALUES(randstr(5000,6000)); |  | 
|  402     INSERT INTO t1 VALUES(randstr(5000,6000)); |  | 
|  403     INSERT INTO t1 VALUES(randstr(5000,6000)); |  | 
|  404     SELECT count(*) FROM t1; |  | 
|  405   } |  | 
|  406 } 5 |  | 
|  407 do_test memdb-8.2 { |  | 
|  408   execsql { |  | 
|  409     DELETE FROM t1; |  | 
|  410     SELECT count(*) FROM t1; |  | 
|  411   } |  | 
|  412 } 0 |  | 
|  413  |  | 
|  414 # Test that auto-vacuum works with in-memory databases. |  | 
|  415 #  |  | 
|  416 ifcapable autovacuum { |  | 
|  417   do_test memdb-9.1 { |  | 
|  418     db close |  | 
|  419     sqlite3 db test.db |  | 
|  420     db cache size 0 |  | 
|  421     execsql { |  | 
|  422       PRAGMA auto_vacuum = full; |  | 
|  423       CREATE TABLE t1(a); |  | 
|  424       INSERT INTO t1 VALUES(randstr(1000,1000)); |  | 
|  425       INSERT INTO t1 VALUES(randstr(1000,1000)); |  | 
|  426       INSERT INTO t1 VALUES(randstr(1000,1000)); |  | 
|  427     } |  | 
|  428     set memused [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1] |  | 
|  429     set pgovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 1] |  | 
|  430     execsql { DELETE FROM t1 } |  | 
|  431     set memused2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1] |  | 
|  432     expr {($memused2 + 2048 < $memused) || $pgovfl==0} |  | 
|  433   } {1} |  | 
|  434 } |  | 
|  435  |  | 
|  436 } ;# ifcapable memorydb |  | 
|  437  |  | 
|  438 finish_test |  | 
| OLD | NEW |