1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/persistentdata/persistentstorage/sqlite3api/TEST/TclScript/incrblob2.test Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,409 @@
1.4 +# 2008 June 9
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 +# Test that it is possible to have two open blob handles on a single
1.16 +# blob object.
1.17 +#
1.18 +# $Id: incrblob2.test,v 1.8 2008/06/28 15:33:26 danielk1977 Exp $
1.19 +#
1.20 +
1.21 +set testdir [file dirname $argv0]
1.22 +source $testdir/tester.tcl
1.23 +
1.24 +ifcapable {!autovacuum || !pragma || !incrblob} {
1.25 + finish_test
1.26 + return
1.27 +}
1.28 +
1.29 +do_test incrblob2-1.0 {
1.30 + execsql {
1.31 + CREATE TABLE blobs(id INTEGER PRIMARY KEY, data BLOB);
1.32 + INSERT INTO blobs VALUES(NULL, zeroblob(5000));
1.33 + INSERT INTO blobs VALUES(NULL, zeroblob(5000));
1.34 + INSERT INTO blobs VALUES(NULL, zeroblob(5000));
1.35 + INSERT INTO blobs VALUES(NULL, zeroblob(5000));
1.36 + }
1.37 +} {}
1.38 +
1.39 +foreach iOffset [list 0 256 4094] {
1.40 + do_test incrblob2-1.$iOffset.1 {
1.41 + set fd [db incrblob blobs data 1]
1.42 + puts $fd "[string repeat x $iOffset]SQLite version 3.6.0"
1.43 + close $fd
1.44 + } {}
1.45 +
1.46 + do_test incrblob2-1.$iOffset.2 {
1.47 + set fd1 [db incrblob blobs data 1]
1.48 + set fd2 [db incrblob blobs data 1]
1.49 + fconfigure $fd1 -buffering none
1.50 + fconfigure $fd2 -buffering none
1.51 + if {$iOffset != 0} {
1.52 + seek $fd2 $iOffset start
1.53 + seek $fd1 $iOffset start
1.54 + }
1.55 + read $fd1 6
1.56 + } {SQLite}
1.57 +
1.58 + do_test incrblob2-1.$iOffset.3 {
1.59 + read $fd2 6
1.60 + } {SQLite}
1.61 +
1.62 + do_test incrblob2-1.$iOffset.4 {
1.63 + seek $fd2 $iOffset start
1.64 + seek $fd1 $iOffset start
1.65 + puts -nonewline $fd2 "etiLQS"
1.66 + } {}
1.67 +
1.68 +
1.69 + do_test incrblob2-1.$iOffset.5 {
1.70 + seek $fd1 $iOffset start
1.71 + read $fd1 6
1.72 + } {etiLQS}
1.73 +
1.74 + do_test incrblob2-1.$iOffset.6 {
1.75 + seek $fd2 $iOffset start
1.76 + read $fd2 6
1.77 + } {etiLQS}
1.78 +
1.79 + do_test incrblob2-1.$iOffset.7 {
1.80 + seek $fd1 $iOffset start
1.81 + read $fd1 6
1.82 + } {etiLQS}
1.83 +
1.84 + do_test incrblob2-1.$iOffset.8 {
1.85 + close $fd1
1.86 + close $fd2
1.87 + } {}
1.88 +}
1.89 +
1.90 +#--------------------------------------------------------------------------
1.91 +
1.92 +foreach iOffset [list 0 256 4094] {
1.93 +
1.94 + do_test incrblob2-2.$iOffset.1 {
1.95 + set fd1 [db incrblob blobs data 1]
1.96 + seek $fd1 [expr $iOffset - 5000] end
1.97 + fconfigure $fd1 -buffering none
1.98 +
1.99 + set fd2 [db incrblob blobs data 1]
1.100 + seek $fd2 [expr $iOffset - 5000] end
1.101 + fconfigure $fd2 -buffering none
1.102 +
1.103 + puts -nonewline $fd1 "123456"
1.104 + } {}
1.105 +
1.106 + do_test incrblob2-2.$iOffset.2 {
1.107 + read $fd2 6
1.108 + } {123456}
1.109 +
1.110 + do_test incrblob2-2.$iOffset.3 {
1.111 + close $fd1
1.112 + close $fd2
1.113 + } {}
1.114 +}
1.115 +
1.116 +do_test incrblob2-3.1 {
1.117 + set fd1 [db incrblob blobs data 1]
1.118 + fconfigure $fd1 -buffering none
1.119 +} {}
1.120 +do_test incrblob2-3.2 {
1.121 + execsql {
1.122 + INSERT INTO blobs VALUES(5, zeroblob(10240));
1.123 + }
1.124 +} {}
1.125 +do_test incrblob2-3.3 {
1.126 + set rc [catch { read $fd1 6 } msg]
1.127 + list $rc $msg
1.128 +} {0 123456}
1.129 +do_test incrblob2-3.4 {
1.130 + close $fd1
1.131 +} {}
1.132 +
1.133 +#--------------------------------------------------------------------------
1.134 +# The following tests - incrblob2-4.* - test that blob handles are
1.135 +# invalidated at the correct times.
1.136 +#
1.137 +do_test incrblob2-4.1 {
1.138 + unset -nocomplain data
1.139 + db eval BEGIN
1.140 + db eval { CREATE TABLE t1(id INTEGER PRIMARY KEY, data BLOB); }
1.141 + for {set ii 1} {$ii < 100} {incr ii} {
1.142 + set data [string repeat "blob$ii" 500]
1.143 + db eval { INSERT INTO t1 VALUES($ii, $data) }
1.144 + }
1.145 + db eval COMMIT
1.146 +} {}
1.147 +
1.148 +proc aborted_handles {} {
1.149 + global handles
1.150 +
1.151 + set aborted {}
1.152 + for {set ii 1} {$ii < 100} {incr ii} {
1.153 + set str "blob$ii"
1.154 + set nByte [string length $str]
1.155 + set iOffset [expr $nByte * $ii * 2]
1.156 +
1.157 + set rc [catch {sqlite3_blob_read $handles($ii) $iOffset $nByte} msg]
1.158 + if {$rc && $msg eq "SQLITE_ABORT"} {
1.159 + lappend aborted $ii
1.160 + } else {
1.161 + if {$rc || $msg ne $str} {
1.162 + error "blob $ii: $msg"
1.163 + }
1.164 + }
1.165 + }
1.166 + set aborted
1.167 +}
1.168 +
1.169 +do_test incrblob2-4.2 {
1.170 + for {set ii 1} {$ii < 100} {incr ii} {
1.171 + set handles($ii) [db incrblob t1 data $ii]
1.172 + }
1.173 + aborted_handles
1.174 +} {}
1.175 +
1.176 +# Update row 3. This should abort handle 3 but leave all others untouched.
1.177 +#
1.178 +do_test incrblob2-4.3 {
1.179 + db eval {UPDATE t1 SET data = data || '' WHERE id = 3}
1.180 + aborted_handles
1.181 +} {3}
1.182 +
1.183 +# Test that a write to handle 3 also returns SQLITE_ABORT.
1.184 +#
1.185 +do_test incrblob2-4.3.1 {
1.186 + set rc [catch {sqlite3_blob_write $::handles(3) 10 HELLO} msg]
1.187 + list $rc $msg
1.188 +} {1 SQLITE_ABORT}
1.189 +
1.190 +# Delete row 14. This should abort handle 6 but leave all others untouched.
1.191 +#
1.192 +do_test incrblob2-4.4 {
1.193 + db eval {DELETE FROM t1 WHERE id = 14}
1.194 + aborted_handles
1.195 +} {3 14}
1.196 +
1.197 +# Change the rowid of row 15 to 102. Should abort handle 15.
1.198 +#
1.199 +do_test incrblob2-4.5 {
1.200 + db eval {UPDATE t1 SET id = 102 WHERE id = 15}
1.201 + aborted_handles
1.202 +} {3 14 15}
1.203 +
1.204 +# Clobber row 92 using INSERT OR REPLACE.
1.205 +#
1.206 +do_test incrblob2-4.6 {
1.207 + db eval {INSERT OR REPLACE INTO t1 VALUES(92, zeroblob(1000))}
1.208 + aborted_handles
1.209 +} {3 14 15 92}
1.210 +
1.211 +# Clobber row 65 using UPDATE OR REPLACE on row 35. This should abort
1.212 +# handles 35 and 65.
1.213 +#
1.214 +do_test incrblob2-4.7 {
1.215 + db eval {UPDATE OR REPLACE t1 SET id = 65 WHERE id = 35}
1.216 + aborted_handles
1.217 +} {3 14 15 35 65 92}
1.218 +
1.219 +# Insert a couple of new rows. This should not invalidate any handles.
1.220 +#
1.221 +do_test incrblob2-4.9 {
1.222 + db eval {INSERT INTO t1 SELECT NULL, data FROM t1}
1.223 + aborted_handles
1.224 +} {3 14 15 35 65 92}
1.225 +
1.226 +# Delete all rows from 1 to 25. This should abort all handles up to 25.
1.227 +#
1.228 +do_test incrblob2-4.9 {
1.229 + db eval {DELETE FROM t1 WHERE id >=1 AND id <= 25}
1.230 + aborted_handles
1.231 +} {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 35 65 92}
1.232 +
1.233 +# Delete the whole table (this will use sqlite3BtreeClearTable()). All handles
1.234 +# should now be aborted.
1.235 +#
1.236 +do_test incrblob2-4.10 {
1.237 + db eval {DELETE FROM t1}
1.238 + aborted_handles
1.239 +} {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}
1.240 +
1.241 +do_test incrblob2-4.1.X {
1.242 + for {set ii 1} {$ii < 100} {incr ii} {
1.243 + close $handles($ii)
1.244 + }
1.245 +} {}
1.246 +
1.247 +#--------------------------------------------------------------------------
1.248 +# The following tests - incrblob2-5.* - test that in shared cache an open
1.249 +# blob handle counts as a read-lock on its table.
1.250 +#
1.251 +ifcapable shared_cache {
1.252 + db close
1.253 + set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
1.254 +
1.255 + do_test incrblob2-5.1 {
1.256 + sqlite3 db test.db
1.257 + sqlite3 db2 test.db
1.258 +
1.259 + execsql {
1.260 + INSERT INTO t1 VALUES(1, 'abcde');
1.261 + }
1.262 + } {}
1.263 +
1.264 + do_test incrblob2-5.2 {
1.265 + catchsql { INSERT INTO t1 VALUES(2, 'fghij') } db2
1.266 + } {0 {}}
1.267 +
1.268 + do_test incrblob2-5.3 {
1.269 + set blob [db incrblob t1 data 1]
1.270 + catchsql { INSERT INTO t1 VALUES(3, 'klmno') } db2
1.271 + } {1 {database is locked}}
1.272 +
1.273 + do_test incrblob2-5.4 {
1.274 + close $blob
1.275 + execsql BEGIN db2
1.276 + catchsql { INSERT INTO t1 VALUES(4, 'pqrst') } db2
1.277 + } {0 {}}
1.278 +
1.279 + do_test incrblob2-5.5 {
1.280 + set blob [db incrblob -readonly t1 data 1]
1.281 + catchsql { INSERT INTO t1 VALUES(5, 'uvwxy') } db2
1.282 + } {1 {database table is locked}}
1.283 +
1.284 + do_test incrblob2-5.6 {
1.285 + close $blob
1.286 + catchsql { INSERT INTO t1 VALUES(3, 'klmno') } db2
1.287 + } {0 {}}
1.288 +
1.289 + db2 close
1.290 + db close
1.291 + sqlite3_enable_shared_cache $::enable_shared_cache
1.292 +}
1.293 +
1.294 +#--------------------------------------------------------------------------
1.295 +# The following tests - incrblob2-6.* - test a specific scenario that might
1.296 +# be causing an error.
1.297 +#
1.298 +sqlite3 db test.db
1.299 +do_test incrblob2-6.1 {
1.300 + execsql {
1.301 + DELETE FROM t1;
1.302 + INSERT INTO t1 VALUES(1, zeroblob(100));
1.303 + }
1.304 +
1.305 + set rdHandle [db incrblob -readonly t1 data 1]
1.306 + set wrHandle [db incrblob t1 data 1]
1.307 +
1.308 + sqlite3_blob_read $rdHandle 0 100
1.309 +
1.310 + sqlite3_blob_write $wrHandle 0 ABCDEF
1.311 +
1.312 + close $wrHandle
1.313 + close $rdHandle
1.314 +} {}
1.315 +
1.316 +do_test incrblob2-6.2 {
1.317 + set rdHandle [db incrblob -readonly t1 data 1]
1.318 + sqlite3_blob_read $rdHandle 0 2
1.319 +} {AB}
1.320 +
1.321 +do_test incrblob2-6.3 {
1.322 + set wrHandle [db incrblob t1 data 1]
1.323 + sqlite3_blob_write $wrHandle 0 ZZZZZZZZZZ
1.324 + sqlite3_blob_read $rdHandle 2 4
1.325 +} {ZZZZ}
1.326 +
1.327 +do_test incrblob2-6.4 {
1.328 + close $wrHandle
1.329 + close $rdHandle
1.330 +} {}
1.331 +
1.332 +sqlite3_memory_highwater 1
1.333 +do_test incrblob2-7.1 {
1.334 + db eval {
1.335 + CREATE TABLE t2(B BLOB);
1.336 + INSERT INTO t2 VALUES(zeroblob(10 * 1024 * 1024));
1.337 + }
1.338 + expr {[sqlite3_memory_highwater]<(5 * 1024 * 1024)}
1.339 +} {1}
1.340 +
1.341 +do_test incrblob2-7.2 {
1.342 + set h [db incrblob t2 B 1]
1.343 + expr {[sqlite3_memory_highwater]<(5 * 1024 * 1024)}
1.344 +} {1}
1.345 +
1.346 +do_test incrblob2-7.3 {
1.347 + seek $h 0 end
1.348 + tell $h
1.349 +} [expr 10 * 1024 * 1024]
1.350 +
1.351 +do_test incrblob2-7.4 {
1.352 + expr {[sqlite3_memory_highwater]<(5 * 1024 * 1024)}
1.353 +} {1}
1.354 +
1.355 +do_test incrblob2-7.5 {
1.356 + close $h
1.357 +} {}
1.358 +
1.359 +#---------------------------------------------------------------------------
1.360 +# The following tests, incrblob2-8.*, test that nothing terrible happens
1.361 +# when a statement transaction is rolled back while there are open
1.362 +# incremental-blob handles. At one point an assert() was failing when
1.363 +# this was attempted.
1.364 +#
1.365 +do_test incrblob2-8.1 {
1.366 + execsql BEGIN
1.367 + set h [db incrblob t2 B 1]
1.368 + set rc [catch {
1.369 + db eval {SELECT ROWID FROM t2} { execsql "DROP TABLE t2" }
1.370 + } msg]
1.371 + list $rc $msg
1.372 +} {1 {database table is locked}}
1.373 +do_test incrblob2-8.2 {
1.374 + close $h
1.375 + execsql COMMIT
1.376 +} {}
1.377 +do_test incrblob2-8.3 {
1.378 + execsql {
1.379 + CREATE TABLE t3(a INTEGER UNIQUE, b TEXT);
1.380 + INSERT INTO t3 VALUES(1, 'aaaaaaaaaaaaaaaaaaaa');
1.381 + INSERT INTO t3 VALUES(2, 'bbbbbbbbbbbbbbbbbbbb');
1.382 + INSERT INTO t3 VALUES(3, 'cccccccccccccccccccc');
1.383 + INSERT INTO t3 VALUES(4, 'dddddddddddddddddddd');
1.384 + INSERT INTO t3 VALUES(5, 'eeeeeeeeeeeeeeeeeeee');
1.385 + }
1.386 +} {}
1.387 +do_test incrblob2-8.4 {
1.388 + execsql BEGIN
1.389 + set h [db incrblob t3 b 3]
1.390 + sqlite3_blob_read $h 0 20
1.391 +} {cccccccccccccccccccc}
1.392 +do_test incrblob2-8.5 {
1.393 + catchsql {UPDATE t3 SET a = 6 WHERE a > 3}
1.394 +} {1 {column a is not unique}}
1.395 +do_test incrblob2-8.6 {
1.396 + catchsql {UPDATE t3 SET a = 6 WHERE a > 3}
1.397 +} {1 {column a is not unique}}
1.398 +do_test incrblob2-8.7 {
1.399 + sqlite3_blob_read $h 0 20
1.400 +} {cccccccccccccccccccc}
1.401 +do_test incrblob2-8.8 {
1.402 + catchsql {UPDATE t3 SET a = 6 WHERE a = 3 OR a = 5}
1.403 +} {1 {column a is not unique}}
1.404 +do_test incrblob2-8.9 {
1.405 + set rc [catch {sqlite3_blob_read $h 0 20} msg]
1.406 + list $rc $msg
1.407 +} {1 SQLITE_ABORT}
1.408 +do_test incrblob2-8.X {
1.409 + close $h
1.410 +} {}
1.411 +
1.412 +finish_test