1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TclScript/shared_err.test Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,519 @@
1.4 +# 2005 December 30
1.5 +#
1.6 +# The author disclaims copyright to this source code. In place of
1.7 +# a legal notice, here is a blessing:
1.8 +#
1.9 +# May you do good and not evil.
1.10 +# May you find forgiveness for yourself and forgive others.
1.11 +# May you share freely, never taking more than you give.
1.12 +#
1.13 +#***********************************************************************
1.14 +#
1.15 +# The focus of the tests in this file are IO errors that occur in a shared
1.16 +# cache context. What happens to connection B if one connection A encounters
1.17 +# an IO-error whilst reading or writing the file-system?
1.18 +#
1.19 +# $Id: shared_err.test,v 1.23 2008/09/29 14:12:57 danielk1977 Exp $
1.20 +
1.21 +proc skip {args} {}
1.22 +
1.23 +
1.24 +set testdir [file dirname $argv0]
1.25 +source $testdir/tester.tcl
1.26 +source $testdir/malloc_common.tcl
1.27 +db close
1.28 +
1.29 +ifcapable !shared_cache||!subquery {
1.30 + finish_test
1.31 + return
1.32 +}
1.33 +
1.34 +set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
1.35 +
1.36 +do_ioerr_test shared_ioerr-1 -tclprep {
1.37 + sqlite3 db2 test.db
1.38 + execsql {
1.39 + PRAGMA read_uncommitted = 1;
1.40 + CREATE TABLE t1(a,b,c);
1.41 + BEGIN;
1.42 + SELECT * FROM sqlite_master;
1.43 + } db2
1.44 +} -sqlbody {
1.45 + SELECT * FROM sqlite_master;
1.46 + INSERT INTO t1 VALUES(1,2,3);
1.47 + BEGIN TRANSACTION;
1.48 + INSERT INTO t1 VALUES(1,2,3);
1.49 + INSERT INTO t1 VALUES(4,5,6);
1.50 + ROLLBACK;
1.51 + SELECT * FROM t1;
1.52 + BEGIN TRANSACTION;
1.53 + INSERT INTO t1 VALUES(1,2,3);
1.54 + INSERT INTO t1 VALUES(4,5,6);
1.55 + COMMIT;
1.56 + SELECT * FROM t1;
1.57 + DELETE FROM t1 WHERE a<100;
1.58 +} -cleanup {
1.59 + do_test shared_ioerr-1.$n.cleanup.1 {
1.60 + set res [catchsql {
1.61 + SELECT * FROM t1;
1.62 + } db2]
1.63 + set possible_results [list \
1.64 + "1 {disk I/O error}" \
1.65 + "0 {1 2 3}" \
1.66 + "0 {1 2 3 1 2 3 4 5 6}" \
1.67 + "0 {1 2 3 1 2 3 4 5 6 1 2 3 4 5 6}" \
1.68 + "0 {}" \
1.69 + "1 {database disk image is malformed}" \
1.70 + ]
1.71 + set rc [expr [lsearch -exact $possible_results $res] >= 0]
1.72 + if {$rc != 1} {
1.73 + puts ""
1.74 + puts "Result: $res"
1.75 + }
1.76 + set rc
1.77 + } {1}
1.78 +
1.79 + # The "database disk image is malformed" is a special case that can
1.80 + # occur if an IO error occurs during a rollback in the {SELECT * FROM t1}
1.81 + # statement above. This test is to make sure there is no real database
1.82 + # corruption.
1.83 + db2 close
1.84 + do_test shared_ioerr-1.$n.cleanup.2 {
1.85 + execsql {pragma integrity_check} db
1.86 + } {ok}
1.87 +}
1.88 +
1.89 +do_ioerr_test shared_ioerr-2 -tclprep {
1.90 + sqlite3 db2 test.db
1.91 + execsql {
1.92 + PRAGMA read_uncommitted = 1;
1.93 + BEGIN;
1.94 + CREATE TABLE t1(a, b);
1.95 + INSERT INTO t1(oid) VALUES(NULL);
1.96 + INSERT INTO t1(oid) SELECT NULL FROM t1;
1.97 + INSERT INTO t1(oid) SELECT NULL FROM t1;
1.98 + INSERT INTO t1(oid) SELECT NULL FROM t1;
1.99 + INSERT INTO t1(oid) SELECT NULL FROM t1;
1.100 + INSERT INTO t1(oid) SELECT NULL FROM t1;
1.101 + INSERT INTO t1(oid) SELECT NULL FROM t1;
1.102 + INSERT INTO t1(oid) SELECT NULL FROM t1;
1.103 + INSERT INTO t1(oid) SELECT NULL FROM t1;
1.104 + INSERT INTO t1(oid) SELECT NULL FROM t1;
1.105 + INSERT INTO t1(oid) SELECT NULL FROM t1;
1.106 + UPDATE t1 set a = oid, b = 'abcdefghijklmnopqrstuvwxyz0123456789';
1.107 + CREATE INDEX i1 ON t1(a);
1.108 + COMMIT;
1.109 + BEGIN;
1.110 + SELECT * FROM sqlite_master;
1.111 + } db2
1.112 +} -tclbody {
1.113 + set ::residx 0
1.114 + execsql {DELETE FROM t1 WHERE 0 = (a % 2);}
1.115 + incr ::residx
1.116 +
1.117 + # When this transaction begins the table contains 512 entries. The
1.118 + # two statements together add 512+146 more if it succeeds.
1.119 + # (1024/7==146)
1.120 + execsql {BEGIN;}
1.121 + execsql {INSERT INTO t1 SELECT a+1, b FROM t1;}
1.122 + execsql {INSERT INTO t1 SELECT 'string' || a, b FROM t1 WHERE 0 = (a%7);}
1.123 + execsql {COMMIT;}
1.124 +
1.125 + incr ::residx
1.126 +} -cleanup {
1.127 + catchsql ROLLBACK
1.128 + do_test shared_ioerr-2.$n.cleanup.1 {
1.129 + set res [catchsql {
1.130 + SELECT max(a), min(a), count(*) FROM (SELECT a FROM t1 order by a);
1.131 + } db2]
1.132 + set possible_results [list \
1.133 + {0 {1024 1 1024}} \
1.134 + {0 {1023 1 512}} \
1.135 + {0 {string994 1 1170}} \
1.136 + ]
1.137 + set idx [lsearch -exact $possible_results $res]
1.138 + set success [expr {$idx==$::residx || $res=="1 {disk I/O error}"}]
1.139 + if {!$success} {
1.140 + puts ""
1.141 + puts "Result: \"$res\" ($::residx)"
1.142 + }
1.143 + set success
1.144 + } {1}
1.145 + db2 close
1.146 +}
1.147 +
1.148 +# This test is designed to provoke an IO error when a cursor position is
1.149 +# "saved" (because another cursor is going to modify the underlying table).
1.150 +#
1.151 +do_ioerr_test shared_ioerr-3 -tclprep {
1.152 + sqlite3 db2 test.db
1.153 + execsql {
1.154 + PRAGMA read_uncommitted = 1;
1.155 + PRAGMA cache_size = 10;
1.156 + BEGIN;
1.157 + CREATE TABLE t1(a, b, UNIQUE(a, b));
1.158 + } db2
1.159 + for {set i 0} {$i < 200} {incr i} {
1.160 + set a [string range [string repeat "[format %03d $i]." 5] 0 end-1]
1.161 +
1.162 + set b [string repeat $i 2000]
1.163 + execsql {INSERT INTO t1 VALUES($a, $b)} db2
1.164 + }
1.165 + execsql {COMMIT} db2
1.166 + set ::DB2 [sqlite3_connection_pointer db2]
1.167 + set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
1.168 + sqlite3_step $::STMT ;# Cursor points at 000.000.000.000
1.169 + sqlite3_step $::STMT ;# Cursor points at 001.001.001.001
1.170 +
1.171 +} -tclbody {
1.172 + execsql {
1.173 + BEGIN;
1.174 + INSERT INTO t1 VALUES('201.201.201.201.201', NULL);
1.175 + UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%';
1.176 + COMMIT;
1.177 + }
1.178 +} -cleanup {
1.179 + set ::steprc [sqlite3_step $::STMT]
1.180 + set ::column [sqlite3_column_text $::STMT 0]
1.181 + set ::finalrc [sqlite3_finalize $::STMT]
1.182 +
1.183 + # There are three possible outcomes here (assuming persistent IO errors):
1.184 + #
1.185 + # 1. If the [sqlite3_step] did not require any IO (required pages in
1.186 + # the cache), then the next row ("002...") may be retrieved
1.187 + # successfully.
1.188 + #
1.189 + # 2. If the [sqlite3_step] does require IO, then [sqlite3_step] returns
1.190 + # SQLITE_ERROR and [sqlite3_finalize] returns IOERR.
1.191 + #
1.192 + # 3. If, after the initial IO error, SQLite tried to rollback the
1.193 + # active transaction and a second IO error was encountered, then
1.194 + # statement $::STMT will have been aborted. This means [sqlite3_stmt]
1.195 + # returns SQLITE_ABORT, and the statement cursor does not move. i.e.
1.196 + # [sqlite3_column] still returns the current row ("001...") and
1.197 + # [sqlite3_finalize] returns SQLITE_OK.
1.198 + #
1.199 +
1.200 + do_test shared_ioerr-3.$n.cleanup.1 {
1.201 + expr {
1.202 + $::steprc eq "SQLITE_ROW" ||
1.203 + $::steprc eq "SQLITE_ERROR" ||
1.204 + $::steprc eq "SQLITE_ABORT"
1.205 + }
1.206 + } {1}
1.207 + do_test shared_ioerr-3.$n.cleanup.2 {
1.208 + expr {
1.209 + ($::steprc eq "SQLITE_ROW" && $::column eq "002.002.002.002.002") ||
1.210 + ($::steprc eq "SQLITE_ERROR" && $::column eq "") ||
1.211 + ($::steprc eq "SQLITE_ABORT" && $::column eq "001.001.001.001.001")
1.212 + }
1.213 + } {1}
1.214 + do_test shared_ioerr-3.$n.cleanup.3 {
1.215 + expr {
1.216 + ($::steprc eq "SQLITE_ROW" && $::finalrc eq "SQLITE_OK") ||
1.217 + ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_IOERR") ||
1.218 + ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_ABORT")
1.219 + }
1.220 + } {1}
1.221 +
1.222 +# db2 eval {select * from sqlite_master}
1.223 + db2 close
1.224 +}
1.225 +
1.226 +# This is a repeat of the previous test except that this time we
1.227 +# are doing a reverse-order scan of the table when the cursor is
1.228 +# "saved".
1.229 +#
1.230 +do_ioerr_test shared_ioerr-3rev -tclprep {
1.231 + sqlite3 db2 test.db
1.232 + execsql {
1.233 + PRAGMA read_uncommitted = 1;
1.234 + PRAGMA cache_size = 10;
1.235 + BEGIN;
1.236 + CREATE TABLE t1(a, b, UNIQUE(a, b));
1.237 + } db2
1.238 + for {set i 0} {$i < 200} {incr i} {
1.239 + set a [string range [string repeat "[format %03d $i]." 5] 0 end-1]
1.240 +
1.241 + set b [string repeat $i 2000]
1.242 + execsql {INSERT INTO t1 VALUES($a, $b)} db2
1.243 + }
1.244 + execsql {COMMIT} db2
1.245 + set ::DB2 [sqlite3_connection_pointer db2]
1.246 + set ::STMT [sqlite3_prepare $::DB2 \
1.247 + "SELECT a FROM t1 ORDER BY a DESC" -1 DUMMY]
1.248 + sqlite3_step $::STMT ;# Cursor points at 199.199.199.199.199
1.249 + sqlite3_step $::STMT ;# Cursor points at 198.198.198.198.198
1.250 +
1.251 +} -tclbody {
1.252 + execsql {
1.253 + BEGIN;
1.254 + INSERT INTO t1 VALUES('201.201.201.201.201', NULL);
1.255 + UPDATE t1 SET a = '202.202.202.202.202' WHERE a LIKE '201%';
1.256 + COMMIT;
1.257 + }
1.258 +} -cleanup {
1.259 + set ::steprc [sqlite3_step $::STMT]
1.260 + set ::column [sqlite3_column_text $::STMT 0]
1.261 + set ::finalrc [sqlite3_finalize $::STMT]
1.262 +
1.263 + # There are three possible outcomes here (assuming persistent IO errors):
1.264 + #
1.265 + # 1. If the [sqlite3_step] did not require any IO (required pages in
1.266 + # the cache), then the next row ("002...") may be retrieved
1.267 + # successfully.
1.268 + #
1.269 + # 2. If the [sqlite3_step] does require IO, then [sqlite3_step] returns
1.270 + # SQLITE_ERROR and [sqlite3_finalize] returns IOERR.
1.271 + #
1.272 + # 3. If, after the initial IO error, SQLite tried to rollback the
1.273 + # active transaction and a second IO error was encountered, then
1.274 + # statement $::STMT will have been aborted. This means [sqlite3_stmt]
1.275 + # returns SQLITE_ABORT, and the statement cursor does not move. i.e.
1.276 + # [sqlite3_column] still returns the current row ("001...") and
1.277 + # [sqlite3_finalize] returns SQLITE_OK.
1.278 + #
1.279 +
1.280 + do_test shared_ioerr-3rev.$n.cleanup.1 {
1.281 + expr {
1.282 + $::steprc eq "SQLITE_ROW" ||
1.283 + $::steprc eq "SQLITE_ERROR" ||
1.284 + $::steprc eq "SQLITE_ABORT"
1.285 + }
1.286 + } {1}
1.287 + do_test shared_ioerr-3rev.$n.cleanup.2 {
1.288 + expr {
1.289 + ($::steprc eq "SQLITE_ROW" && $::column eq "197.197.197.197.197") ||
1.290 + ($::steprc eq "SQLITE_ERROR" && $::column eq "") ||
1.291 + ($::steprc eq "SQLITE_ABORT" && $::column eq "198.198.198.198.198")
1.292 + }
1.293 + } {1}
1.294 + do_test shared_ioerr-3rev.$n.cleanup.3 {
1.295 + expr {
1.296 + ($::steprc eq "SQLITE_ROW" && $::finalrc eq "SQLITE_OK") ||
1.297 + ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_IOERR") ||
1.298 + ($::steprc eq "SQLITE_ERROR" && $::finalrc eq "SQLITE_ABORT")
1.299 + }
1.300 + } {1}
1.301 +
1.302 +# db2 eval {select * from sqlite_master}
1.303 + db2 close
1.304 +}
1.305 +
1.306 +# Provoke a malloc() failure when a cursor position is being saved. This
1.307 +# only happens with index cursors (because they malloc() space to save the
1.308 +# current key value). It does not happen with tables, because an integer
1.309 +# key does not require a malloc() to store.
1.310 +#
1.311 +# The library should return an SQLITE_NOMEM to the caller. The query that
1.312 +# owns the cursor (the one for which the position is not saved) should
1.313 +# continue unaffected.
1.314 +#
1.315 +do_malloc_test shared_err-4 -tclprep {
1.316 + sqlite3 db2 test.db
1.317 + execsql {
1.318 + PRAGMA read_uncommitted = 1;
1.319 + BEGIN;
1.320 + CREATE TABLE t1(a, b, UNIQUE(a, b));
1.321 + } db2
1.322 + for {set i 0} {$i < 5} {incr i} {
1.323 + set a [string repeat $i 10]
1.324 + set b [string repeat $i 2000]
1.325 + execsql {INSERT INTO t1 VALUES($a, $b)} db2
1.326 + }
1.327 + execsql {COMMIT} db2
1.328 + set ::DB2 [sqlite3_connection_pointer db2]
1.329 + set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
1.330 + sqlite3_step $::STMT ;# Cursor points at 0000000000
1.331 + sqlite3_step $::STMT ;# Cursor points at 1111111111
1.332 +} -tclbody {
1.333 + execsql {
1.334 + INSERT INTO t1 VALUES(6, NULL);
1.335 + }
1.336 +} -cleanup {
1.337 + do_test shared_malloc-4.$::n.cleanup.1 {
1.338 + set ::rc [sqlite3_step $::STMT]
1.339 + expr {$::rc=="SQLITE_ROW" || $::rc=="SQLITE_ERROR"}
1.340 + } {1}
1.341 + if {$::rc=="SQLITE_ROW"} {
1.342 + do_test shared_malloc-4.$::n.cleanup.2 {
1.343 + sqlite3_column_text $::STMT 0
1.344 + } {2222222222}
1.345 + }
1.346 + do_test shared_malloc-4.$::n.cleanup.3 {
1.347 + set rc [sqlite3_finalize $::STMT]
1.348 + expr {$rc=="SQLITE_OK" || $rc=="SQLITE_ABORT" ||
1.349 + $rc=="SQLITE_NOMEM" || $rc=="SQLITE_IOERR"}
1.350 + } {1}
1.351 +# db2 eval {select * from sqlite_master}
1.352 + db2 close
1.353 +}
1.354 +
1.355 +do_malloc_test shared_err-5 -tclbody {
1.356 + db close
1.357 + sqlite3 dbX test.db
1.358 + sqlite3 dbY test.db
1.359 + dbX close
1.360 + dbY close
1.361 +} -cleanup {
1.362 + catch {dbX close}
1.363 + catch {dbY close}
1.364 +}
1.365 +
1.366 +do_malloc_test shared_err-6 -tclbody {
1.367 + catch {db close}
1.368 + sqlite3_thread_cleanup
1.369 + sqlite3_enable_shared_cache 0
1.370 +} -cleanup {
1.371 + sqlite3_enable_shared_cache 1
1.372 +}
1.373 +
1.374 +# As of 3.5.0, sqlite3_enable_shared_cache can be called at
1.375 +# any time and from any thread
1.376 +#do_test shared_err-misuse-7.1 {
1.377 +# sqlite3 db test.db
1.378 +# catch {
1.379 +# sqlite3_enable_shared_cache 0
1.380 +# } msg
1.381 +# set msg
1.382 +#} {library routine called out of sequence}
1.383 +
1.384 +# Again provoke a malloc() failure when a cursor position is being saved,
1.385 +# this time during a ROLLBACK operation by some other handle.
1.386 +#
1.387 +# The library should return an SQLITE_NOMEM to the caller. The query that
1.388 +# owns the cursor (the one for which the position is not saved) should
1.389 +# be aborted.
1.390 +#
1.391 +set ::aborted 0
1.392 +do_malloc_test shared_err-8 -tclprep {
1.393 + sqlite3 db2 test.db
1.394 + execsql {
1.395 + PRAGMA read_uncommitted = 1;
1.396 + BEGIN;
1.397 + CREATE TABLE t1(a, b, UNIQUE(a, b));
1.398 + } db2
1.399 + for {set i 0} {$i < 2} {incr i} {
1.400 + set a [string repeat $i 10]
1.401 + set b [string repeat $i 2000]
1.402 + execsql {INSERT INTO t1 VALUES($a, $b)} db2
1.403 + }
1.404 + execsql {COMMIT} db2
1.405 + set ::DB2 [sqlite3_connection_pointer db2]
1.406 + set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
1.407 + sqlite3_step $::STMT ;# Cursor points at 0000000000
1.408 + sqlite3_step $::STMT ;# Cursor points at 1111111111
1.409 +} -tclbody {
1.410 + execsql {
1.411 + BEGIN;
1.412 + INSERT INTO t1 VALUES(6, NULL);
1.413 + ROLLBACK;
1.414 + }
1.415 +} -cleanup {
1.416 + # UPDATE: As of [5668], if the rollback fails SQLITE_CORRUPT is returned.
1.417 + # So these tests have been updated to expect SQLITE_CORRUPT and its
1.418 + # associated English language error message.
1.419 + #
1.420 + do_test shared_malloc-8.$::n.cleanup.1 {
1.421 + set res [catchsql {SELECT a FROM t1} db2]
1.422 + set ans [lindex $res 1]
1.423 + if {[lindex $res 0]} {
1.424 + set r [expr {
1.425 + $ans=="disk I/O error" ||
1.426 + $ans=="out of memory" ||
1.427 + $ans=="database disk image is malformed"
1.428 + }]
1.429 + } else {
1.430 + set r [expr {[lrange $ans 0 1]=="0000000000 1111111111"}]
1.431 + }
1.432 + } {1}
1.433 + do_test shared_malloc-8.$::n.cleanup.2 {
1.434 + set rc1 [sqlite3_step $::STMT]
1.435 + set rc2 [sqlite3_finalize $::STMT]
1.436 + if {$rc2=="SQLITE_ABORT"} {
1.437 + incr ::aborted
1.438 + }
1.439 + expr {
1.440 + ($rc1=="SQLITE_DONE" && $rc2=="SQLITE_OK") ||
1.441 + ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_ABORT") ||
1.442 + ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_NOMEM") ||
1.443 + ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_IOERR") ||
1.444 + ($rc1=="SQLITE_ERROR" && $rc2=="SQLITE_CORRUPT")
1.445 + }
1.446 + } {1}
1.447 + db2 close
1.448 +}
1.449 +do_test shared_malloc-8.X {
1.450 + # Test that one or more queries were aborted due to the malloc() failure.
1.451 + expr $::aborted>=1
1.452 +} {1}
1.453 +
1.454 +# This test is designed to catch a specific bug that was present during
1.455 +# development of 3.5.0. If a malloc() failed while setting the page-size,
1.456 +# a buffer (Pager.pTmpSpace) was being freed. This could cause a seg-fault
1.457 +# later if another connection tried to use the pager.
1.458 +#
1.459 +# This test will crash 3.4.2.
1.460 +#
1.461 +do_malloc_test shared_err-9 -tclprep {
1.462 + sqlite3 db2 test.db
1.463 +} -sqlbody {
1.464 + PRAGMA page_size = 4096;
1.465 + PRAGMA page_size = 1024;
1.466 +} -cleanup {
1.467 + db2 eval {
1.468 + CREATE TABLE abc(a, b, c);
1.469 + BEGIN;
1.470 + INSERT INTO abc VALUES(1, 2, 3);
1.471 + ROLLBACK;
1.472 + }
1.473 + db2 close
1.474 +}
1.475 +
1.476 +catch {db close}
1.477 +catch {db2 close}
1.478 +do_malloc_test shared_err-10 -tclprep {
1.479 + sqlite3 db test.db
1.480 + sqlite3 db2 test.db
1.481 +
1.482 + db eval { SELECT * FROM sqlite_master }
1.483 + db2 eval {
1.484 + BEGIN;
1.485 + CREATE TABLE abc(a, b, c);
1.486 + }
1.487 +} -tclbody {
1.488 + catch {db eval {SELECT * FROM sqlite_master}}
1.489 + error 1
1.490 +} -cleanup {
1.491 + execsql { SELECT * FROM sqlite_master }
1.492 +}
1.493 +
1.494 +do_malloc_test shared_err-11 -tclprep {
1.495 + sqlite3 db test.db
1.496 + sqlite3 db2 test.db
1.497 +
1.498 + db eval { SELECT * FROM sqlite_master }
1.499 + db2 eval {
1.500 + BEGIN;
1.501 + CREATE TABLE abc(a, b, c);
1.502 + }
1.503 +} -tclbody {
1.504 + catch {db eval {SELECT * FROM sqlite_master}}
1.505 + catch {sqlite3_errmsg16 db}
1.506 + error 1
1.507 +} -cleanup {
1.508 + execsql { SELECT * FROM sqlite_master }
1.509 +}
1.510 +
1.511 +catch {db close}
1.512 +catch {db2 close}
1.513 +
1.514 +do_malloc_test shared_err-12 -sqlbody {
1.515 + CREATE TABLE abc(a, b, c);
1.516 + INSERT INTO abc VALUES(1, 2, 3);
1.517 +}
1.518 +
1.519 +catch {db close}
1.520 +catch {db2 close}
1.521 +sqlite3_enable_shared_cache $::enable_shared_cache
1.522 +finish_test