Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Candidate fixes for problems revealed by notify2.test. Notify2.test is still failing at this point. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | shared-cache-fixes |
Files: | files | file ages | folders |
SHA1: |
ea0428f9b6e63066e7444a2ba2f8c12a |
User & Date: | dan 2013-05-13 18:23:15.893 |
Context
2013-05-14
| ||
23:12 | Fix an assert() in unlockBtreeIfUnused() so that it checks for the existance of an untripped cursor, not for the existance of any cursor at all. (check-in: a6f851d0fe user: drh tags: shared-cache-fixes) | |
20:36 | Avoid deleting a b-tree "has-content" vector belonging to another shared-cache connection from within sqlite3_close(). (check-in: 93462df782 user: dan tags: shared-cache-fixes) | |
2013-05-13
| ||
18:23 | Candidate fixes for problems revealed by notify2.test. Notify2.test is still failing at this point. (check-in: ea0428f9b6 user: dan tags: shared-cache-fixes) | |
2013-05-09
| ||
18:12 | Add assert()s to the implementation of xRead() in the built-in VFSes to verify that the offset parameter is always non-negative. (check-in: cf5c364224 user: drh tags: trunk) | |
Changes
Changes to src/main.c.
︙ | ︙ | |||
832 833 834 835 836 837 838 | /* If a transaction is open, the disconnectAllVtab() call above ** will not have called the xDisconnect() method on any virtual ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() ** call will do so. We need to do this before the check for active ** SQL statements below, as the v-table implementation may be storing ** some prepared statements internally. */ | | | 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 | /* If a transaction is open, the disconnectAllVtab() call above ** will not have called the xDisconnect() method on any virtual ** tables in the db->aVTrans[] array. The following sqlite3VtabRollback() ** call will do so. We need to do this before the check for active ** SQL statements below, as the v-table implementation may be storing ** some prepared statements internally. */ sqlite3RollbackAll(db, SQLITE_ABORT); /* Legacy behavior (sqlite3_close() behavior) is to return ** SQLITE_BUSY if the connection can not be closed immediately. */ if( !forceZombie && connectionIsBusy(db) ){ sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized " "statements or unfinished backups"); |
︙ | ︙ | |||
998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 | ** attempts to use that cursor. */ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ int i; int inTrans = 0; assert( sqlite3_mutex_held(db->mutex) ); sqlite3BeginBenignMalloc(); for(i=0; i<db->nDb; i++){ Btree *p = db->aDb[i].pBt; if( p ){ if( sqlite3BtreeIsInTrans(p) ){ inTrans = 1; } sqlite3BtreeRollback(p, tripCode); db->aDb[i].inTrans = 0; } } sqlite3VtabRollback(db); sqlite3EndBenignMalloc(); if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); } /* Any deferred constraint violations have now been resolved. */ db->nDeferredCons = 0; /* If one has been configured, invoke the rollback-hook callback */ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ db->xRollbackCallback(db->pRollbackArg); | > > | 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 | ** attempts to use that cursor. */ void sqlite3RollbackAll(sqlite3 *db, int tripCode){ int i; int inTrans = 0; assert( sqlite3_mutex_held(db->mutex) ); sqlite3BeginBenignMalloc(); sqlite3BtreeEnterAll(db); for(i=0; i<db->nDb; i++){ Btree *p = db->aDb[i].pBt; if( p ){ if( sqlite3BtreeIsInTrans(p) ){ inTrans = 1; } sqlite3BtreeRollback(p, tripCode); db->aDb[i].inTrans = 0; } } sqlite3VtabRollback(db); sqlite3EndBenignMalloc(); if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){ sqlite3ExpirePreparedStatements(db); sqlite3ResetAllSchemasOfConnection(db); } sqlite3BtreeLeaveAll(db); /* Any deferred constraint violations have now been resolved. */ db->nDeferredCons = 0; /* If one has been configured, invoke the rollback-hook callback */ if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ db->xRollbackCallback(db->pRollbackArg); |
︙ | ︙ |
Added test/sharedA.test.
> > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 | # 2013 May 14 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # # Test some specific circumstances to do with shared cache mode. # set testdir [file dirname $argv0] source $testdir/tester.tcl db close set ::testprefix x set ::enable_shared_cache [sqlite3_enable_shared_cache 1] #------------------------------------------------------------------------- # do_test 1.1 { sqlite3 db1 test.db sqlite3 db2 test.db db2 eval { CREATE TABLE t1(x); INSERT INTO t1 VALUES(123); } db1 eval { SELECT * FROM t1; CREATE INDEX i1 ON t1(x); } } {123} do_test 1.2 { db2 eval { SELECT * FROM t1 ORDER BY x; } db1 eval { BEGIN; DROP INDEX i1; } db1 close db2 eval { SELECT * FROM t1 ORDER BY x; } } {123} do_test 1.3 { db2 close } {} #------------------------------------------------------------------------- # testvfs tvfs tvfs filter xRead tvfs script read_callback proc read_callback {args} { } do_test 2.1 { forcedelete test.db test.db2 sqlite3 db1 test.db -vfs tvfs db1 eval { ATTACH 'test.db2' AS two } db1 eval { CREATE TABLE t1(x); INSERT INTO t1 VALUES(1); INSERT INTO t1 VALUES(2); INSERT INTO t1 VALUES(3); CREATE TABLE two.t2(x); INSERT INTO t2 SELECT * FROM t1; } sqlite3 db2 test.db -vfs tvfs db2 eval { SELECT * FROM t1 } } {1 2 3} do_test 2.2 { set ::STMT [sqlite3_prepare db2 "CREATE INDEX i1 ON t1(x)" -1 tail] set {} {} } {} do_test 2.3 { db1 eval { BEGIN; CREATE INDEX i1 ON t1(x); INSERT INTO t2 VALUES('value!'); } } {} set ::bFired 0 proc read_callback {call file args} { if { $::bFired==0 && [string match *test.db2-journal $file] } { sqlthread spawn ::thread_result [subst -nocommands { sqlite3_step $::STMT set rc [sqlite3_finalize $::STMT] }] after 1000 { set ::bFired 1 } vwait ::bFired } } do_test 2.4 { db1 eval ROLLBACK } {} if {[info exists ::thread_result]==0} { vwait ::thread_result } do_test 2.5 { list $::thread_result [sqlite3_errmsg db2] } {SQLITE_SCHEMA {database schema has changed}} db1 close db2 close tvfs delete sqlite3_enable_shared_cache $::enable_shared_cache finish_test |