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

     1  # 2012 October 5
     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  # The tests in this file are intended to show if two connections attach
    13  # to the same shared cache using different database names, views and
    14  # virtual tables may still be accessed.
    15  #
    16  
    17  set testdir [file dirname $argv0]
    18  source $testdir/tester.tcl
    19  source $testdir/lock_common.tcl
    20  set testprefix shared9
    21  
    22  ifcapable !view||!trigger {
    23    finish_test
    24    return
    25  }
    26  
    27  db close
    28  set enable_shared_cache [sqlite3_enable_shared_cache 1]
    29  
    30  sqlite3 db1 test.db
    31  sqlite3 db2 test.db
    32  forcedelete test.db2
    33  
    34  do_test 1.1 {
    35    db1 eval {
    36      ATTACH 'test.db2' AS 'fred';
    37      CREATE TABLE fred.t1(a, b, c);
    38      CREATE VIEW fred.v1 AS SELECT * FROM t1;
    39  
    40      CREATE TABLE fred.t2(a, b);
    41      CREATE TABLE fred.t3(a, b);
    42      CREATE TRIGGER fred.trig AFTER INSERT ON t2 BEGIN
    43        DELETE FROM t3;
    44        INSERT INTO t3 SELECT * FROM t2;
    45      END;
    46      INSERT INTO t2 VALUES(1, 2);
    47      SELECT * FROM t3;
    48    }
    49  } {1 2}
    50  
    51  do_test 1.2 { db2 eval "ATTACH 'test.db2' AS 'jones'" } {}
    52  do_test 1.3 { db2 eval "SELECT * FROM v1"             } {}
    53  do_test 1.4 { db2 eval "INSERT INTO t2 VALUES(3, 4)"  } {}
    54  
    55  ifcapable fts3 {
    56    do_test 1.5 {
    57      db1 eval {
    58        CREATE VIRTUAL TABLE fred.t4 USING fts4;
    59        INSERT INTO t4 VALUES('hello world');
    60      }
    61    } {}
    62  
    63    do_test 1.6 {
    64      db2 eval {
    65        INSERT INTO t4 VALUES('shared cache');
    66        SELECT * FROM t4 WHERE t4 MATCH 'hello';
    67      }
    68    } {{hello world}}
    69  
    70    do_test 1.7 {
    71      db1 eval {
    72        SELECT * FROM t4 WHERE t4 MATCH 'c*';
    73      }
    74    } {{shared cache}}
    75  }
    76  
    77  db1 close
    78  db2 close
    79  
    80  #-------------------------------------------------------------------------
    81  # The following tests attempt to find a similar problem with collation 
    82  # sequence names - pointers to database handle specific allocations leaking 
    83  # into schema objects and being used after the original handle has been
    84  # closed.
    85  #
    86  forcedelete test.db test.db2
    87  sqlite3 db1 test.db
    88  sqlite3 db2 test.db
    89  foreach x {collate1 collate2 collate3} {
    90    proc $x {a b} { string compare $a $b }
    91    db1 collate $x $x
    92    db2 collate $x $x
    93  }
    94  do_test 2.1 {
    95    db1 eval {
    96      CREATE TABLE t1(a, b, c COLLATE collate1);
    97      CREATE INDEX i1 ON t1(a COLLATE collate2, c, b);
    98    }
    99  } {}
   100  do_test 2.2 {
   101    db1 close
   102    db2 eval "INSERT INTO t1 VALUES('abc', 'def', 'ghi')"
   103  } {}
   104  db2 close
   105  
   106  #-------------------------------------------------------------------------
   107  # At one point, the following would cause a collation sequence belonging
   108  # to connection [db1] to be invoked by a call to [db2 eval]. Which is a
   109  # problem if [db1] has already been closed.
   110  #
   111  forcedelete test.db test.db2
   112  sqlite3 db1 test.db
   113  sqlite3 db2 test.db
   114  
   115  proc mycollate_db1 {a b} {set ::invoked_mycollate_db1 1 ; string compare $a $b}
   116  proc mycollate_db2 {a b} {string compare $a $b}
   117  
   118  db1 collate mycollate mycollate_db1
   119  db2 collate mycollate mycollate_db2
   120  
   121  do_test 2.3 {
   122    set ::invoked_mycollate_db1 0
   123    db1 eval {
   124      CREATE TABLE t1(a COLLATE mycollate, CHECK (a IN ('one', 'two', 'three')));
   125      INSERT INTO t1 VALUES('one');
   126    }
   127    db1 close
   128    set ::invoked_mycollate_db1
   129  } {1}
   130  do_test 2.4 {
   131    set ::invoked_mycollate_db1 0
   132    db2 eval {
   133      INSERT INTO t1 VALUES('two');
   134    }
   135    db2 close
   136    set ::invoked_mycollate_db1
   137  } {0}
   138  
   139  forcedelete test.db test.db2
   140  sqlite3 db1 test.db
   141  sqlite3 db2 test.db
   142  db1 collate mycollate mycollate_db1
   143  db2 collate mycollate mycollate_db2
   144  
   145  do_test 2.13 {
   146    set ::invoked_mycollate_db1 0
   147    db1 eval {
   148      CREATE TABLE t1(a, CHECK (a COLLATE mycollate IN ('one', 'two', 'three')));
   149      INSERT INTO t1 VALUES('one');
   150    }
   151    db1 close
   152    set ::invoked_mycollate_db1
   153  } {1}
   154  do_test 2.14 {
   155    set ::invoked_mycollate_db1 0
   156    db2 eval {
   157      INSERT INTO t1 VALUES('two');
   158    }
   159    db2 close
   160    set ::invoked_mycollate_db1
   161  } {0}
   162  
   163  #-------------------------------------------------------------------------
   164  # This test verifies that a bug causing a busy-handler belonging to one
   165  # shared-cache connection to be executed as a result of an sqlite3_step()
   166  # on another has been fixed.
   167  #
   168  forcedelete test.db test.db2
   169  sqlite3 db1 test.db
   170  sqlite3 db2 test.db
   171  
   172  proc busyhandler {handle args} {
   173    set ::busyhandler_invoked_for $handle
   174    return 1
   175  }
   176  db1 busy [list busyhandler db1]
   177  db2 busy [list busyhandler db2]
   178  
   179  do_test 3.1 {
   180    db1 eval {
   181      BEGIN; 
   182        CREATE TABLE t1(a, b);
   183        CREATE TABLE t2(a, b);
   184        INSERT INTO t1 VALUES(1, 2);
   185        INSERT INTO t2 VALUES(1, 2);
   186    }
   187    # Keep this next COMMIT as a separate statement. This ensures that COMMIT
   188    # has already been compiled and loaded into the tcl interface statement 
   189    # cache when it is attempted below.
   190    db1 eval COMMIT
   191    db1 eval {
   192      BEGIN;
   193        INSERT INTO t1 VALUES(3, 4);
   194    }
   195  } {}
   196  
   197  do_test 3.2 {
   198    set ::tf [launch_testfixture]
   199    testfixture $::tf {
   200      sqlite3 db test.db
   201      db eval {
   202        BEGIN;
   203          SELECT * FROM t1;
   204      }
   205    }
   206  } {1 2}
   207  
   208  do_test 3.3 {
   209    db2 eval { SELECT * FROM t2 }
   210  } {1 2}
   211  
   212  do_test 3.4 {
   213    list [catch { db1 eval COMMIT } msg] $msg
   214  } {1 {database is locked}}
   215  
   216  # At one point the following would fail, showing that the busy-handler
   217  # belonging to [db2] was invoked instead.
   218  do_test 3.5 {
   219    set ::busyhandler_invoked_for
   220  } {db1}
   221  do_test 3.6 {
   222    close $::tf
   223    db1 eval COMMIT
   224  } {}
   225    
   226  db1 close
   227  db2 close
   228  
   229  sqlite3_enable_shared_cache $::enable_shared_cache
   230  finish_test