github.com/jdgcs/sqlite3@v1.12.1-0.20210908114423-bc5f96e4dd51/testdata/tcl/tkt3793.test (about)

     1  # 2009 April 10
     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.
    12  #
    13  # This file implements tests to verify that ticket #3793 has been
    14  # fixed.  
    15  #
    16  
    17  
    18  set testdir [file dirname $argv0]
    19  source $testdir/tester.tcl
    20  
    21  ifcapable !shared_cache||!attach {
    22    finish_test
    23    return
    24  }
    25  set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
    26  
    27  do_test tkt3793-1.1 {
    28    db close
    29    sqlite3 db "file:test.db" -uri 1
    30    sqlite3 db1 "file:test.db?cache=private" -uri 1
    31    sqlite3 db2 "file:test.db?cache=shared" -uri 1
    32    execsql {
    33      BEGIN;
    34      CREATE TABLE t1(a, b);
    35      CREATE TABLE t2(a PRIMARY KEY, b);
    36      INSERT INTO t1 VALUES(randstr(50,50), randstr(50,50));
    37      INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;
    38      INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;
    39      INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;
    40      INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;
    41      INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;
    42      INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;
    43      INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;
    44      INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;
    45      INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;
    46      INSERT INTO t1 SELECT randstr(50,50), randstr(50,50) FROM t1;
    47      INSERT INTO t2 SELECT * FROM t1;
    48      COMMIT;
    49    }
    50  } {}
    51  
    52  proc busyhandler {db args} { set ::busyconnection $db ; return 1 }
    53  db2 busy {busyhandler db2}
    54  db1 busy {busyhandler db1}
    55  
    56  # Establish a read-lock on the database file using connection [db].
    57  #
    58  do_test tkt3793-1.2 {
    59    execsql {
    60      BEGIN;
    61      SELECT count(*) FROM t1;
    62    }
    63  } {1024}
    64  
    65  # Set the size of the cache shared by [db1] and [db2] to 10. Then update
    66  # more than 10 pages of table t1. At this point the shared-cache will
    67  # hold a RESERVED lock on the database file. Even though there are now
    68  # more than 10 dirty pages in memory, it cannot upgrade to an EXCLUSIVE 
    69  # lock because of the read-lock held by [db].
    70  #
    71  do_test tkt3793-1.3 {
    72    execsql {
    73      PRAGMA cache_size = 10;
    74      BEGIN;
    75      UPDATE t1 SET b = randstr(50,50);
    76    } db1
    77  } {}
    78  
    79  set x 0
    80  
    81  # Run one SELECT query on the shared-cache using [db1], then from within 
    82  # the callback run another via [db2]. Because of the large number of dirty
    83  # pages within the cache, each time a new page is read from the database
    84  # SQLite will attempt to upgrade to an EXCLUSIVE lock, and hence invoke
    85  # the busy-handler. The tests here verify that the correct busy-handler
    86  # function is invoked (the busy-handler associated with the database
    87  # connection that called sqlite3_step()). When bug #3793 existed, sometimes
    88  # the [db2] busy-handler was invoked from within the call to sqlite3_step()
    89  # associated with [db1]. 
    90  #
    91  # Note: Before the bug was fixed, if [db2] was opened with the "-fullmutex 1"
    92  # option, then this test case would cause an assert() to fail.
    93  #
    94  ifcapable threadsafe {
    95    set ::busyconnection db1
    96    db1 eval {SELECT * FROM t2 ORDER BY a LIMIT 20} {
    97      do_test tkt3793-2.[incr x] { set ::busyconnection } db1
    98      set ::busyconnection db2
    99    
   100      db2 eval { SELECT count(*) FROM t2 }
   101      do_test tkt3793-2.[incr x] { set ::busyconnection } db2
   102      set ::busyconnection db1
   103    }
   104  }
   105    
   106  do_test tkt3793-3 {
   107    db1 close
   108    db2 close
   109  } {}
   110  
   111  sqlite3_enable_shared_cache $::enable_shared_cache
   112  finish_test