SQLite

Check-in [e0c889d66c]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Fix a problem in shared-cache mode where a COMMIT statement might cause a busy-handler belonging to a shared-cache connection other than the current writer to be invoked.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e0c889d66ccf4af12cc77ac38c1e6477da63ac72
User & Date: dan 2012-10-05 19:43:02.225
Context
2012-10-06
03:48
Changes for WinRT compatibility. Also, allow version resource compilation and embedding to be disabled at compile-time. (check-in: 4b0facc13b user: mistachkin tags: trunk)
2012-10-05
19:43
Fix a problem in shared-cache mode where a COMMIT statement might cause a busy-handler belonging to a shared-cache connection other than the current writer to be invoked. (check-in: e0c889d66c user: dan tags: trunk)
17:44
Merge the shared-cache related fixes from the shared-cache-fix branch to the trunk. (check-in: 698ec7769d user: dan tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/vdbeaux.c.
1766
1767
1768
1769
1770
1771
1772

1773

1774
1775
1776
1777
1778
1779
1780
  ** file is required for an atomic commit.
  */ 
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ 
    Btree *pBt = db->aDb[i].pBt;
    if( sqlite3BtreeIsInTrans(pBt) ){
      needXcommit = 1;
      if( i!=1 ) nTrans++;

      rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt));

    }
  }
  if( rc!=SQLITE_OK ){
    return rc;
  }

  /* If there are any write-transactions at all, invoke the commit hook */







>

>







1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
  ** file is required for an atomic commit.
  */ 
  for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ 
    Btree *pBt = db->aDb[i].pBt;
    if( sqlite3BtreeIsInTrans(pBt) ){
      needXcommit = 1;
      if( i!=1 ) nTrans++;
      sqlite3BtreeEnter(pBt);
      rc = sqlite3PagerExclusiveLock(sqlite3BtreePager(pBt));
      sqlite3BtreeLeave(pBt);
    }
  }
  if( rc!=SQLITE_OK ){
    return rc;
  }

  /* If there are any write-transactions at all, invoke the commit hook */
Changes to test/shared9.test.
12
13
14
15
16
17
18

19
20
21
22
23
24
25
# The tests in this file are intended to show if two connections attach
# to the same shared cache using different database names, views and
# virtual tables may still be accessed.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set testprefix shared9

ifcapable !view||!trigger {
  finish_test
  return
}








>







12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# The tests in this file are intended to show if two connections attach
# to the same shared cache using different database names, views and
# virtual tables may still be accessed.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
set testprefix shared9

ifcapable !view||!trigger {
  finish_test
  return
}

130
131
132
133
134
135
136
137


































































138
139
140
  set ::invoked_mycollate_db1 0
  db2 eval {
    INSERT INTO t1 VALUES('two');
  }
  db2 close
  set ::invoked_mycollate_db1
} {0}



































































sqlite3_enable_shared_cache $::enable_shared_cache
finish_test









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
  set ::invoked_mycollate_db1 0
  db2 eval {
    INSERT INTO t1 VALUES('two');
  }
  db2 close
  set ::invoked_mycollate_db1
} {0}

#-------------------------------------------------------------------------
# This test verifies that a bug causing a busy-handler belonging to one
# shared-cache connection to be executed as a result of an sqlite3_step()
# on another has been fixed.
#
forcedelete test.db test.db2
sqlite3 db1 test.db
sqlite3 db2 test.db

proc busyhandler {handle args} {
  set ::busyhandler_invoked_for $handle
  return 1
}
db1 busy [list busyhandler db1]
db2 busy [list busyhandler db2]

do_test 3.1 {
  db1 eval {
    BEGIN; 
      CREATE TABLE t1(a, b);
      CREATE TABLE t2(a, b);
      INSERT INTO t1 VALUES(1, 2);
      INSERT INTO t2 VALUES(1, 2);
  }
  # Keep this next COMMIT as a separate statement. This ensures that COMMIT
  # has already been compiled and loaded into the tcl interface statement 
  # cache when it is attempted below.
  db1 eval COMMIT
  db1 eval {
    BEGIN;
      INSERT INTO t1 VALUES(3, 4);
  }
} {}

do_test 3.3 {
  set ::tf [launch_testfixture]
  testfixture $::tf {
    sqlite3 db test.db
    db eval {
      BEGIN;
        SELECT * FROM t1;
    }
  }
} {1 2}

do_test 3.2 {
  db2 eval { SELECT * FROM t2 }
} {1 2}

do_test 3.3 {
  list [catch { db1 eval COMMIT } msg] $msg
} {1 {database is locked}}

# At one point the following would fail, showing that the busy-handler
# belonging to [db2] was invoked instead.
do_test 3.4 {
  set ::busyhandler_invoked_for
} {db1}
do_test 3.5 {
  close $::tf
  db1 eval COMMIT
} {}
  
db1 close
db2 close

sqlite3_enable_shared_cache $::enable_shared_cache
finish_test