CoolFace
Modelpublic

AryaWu/sqlite

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
snapshot.test498 linesDownload Raw Back to test
1# 2015 December 72#3# The author disclaims copyright to this source code.  In place of4# 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 focus12# of this file is the sqlite3_snapshot_xxx() APIs.13#14 15set testdir [file dirname $argv0]16source $testdir/tester.tcl17ifcapable !snapshot {finish_test; return}18set testprefix snapshot19 20# This test does not work with the inmemory_journal permutation. The reason21# is that each connection opened as part of this permutation executes22# "PRAGMA journal_mode=memory", which fails if the database is in wal mode23# and there are one or more existing connections.24if {[permutation]=="inmemory_journal"} {25  finish_test26  return27}28 29foreach {tn tcl} {30  1 {31    proc snapshot_get {DB DBNAME} {32      uplevel [list sqlite3_snapshot_get $DB $DBNAME]33    }34    proc snapshot_open {DB DBNAME SNAPSHOT} {35      uplevel [list sqlite3_snapshot_open $DB $DBNAME $SNAPSHOT]36    }37    proc snapshot_free {SNAPSHOT} {38      uplevel [list sqlite3_snapshot_free $SNAPSHOT]39    }40    proc snapshot_cmp {SNAPSHOT1 SNAPSHOT2} {41      uplevel [list sqlite3_snapshot_cmp $SNAPSHOT1 $SNAPSHOT2]42    }43  }44 45  2 {46    proc snapshot_get {DB DBNAME} {47      uplevel [list sqlite3_snapshot_get_blob $DB $DBNAME]48    }49    proc snapshot_open {DB DBNAME SNAPSHOT} {50      uplevel [list sqlite3_snapshot_open_blob $DB $DBNAME $SNAPSHOT]51    }52    proc snapshot_free {SNAPSHOT} {53    }54    proc snapshot_cmp {SNAPSHOT1 SNAPSHOT2} {55      uplevel [list sqlite3_snapshot_cmp_blob $SNAPSHOT1 $SNAPSHOT2]56    }57  }58} {59 60  reset_db61  eval $tcl62 63  #-------------------------------------------------------------------------64  # Check some error conditions in snapshot_get(). It is an error if:65  #66  #  1) snapshot_get() is called on a non-WAL database, or67  #  2) there is an open write transaction on the database.68  #  3) the database handle is in auto-commit mode69  #70  do_execsql_test $tn.1.0 {71    CREATE TABLE t1(a, b);72    INSERT INTO t1 VALUES(1, 2);73    INSERT INTO t1 VALUES(3, 4);74  }75 76  do_test $tn.1.1.1 {77    execsql { BEGIN; SELECT * FROM t1; }78    list [catch { snapshot_get db main } msg] $msg79  } {1 SQLITE_ERROR}80  do_execsql_test $tn.1.1.2 COMMIT81 82  do_test $tn.1.2.1 {83    execsql {84      PRAGMA journal_mode = WAL;85      BEGIN;86        INSERT INTO t1 VALUES(5, 6);87        INSERT INTO t1 VALUES(7, 8);88    }89    list [catch { snapshot_get db main } msg] $msg90  } {1 SQLITE_ERROR}91  do_execsql_test $tn.1.2.2 COMMIT92 93  do_test $tn.1.3.1 {94    list [catch { snapshot_get db main } msg] $msg95  } {1 SQLITE_ERROR}96  do_test $tn.1.3.2 {97    db trans { set snap [snapshot_get db main] }98    snapshot_free $snap99  } {}100 101  #-------------------------------------------------------------------------102  # Check that a simple case works. Reuse the database created by the103  # block of tests above.104  #105  do_execsql_test $tn.2.1.0 {106    BEGIN;107      SELECT * FROM t1;108  } {1 2 3 4 5 6 7 8}109 110  do_test $tn.2.1.1 {111    set snapshot [snapshot_get db main]112    execsql {113      COMMIT;114      INSERT INTO t1 VALUES(9, 10);115      SELECT * FROM t1;116    }117  } {1 2 3 4 5 6 7 8 9 10}118 119  do_test $tn.2.1.2 {120    execsql BEGIN121    snapshot_open db main $snapshot122    execsql {123      SELECT * FROM t1;124    }125  } {1 2 3 4 5 6 7 8}126 127  do_test $tn.2.1.3 {128    snapshot_free $snapshot129    execsql COMMIT130  } {}131 132  do_test $tn.2.2.0 {133    sqlite3 db2 test.db134    execsql {135      BEGIN;136        SELECT * FROM t1;137    } db2138  } {1 2 3 4 5 6 7 8 9 10}139 140  do_test $tn.2.2.1 {141    set snapshot [snapshot_get db2 main]142    execsql {143      INSERT INTO t1 VALUES(11, 12);144      SELECT * FROM t1;145    }146  } {1 2 3 4 5 6 7 8 9 10 11 12}147 148  do_test $tn.2.2.2 {149    execsql BEGIN150    snapshot_open db main $snapshot151    execsql {152      SELECT * FROM t1;153    }154  } {1 2 3 4 5 6 7 8 9 10}155 156  do_test $tn.2.2.3 {157    snapshot_free $snapshot158    execsql COMMIT159    execsql COMMIT db2160    db2 close161  } {}162 163  do_test $tn.2.3.1 {164    execsql { DELETE FROM t1 WHERE a>6 }165    db trans { set snapshot [snapshot_get db main] }166    execsql {167      INSERT INTO t1 VALUES('a', 'b');168      INSERT INTO t1 VALUES('c', 'd');169      SELECT * FROM t1;170    }171  } {1 2 3 4 5 6 a b c d}172  do_test $tn.2.3.2 {173    execsql BEGIN174    snapshot_open db main $snapshot175    execsql { SELECT * FROM t1 }176  } {1 2 3 4 5 6}177 178  do_test $tn.2.3.3 {179    catchsql {180      INSERT INTO t1 VALUES('x','y')181    }182  } {1 {database is locked}}183  do_test $tn.2.3.4 {184    execsql COMMIT185    snapshot_free $snapshot186  } {}187 188  #-------------------------------------------------------------------------189  # Check some errors in snapshot_open(). It is an error if:190  #191  #   1) the db is in auto-commit mode,192  #   2) the db has an open (read or write) transaction,193  #   3) the db is not a wal database,194  #195  # Reuse the database created by earlier tests.196  #197  do_execsql_test $tn.3.0.0 {198    CREATE TABLE t2(x, y);199    INSERT INTO t2 VALUES('a', 'b');200    INSERT INTO t2 VALUES('c', 'd');201    BEGIN;202      SELECT * FROM t2;203  } {a b c d}204  do_test $tn.3.0.1 {205    set snapshot [snapshot_get db main]206    execsql { COMMIT }207    execsql { INSERT INTO t2 VALUES('e', 'f'); }208  } {}209 210  do_test $tn.3.1 {211    list [catch {snapshot_open db main $snapshot } msg] $msg212  } {1 SQLITE_ERROR}213 214  do_test $tn.3.2.1 {215    execsql {216      BEGIN;217        SELECT * FROM t2;218    }219  } {a b c d e f}220 221  # Update - it is no longer an error to have a read-transaction open, 222  # provided there are no active SELECT statements.223  do_test $tn.3.2.2a {224    db eval "SELECT * FROM t2" {225      set res [list [catch {snapshot_open db main $snapshot } msg] $msg]226      break227    }228    set res229  } {1 SQLITE_ERROR}230  do_test $tn.3.2.2b {231    snapshot_open db main $snapshot232  } {}233 234  do_test $tn.3.2.3 {235    execsql {236      COMMIT;237      BEGIN;238        INSERT INTO t2 VALUES('g', 'h');239    }240    list [catch {snapshot_open db main $snapshot } msg] $msg241  } {1 SQLITE_ERROR}242  do_execsql_test $tn.3.2.4 COMMIT243 244  do_test $tn.3.3.1a {245    execsql { PRAGMA journal_mode = DELETE }246    execsql { BEGIN }247    list [catch {snapshot_open db main $snapshot } msg] $msg248  } {1 SQLITE_ERROR}249 250  do_test $tn.3.3.1b {251    execsql { COMMIT ; BEGIN ; SELECT * FROM t2 }252    list [catch {snapshot_open db main $snapshot } msg] $msg253  } {1 SQLITE_ERROR}254 255  do_test $tn.$tn.3.3.2 {256    snapshot_free $snapshot257    execsql COMMIT258  } {}259 260  #-------------------------------------------------------------------------261  # Check that SQLITE_ERROR_SNAPSHOT is returned if the specified snapshot262  # no longer exists because the wal file has been checkpointed.263  #264  #   1. Reading a snapshot from the middle of a wal file is not possible265  #      after the wal file has been checkpointed.266  #267  #   2. That a snapshot from the end of a wal file can not be read once268  #      the wal file has been wrapped.269  #270  do_execsql_test $tn.4.1.0 {271    PRAGMA journal_mode = wal;272    CREATE TABLE t3(i, j);273    INSERT INTO t3 VALUES('o', 't');274    INSERT INTO t3 VALUES('t', 'f');275    BEGIN;276      SELECT * FROM t3;277  } {wal o t t f}278 279  do_test $tn.4.1.1 {280    set snapshot [snapshot_get db main]281    execsql COMMIT282  } {}283  do_test $tn.4.1.2 {284    execsql { 285      INSERT INTO t3 VALUES('f', 's'); 286      BEGIN;287    }288    snapshot_open db main $snapshot289    execsql { SELECT * FROM t3 }290  } {o t t f}291 292  do_test $tn.4.1.3 {293    execsql { 294      COMMIT;295      PRAGMA wal_checkpoint;296      BEGIN;297    }298    list [catch {snapshot_open db main $snapshot} msg] $msg299  } {1 SQLITE_ERROR_SNAPSHOT}300  do_test $tn.4.1.4 {301    snapshot_free $snapshot302    execsql COMMIT303  } {}304 305  do_test $tn.4.2.1 {306    execsql {307      INSERT INTO t3 VALUES('s', 'e');308      INSERT INTO t3 VALUES('n', 't');309      BEGIN;310        SELECT * FROM t3;311    }312  } {o t t f f s s e n t}313  do_test $tn.4.2.2 {314    set snapshot [snapshot_get db main]315    execsql {316      COMMIT;317      PRAGMA wal_checkpoint;318      BEGIN;319    }320    snapshot_open db main $snapshot321    execsql { SELECT * FROM t3 }322  } {o t t f f s s e n t}323  do_test $tn.4.2.3 {324    execsql {325      COMMIT;326      INSERT INTO t3 VALUES('e', 't');327      BEGIN;328    }329    list [catch {snapshot_open db main $snapshot} msg] $msg330  } {1 SQLITE_ERROR_SNAPSHOT}331  do_test $tn.4.2.4 {332    snapshot_free $snapshot333  } {}334 335  #-------------------------------------------------------------------------336  # Check that SQLITE_BUSY is returned if a checkpoint is running when337  # sqlite3_snapshot_open() is called.338  #339  reset_db340  db close341  testvfs tvfs342  sqlite3 db test.db -vfs tvfs343 344  do_execsql_test $tn.5.1 {345    PRAGMA journal_mode = wal;346    CREATE TABLE x1(x, xx, xxx);347    INSERT INTO x1 VALUES('z', 'zz', 'zzz');348    BEGIN;349      SELECT * FROM x1;350  } {wal z zz zzz}351 352  do_test $tn.5.2 {353    set ::snapshot [snapshot_get db main]354    sqlite3 db2 test.db -vfs tvfs355    execsql {356      INSERT INTO x1 VALUES('a', 'aa', 'aaa');357      COMMIT;358    }359  } {}360 361  set t53 0362  proc write_callback {args} {363    do_test $tn.5.3.[incr ::t53] {364      execsql BEGIN365      list [catch { snapshot_open db main $::snapshot } msg] $msg366    } {1 SQLITE_BUSY}367    catchsql COMMIT368  }369 370  tvfs filter xWrite371  tvfs script write_callback372  db2 eval { PRAGMA wal_checkpoint }373  db close374  db2 close375  tvfs delete376  snapshot_free $snapshot377 378  #-------------------------------------------------------------------------379  # Test that sqlite3_snapshot_get() may be called immediately after380  # "BEGIN; PRAGMA user_version;". And that sqlite3_snapshot_open() may381  # be called after opening the db handle and running the script382  # "PRAGMA user_version; BEGIN".383  reset_db384  do_execsql_test $tn.6.1 {385    PRAGMA journal_mode = wal;386    CREATE TABLE x1(x, xx, xxx);387    INSERT INTO x1 VALUES('z', 'zz', 'zzz');388    BEGIN;389      PRAGMA user_version;390  } {wal 0}391  do_test $tn.6.2 {392    set ::snapshot [snapshot_get db main]393    execsql {394      INSERT INTO x1 VALUES('a', 'aa', 'aaa');395      COMMIT;396    }397  } {}398  do_test $tn.6.3 {399    sqlite3 db2 test.db 400    db2 eval "PRAGMA user_version ; BEGIN"401    snapshot_open db2 main $::snapshot402    db2 eval { SELECT * FROM x1 }403  } {z zz zzz}404  do_test $tn.6.4 {405    db2 close406    sqlite3 db2 test.db 407    db2 eval "PRAGMA application_id"408    db2 eval "BEGIN"409    snapshot_open db2 main $::snapshot410    db2 eval { SELECT * FROM x1 }411  } {z zz zzz}412 413  do_test $tn.6.5 {414    db2 close415    sqlite3 db2 test.db 416    db2 eval "BEGIN"417    list [catch {snapshot_open db2 main $::snapshot} msg] $msg418  } {1 SQLITE_ERROR}419 420  snapshot_free $snapshot421 422  #-------------------------------------------------------------------------423  # The following tests investigate the sqlite3_snapshot_cmp() API.424  #425 426  # Compare snapshots $p1 and $p2, checking that the result is $r.427  #428  proc do_snapshot_cmp_test {tn p1 p2 r} {429    uplevel [list do_test $tn.1 [list snapshot_cmp $p1 $p2] $r]430    uplevel [list do_test $tn.2 [list snapshot_cmp $p2 $p1] [expr $r*-1]]431    uplevel [list do_test $tn.3 [list snapshot_cmp $p1 $p1] 0]432    uplevel [list do_test $tn.4 [list snapshot_cmp $p2 $p2] 0]433  }434 435  catch { db2 close }436  reset_db437 438  do_execsql_test $tn.7.1 {439    PRAGMA journal_mode = wal;440    CREATE TABLE t1(x);441  } wal442 443  do_test $tn.7.1.2 {444    execsql { BEGIN ; PRAGMA application_id }445    set p1 [snapshot_get db main]446    execsql {447      INSERT INTO t1 VALUES(10);448      COMMIT;449    }450    execsql { BEGIN ; PRAGMA application_id }451    set p2 [snapshot_get db main]452    execsql COMMIT453  } {}454 455  do_snapshot_cmp_test $tn.7.1.3 $p1 $p2 -1456  snapshot_free $p1457  snapshot_free $p2458 459  do_execsql_test $tn.7.2.1 {460    INSERT INTO t1 VALUES(11);461    INSERT INTO t1 VALUES(12);462    INSERT INTO t1 VALUES(13);463    BEGIN; 464      PRAGMA application_id;465  } {0}466  do_test $tn.7.2.2 {467    set p1 [snapshot_get db main]468    execsql {469      COMMIT;470      INSERT INTO t1 VALUES(14);471      PRAGMA wal_checkpoint;472      BEGIN;473        PRAGMA application_id;474    }475    set p2 [snapshot_get db main]476    execsql COMMIT477  } {}478 479  do_snapshot_cmp_test $tn.7.2.3 $p1 $p2 -1480  snapshot_free $p2481 482  do_test $tn.7.3.1 {483    execsql {484      INSERT INTO t1 VALUES(14);485      BEGIN;486        PRAGMA application_id;487    }488    set p2 [snapshot_get db main]489    execsql COMMIT490  } {}491 492  do_snapshot_cmp_test $tn.7.3.2 $p1 $p2 -1493  snapshot_free $p1494  snapshot_free $p2495}496 497finish_test498