modernc.org/cc@v1.0.1/v2/testdata/_sqlite/ext/rbu/rbu12.test (about)

     1  # 2015 February 16
     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  #
    12  
    13  if {![info exists testdir]} {
    14    set testdir [file join [file dirname [info script]] .. .. test]
    15  }
    16  source $testdir/tester.tcl
    17  source $testdir/lock_common.tcl
    18  set ::testprefix rbu12
    19  
    20  set setup_sql {
    21    DROP TABLE IF EXISTS xx;
    22    DROP TABLE IF EXISTS xy;
    23    CREATE TABLE xx(a, b, c PRIMARY KEY);
    24    INSERT INTO xx VALUES(1, 2, 3);
    25    CREATE TABLE xy(a, b, c PRIMARY KEY);
    26  
    27    ATTACH 'rbu.db' AS rbu;
    28      DROP TABLE IF EXISTS data_xx;
    29      CREATE TABLE rbu.data_xx(a, b, c, rbu_control);
    30      INSERT INTO data_xx VALUES(4, 5, 6, 0);
    31      INSERT INTO data_xx VALUES(7, 8, 9, 0);
    32      CREATE TABLE rbu.data_xy(a, b, c, rbu_control);
    33      INSERT INTO data_xy VALUES(10, 11, 12, 0);
    34    DETACH rbu;
    35  }
    36  
    37  do_multiclient_test tn {
    38  
    39    # Initialize a target (test.db) and rbu (rbu.db) database.
    40    #
    41    forcedelete rbu.db
    42    sql1 $setup_sql
    43  
    44    # Using connection 2, open a read transaction on the target database.
    45    # RBU will still be able to generate "test.db-oal", but it will not be
    46    # able to rename it to "test.db-wal".
    47    #
    48    do_test 1.$tn.1 {
    49      sql2 { BEGIN; SELECT * FROM xx; }
    50    } {1 2 3}
    51    do_test 1.$tn.2 {
    52      sqlite3rbu rbu test.db rbu.db
    53      while 1 {
    54        set res [rbu step]
    55        if {$res!="SQLITE_OK"} break
    56      }
    57      set res
    58    } {SQLITE_BUSY}
    59  
    60    do_test 1.$tn.3 { sql2 { SELECT * FROM xx; } } {1 2 3}
    61    do_test 1.$tn.4 { sql2 { SELECT * FROM xy; } } {}
    62    do_test 1.$tn.5 {
    63      list [file exists test.db-wal] [file exists test.db-oal]
    64    } {0 1}
    65    do_test 1.$tn.6 { sql2 COMMIT } {}
    66  
    67    # The rbu object that hit the SQLITE_BUSY error above cannot be reused.
    68    # It is stuck in a permanent SQLITE_BUSY state at this point.
    69    #
    70    do_test 1.$tn.7 { rbu step } {SQLITE_BUSY}
    71    do_test 1.$tn.8 { 
    72      list [catch { rbu close } msg] $msg 
    73    } {1 SQLITE_BUSY}
    74  
    75    do_test 1.$tn.9.1 { sql2 { BEGIN EXCLUSIVE } } {}
    76    do_test 1.$tn.9.2 {
    77      sqlite3rbu rbu test.db rbu.db
    78      rbu step
    79    } {SQLITE_BUSY}
    80    do_test 1.$tn.9.3 {
    81      list [catch { rbu close } msg] $msg 
    82    } {1 {SQLITE_BUSY - database is locked}}
    83    do_test 1.$tn.9.4 { sql2 COMMIT } {}
    84  
    85    sqlite3rbu rbu test.db rbu.db
    86    do_test 1.$tn.10.1 { sql2 { BEGIN EXCLUSIVE } } {}
    87    do_test 1.$tn.10.2 {
    88      rbu step
    89    } {SQLITE_BUSY}
    90    do_test 1.$tn.10.3 {
    91      list [catch { rbu close } msg] $msg 
    92    } {1 SQLITE_BUSY}
    93    do_test 1.$tn.10.4 { sql2 COMMIT } {}
    94  
    95    # A new rbu object can finish the work though.
    96    #
    97    do_test 1.$tn.11 {
    98      sqlite3rbu rbu test.db rbu.db
    99      rbu step
   100    } {SQLITE_OK}
   101    do_test 1.$tn.12 {
   102      list [file exists test.db-wal] [file exists test.db-oal]
   103    } {1 0}
   104    do_test 1.$tn.13 {
   105      while 1 {
   106        set res [rbu step]
   107        if {$res!="SQLITE_OK"} break
   108      }
   109      set res
   110    } {SQLITE_DONE}
   111  
   112    do_test 1.$tn.14 {
   113      rbu close
   114    } {SQLITE_DONE}
   115  }
   116  
   117  do_multiclient_test tn {
   118  
   119    # Initialize a target (test.db) and rbu (rbu.db) database.
   120    #
   121    forcedelete rbu.db
   122    sql1 $setup_sql
   123  
   124    do_test 2.$tn.1 {
   125      sqlite3rbu rbu test.db rbu.db
   126      while {[file exists test.db-wal]==0} {
   127        if {[rbu step]!="SQLITE_OK"} {error "problem here...."}
   128      }
   129      rbu close
   130    } {SQLITE_OK}
   131  
   132  
   133    do_test 2.$tn.2 { sql2 { BEGIN IMMEDIATE } } {}
   134  
   135    do_test 2.$tn.3 { 
   136      sqlite3rbu rbu test.db rbu.db
   137      rbu step 
   138    } {SQLITE_BUSY}
   139  
   140    do_test 2.$tn.4 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY}
   141  
   142    do_test 2.$tn.5 { 
   143      sql2 { SELECT * FROM xx ; COMMIT }
   144    } {1 2 3 4 5 6 7 8 9}
   145  
   146    do_test 2.$tn.6 {
   147      sqlite3rbu rbu test.db rbu.db
   148      rbu step
   149      rbu close
   150    } {SQLITE_OK}
   151  
   152    do_test 2.$tn.7 { sql2 { BEGIN EXCLUSIVE } } {}
   153  
   154    do_test 2.$tn.8 { 
   155      sqlite3rbu rbu test.db rbu.db
   156      rbu step 
   157    } {SQLITE_BUSY}
   158    do_test 2.$tn.9 { list [catch { rbu close } msg] $msg } {1 SQLITE_BUSY}
   159    do_test 2.$tn.10 { 
   160      sql2 { SELECT * FROM xx ; COMMIT }
   161    } {1 2 3 4 5 6 7 8 9}
   162  
   163    do_test 2.$tn.11 {
   164      sqlite3rbu rbu test.db rbu.db
   165      while {[rbu step]=="SQLITE_OK"} {}
   166      rbu close
   167    } {SQLITE_DONE}
   168  
   169  }
   170  
   171  #-------------------------------------------------------------------------
   172  # Test that "PRAGMA data_version" works when an RBU client writes the
   173  # database.
   174  #
   175  do_multiclient_test tn {
   176  
   177    # Initialize a target (test.db) and rbu (rbu.db) database.
   178    #
   179    forcedelete rbu.db
   180    sql1 $setup_sql
   181  
   182    # Check the initial database contains table "xx" with a single row.
   183    # Also save the current values of "PRAGMA data-version" for [db1] 
   184    # and [db2].
   185    #
   186    do_test 2.$tn.1 {
   187      list [sql1 { SELECT count(*) FROM xx }] [sql2 { SELECT count(*) FROM xx }]
   188    } {1 1}
   189    set V1 [sql1 {PRAGMA data_version}] 
   190    set V2 [sql2 {PRAGMA data_version}]
   191  
   192    # Check the values of data-version have not magically changed.
   193    #
   194    do_test 2.$tn.2 {
   195      list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
   196    } [list $V1 $V2]
   197  
   198    # Start stepping the RBU. From the point of view of [db1] and [db2], the 
   199    # data-version values remain unchanged until the database contents are
   200    # modified. At which point the values are incremented.
   201    #
   202    sqlite3rbu rbu test.db rbu.db
   203    set x 0
   204    while {[db one {SELECT count(*) FROM xx}]==1} {
   205      do_test 2.$tn.3.[incr x] {
   206        list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
   207      } [list $V1 $V2]
   208      rbu step
   209    }
   210    do_test 2.$tn.5.1 { expr {$V1 < [sql1 {PRAGMA data_version}]} } 1
   211    do_test 2.$tn.5.2 { expr {$V2 < [sql2 {PRAGMA data_version}]} } 1
   212  
   213    # Check the db contents is as expected.
   214    #
   215    do_test 2.$tn.4 {
   216      list [sql1 {SELECT count(*) FROM xx}] [sql2 {SELECT count(*) FROM xx}]
   217    } {3 3}
   218  
   219    set V1 [sql1 {PRAGMA data_version}] 
   220    set V2 [sql2 {PRAGMA data_version}]
   221  
   222    # Finish applying the RBU (i.e. do the incremental checkpoint). Check that
   223    # this does not cause the data-version values to change.
   224    #
   225    while {[rbu step]=="SQLITE_OK"} { }
   226    rbu close
   227  
   228    do_test 2.$tn.6 {
   229      list [sql1 {PRAGMA data_version}] [sql2 {PRAGMA data_version}]
   230    } [list $V1 $V2]
   231  
   232  }
   233  
   234  finish_test
   235