Home | History | Annotate | Download | only in test
      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&&vtab {
    367   do_test memdb-7.1 {
    368     register_wholenumber_module db
    369     execsql {
    370       CREATE TABLE t6(x);
    371       CREATE VIRTUAL TABLE nums USING wholenumber;
    372       INSERT INTO t6 SELECT value FROM nums WHERE value BETWEEN 1 AND 256;
    373       SELECT count(*) FROM (SELECT DISTINCT x FROM t6);
    374     }
    375   } {256}
    376   for {set i 1} {$i<=256} {incr i} {
    377     do_test memdb-7.2.$i {
    378        execsql "DELETE FROM t6 WHERE x=\
    379                 (SELECT x FROM t6 ORDER BY random() LIMIT 1)"
    380        execsql {SELECT count(*) FROM t6}
    381     } [expr {256-$i}]
    382   }
    383 }
    384 
    385 # Ticket #1524
    386 #
    387 do_test memdb-8.1 {
    388   db close
    389   sqlite3 db {:memory:}
    390   execsql {
    391     PRAGMA auto_vacuum=TRUE;
    392     CREATE TABLE t1(a);
    393     INSERT INTO t1 VALUES(randstr(5000,6000));
    394     INSERT INTO t1 VALUES(randstr(5000,6000));
    395     INSERT INTO t1 VALUES(randstr(5000,6000));
    396     INSERT INTO t1 VALUES(randstr(5000,6000));
    397     INSERT INTO t1 VALUES(randstr(5000,6000));
    398     SELECT count(*) FROM t1;
    399   }
    400 } 5
    401 do_test memdb-8.2 {
    402   execsql {
    403     DELETE FROM t1;
    404     SELECT count(*) FROM t1;
    405   }
    406 } 0
    407 
    408 # Test that auto-vacuum works with in-memory databases.
    409 # 
    410 ifcapable autovacuum {
    411   do_test memdb-9.1 {
    412     db close
    413     sqlite3 db test.db
    414     db cache size 0
    415     execsql {
    416       PRAGMA auto_vacuum = full;
    417       CREATE TABLE t1(a);
    418       INSERT INTO t1 VALUES(randstr(1000,1000));
    419       INSERT INTO t1 VALUES(randstr(1000,1000));
    420       INSERT INTO t1 VALUES(randstr(1000,1000));
    421     }
    422     set memused [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
    423     set pgovfl [lindex [sqlite3_status SQLITE_STATUS_PAGECACHE_OVERFLOW 0] 1]
    424     execsql { DELETE FROM t1 }
    425     set memused2 [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
    426     expr {($memused2 + 2048 < $memused) || $pgovfl==0}
    427   } {1}
    428 }
    429 
    430 } ;# ifcapable memorydb
    431 
    432 finish_test
    433