gitlab.com/CoiaPrant/sqlite3@v1.19.1/testdata/tcl/memdb.test (about)

     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 {UNIQUE constraint failed: t1.a}}
   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      load_static_extension db wholenumber
   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 before [db one {PRAGMA page_count}]
   423      execsql { DELETE FROM t1 }
   424      set after [db one {PRAGMA page_count}]
   425      expr {$before>$after}
   426    } {1}
   427  }
   428  
   429  } ;# ifcapable memorydb
   430  
   431  finish_test