| OLD | NEW |
| (Empty) |
| 1 # 2010 June 15 | |
| 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 | |
| 13 set testdir [file dirname $argv0] | |
| 14 source $testdir/tester.tcl | |
| 15 source $testdir/lock_common.tcl | |
| 16 source $testdir/malloc_common.tcl | |
| 17 source $testdir/wal_common.tcl | |
| 18 set testprefix pager1 | |
| 19 | |
| 20 # Do not use a codec for tests in this file, as the database file is | |
| 21 # manipulated directly using tcl scripts (using the [hexio_write] command). | |
| 22 # | |
| 23 do_not_use_codec | |
| 24 | |
| 25 # | |
| 26 # pager1-1.*: Test inter-process locking (clients in multiple processes). | |
| 27 # | |
| 28 # pager1-2.*: Test intra-process locking (multiple clients in this process). | |
| 29 # | |
| 30 # pager1-3.*: Savepoint related tests. | |
| 31 # | |
| 32 # pager1-4.*: Hot-journal related tests. | |
| 33 # | |
| 34 # pager1-5.*: Cases related to multi-file commits. | |
| 35 # | |
| 36 # pager1-6.*: Cases related to "PRAGMA max_page_count" | |
| 37 # | |
| 38 # pager1-7.*: Cases specific to "PRAGMA journal_mode=TRUNCATE" | |
| 39 # | |
| 40 # pager1-8.*: Cases using temporary and in-memory databases. | |
| 41 # | |
| 42 # pager1-9.*: Tests related to the backup API. | |
| 43 # | |
| 44 # pager1-10.*: Test that the assumed file-system sector-size is limited to | |
| 45 # 64KB. | |
| 46 # | |
| 47 # pager1-12.*: Tests involving "PRAGMA page_size" | |
| 48 # | |
| 49 # pager1-13.*: Cases specific to "PRAGMA journal_mode=PERSIST" | |
| 50 # | |
| 51 # pager1-14.*: Cases specific to "PRAGMA journal_mode=OFF" | |
| 52 # | |
| 53 # pager1-15.*: Varying sqlite3_vfs.szOsFile | |
| 54 # | |
| 55 # pager1-16.*: Varying sqlite3_vfs.mxPathname | |
| 56 # | |
| 57 # pager1-17.*: Tests related to "PRAGMA omit_readlock" | |
| 58 # (The omit_readlock pragma has been removed and so have | |
| 59 # these tests.) | |
| 60 # | |
| 61 # pager1-18.*: Test that the pager layer responds correctly if the b-tree | |
| 62 # requests an invalid page number (due to db corruption). | |
| 63 # | |
| 64 | |
| 65 proc recursive_select {id table {script {}}} { | |
| 66 set cnt 0 | |
| 67 db eval "SELECT rowid, * FROM $table WHERE rowid = ($id-1)" { | |
| 68 recursive_select $rowid $table $script | |
| 69 incr cnt | |
| 70 } | |
| 71 if {$cnt==0} { eval $script } | |
| 72 } | |
| 73 | |
| 74 set a_string_counter 1 | |
| 75 proc a_string {n} { | |
| 76 global a_string_counter | |
| 77 incr a_string_counter | |
| 78 string range [string repeat "${a_string_counter}." $n] 1 $n | |
| 79 } | |
| 80 db func a_string a_string | |
| 81 | |
| 82 do_multiclient_test tn { | |
| 83 | |
| 84 # Create and populate a database table using connection [db]. Check | |
| 85 # that connections [db2] and [db3] can see the schema and content. | |
| 86 # | |
| 87 do_test pager1-$tn.1 { | |
| 88 sql1 { | |
| 89 CREATE TABLE t1(a PRIMARY KEY, b); | |
| 90 CREATE INDEX i1 ON t1(b); | |
| 91 INSERT INTO t1 VALUES(1, 'one'); INSERT INTO t1 VALUES(2, 'two'); | |
| 92 } | |
| 93 } {} | |
| 94 do_test pager1-$tn.2 { sql2 { SELECT * FROM t1 } } {1 one 2 two} | |
| 95 do_test pager1-$tn.3 { sql3 { SELECT * FROM t1 } } {1 one 2 two} | |
| 96 | |
| 97 # Open a transaction and add a row using [db]. This puts [db] in | |
| 98 # RESERVED state. Check that connections [db2] and [db3] can still | |
| 99 # read the database content as it was before the transaction was | |
| 100 # opened. [db] should see the inserted row. | |
| 101 # | |
| 102 do_test pager1-$tn.4 { | |
| 103 sql1 { | |
| 104 BEGIN; | |
| 105 INSERT INTO t1 VALUES(3, 'three'); | |
| 106 } | |
| 107 } {} | |
| 108 do_test pager1-$tn.5 { sql2 { SELECT * FROM t1 } } {1 one 2 two} | |
| 109 do_test pager1-$tn.7 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} | |
| 110 | |
| 111 # [db] still has an open write transaction. Check that this prevents | |
| 112 # other connections (specifically [db2]) from writing to the database. | |
| 113 # | |
| 114 # Even if [db2] opens a transaction first, it may not write to the | |
| 115 # database. After the attempt to write the db within a transaction, | |
| 116 # [db2] is left with an open transaction, but not a read-lock on | |
| 117 # the main database. So it does not prevent [db] from committing. | |
| 118 # | |
| 119 do_test pager1-$tn.8 { | |
| 120 csql2 { UPDATE t1 SET a = a + 10 } | |
| 121 } {1 {database is locked}} | |
| 122 do_test pager1-$tn.9 { | |
| 123 csql2 { | |
| 124 BEGIN; | |
| 125 UPDATE t1 SET a = a + 10; | |
| 126 } | |
| 127 } {1 {database is locked}} | |
| 128 | |
| 129 # Have [db] commit its transactions. Check the other connections can | |
| 130 # now see the new database content. | |
| 131 # | |
| 132 do_test pager1-$tn.10 { sql1 { COMMIT } } {} | |
| 133 do_test pager1-$tn.11 { sql1 { SELECT * FROM t1 } } {1 one 2 two 3 three} | |
| 134 do_test pager1-$tn.12 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} | |
| 135 do_test pager1-$tn.13 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} | |
| 136 | |
| 137 # Check that, as noted above, [db2] really did keep an open transaction | |
| 138 # after the attempt to write the database failed. | |
| 139 # | |
| 140 do_test pager1-$tn.14 { | |
| 141 csql2 { BEGIN } | |
| 142 } {1 {cannot start a transaction within a transaction}} | |
| 143 do_test pager1-$tn.15 { sql2 { ROLLBACK } } {} | |
| 144 | |
| 145 # Have [db2] open a transaction and take a read-lock on the database. | |
| 146 # Check that this prevents [db] from writing to the database (outside | |
| 147 # of any transaction). After this fails, check that [db3] can read | |
| 148 # the db (showing that [db] did not take a PENDING lock etc.) | |
| 149 # | |
| 150 do_test pager1-$tn.15 { | |
| 151 sql2 { BEGIN; SELECT * FROM t1; } | |
| 152 } {1 one 2 two 3 three} | |
| 153 do_test pager1-$tn.16 { | |
| 154 csql1 { UPDATE t1 SET a = a + 10 } | |
| 155 } {1 {database is locked}} | |
| 156 do_test pager1-$tn.17 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} | |
| 157 | |
| 158 # This time, have [db] open a transaction before writing the database. | |
| 159 # This works - [db] gets a RESERVED lock which does not conflict with | |
| 160 # the SHARED lock [db2] is holding. | |
| 161 # | |
| 162 do_test pager1-$tn.18 { | |
| 163 sql1 { | |
| 164 BEGIN; | |
| 165 UPDATE t1 SET a = a + 10; | |
| 166 } | |
| 167 } {} | |
| 168 do_test pager1-$tn-19 { | |
| 169 sql1 { PRAGMA lock_status } | |
| 170 } {main reserved temp closed} | |
| 171 do_test pager1-$tn-20 { | |
| 172 sql2 { PRAGMA lock_status } | |
| 173 } {main shared temp closed} | |
| 174 | |
| 175 # Check that all connections can still read the database. Only [db] sees | |
| 176 # the updated content (as the transaction has not been committed yet). | |
| 177 # | |
| 178 do_test pager1-$tn.21 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} | |
| 179 do_test pager1-$tn.22 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} | |
| 180 do_test pager1-$tn.23 { sql3 { SELECT * FROM t1 } } {1 one 2 two 3 three} | |
| 181 | |
| 182 # Because [db2] still has the SHARED lock, [db] is unable to commit the | |
| 183 # transaction. If it tries, an error is returned and the connection | |
| 184 # upgrades to a PENDING lock. | |
| 185 # | |
| 186 # Once this happens, [db] can read the database and see the new content, | |
| 187 # [db2] (still holding SHARED) can still read the old content, but [db3] | |
| 188 # (not holding any lock) is prevented by [db]'s PENDING from reading | |
| 189 # the database. | |
| 190 # | |
| 191 do_test pager1-$tn.24 { csql1 { COMMIT } } {1 {database is locked}} | |
| 192 do_test pager1-$tn-25 { | |
| 193 sql1 { PRAGMA lock_status } | |
| 194 } {main pending temp closed} | |
| 195 do_test pager1-$tn.26 { sql1 { SELECT * FROM t1 } } {11 one 12 two 13 three} | |
| 196 do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {1 one 2 two 3 three} | |
| 197 do_test pager1-$tn.28 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} | |
| 198 | |
| 199 # Have [db2] commit its read transaction, releasing the SHARED lock it | |
| 200 # is holding. Now, neither [db2] nor [db3] may read the database (as [db] | |
| 201 # is still holding a PENDING). | |
| 202 # | |
| 203 do_test pager1-$tn.29 { sql2 { COMMIT } } {} | |
| 204 do_test pager1-$tn.30 { csql2 { SELECT * FROM t1 } } {1 {database is locked}} | |
| 205 do_test pager1-$tn.31 { csql3 { SELECT * FROM t1 } } {1 {database is locked}} | |
| 206 | |
| 207 # [db] is now able to commit the transaction. Once the transaction is | |
| 208 # committed, all three connections can read the new content. | |
| 209 # | |
| 210 do_test pager1-$tn.25 { sql1 { UPDATE t1 SET a = a+10 } } {} | |
| 211 do_test pager1-$tn.26 { sql1 { COMMIT } } {} | |
| 212 do_test pager1-$tn.27 { sql1 { SELECT * FROM t1 } } {21 one 22 two 23 three} | |
| 213 do_test pager1-$tn.27 { sql2 { SELECT * FROM t1 } } {21 one 22 two 23 three} | |
| 214 do_test pager1-$tn.28 { sql3 { SELECT * FROM t1 } } {21 one 22 two 23 three} | |
| 215 | |
| 216 # Install a busy-handler for connection [db]. | |
| 217 # | |
| 218 set ::nbusy [list] | |
| 219 proc busy {n} { | |
| 220 lappend ::nbusy $n | |
| 221 if {$n>5} { sql2 COMMIT } | |
| 222 return 0 | |
| 223 } | |
| 224 db busy busy | |
| 225 | |
| 226 do_test pager1-$tn.29 { | |
| 227 sql1 { BEGIN ; INSERT INTO t1 VALUES('x', 'y') } | |
| 228 } {} | |
| 229 do_test pager1-$tn.30 { | |
| 230 sql2 { BEGIN ; SELECT * FROM t1 } | |
| 231 } {21 one 22 two 23 three} | |
| 232 do_test pager1-$tn.31 { sql1 COMMIT } {} | |
| 233 do_test pager1-$tn.32 { set ::nbusy } {0 1 2 3 4 5 6} | |
| 234 } | |
| 235 | |
| 236 #------------------------------------------------------------------------- | |
| 237 # Savepoint related test cases. | |
| 238 # | |
| 239 # pager1-3.1.2.*: Force a savepoint rollback to cause the database file | |
| 240 # to grow. | |
| 241 # | |
| 242 # pager1-3.1.3.*: Use a journal created in synchronous=off mode as part | |
| 243 # of a savepoint rollback. | |
| 244 # | |
| 245 do_test pager1-3.1.1 { | |
| 246 faultsim_delete_and_reopen | |
| 247 execsql { | |
| 248 CREATE TABLE t1(a PRIMARY KEY, b); | |
| 249 CREATE TABLE counter( | |
| 250 i CHECK (i<5), | |
| 251 u CHECK (u<10) | |
| 252 ); | |
| 253 INSERT INTO counter VALUES(0, 0); | |
| 254 CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN | |
| 255 UPDATE counter SET i = i+1; | |
| 256 END; | |
| 257 CREATE TRIGGER tr2 AFTER UPDATE ON t1 BEGIN | |
| 258 UPDATE counter SET u = u+1; | |
| 259 END; | |
| 260 } | |
| 261 execsql { SELECT * FROM counter } | |
| 262 } {0 0} | |
| 263 | |
| 264 do_execsql_test pager1-3.1.2 { | |
| 265 PRAGMA cache_size = 10; | |
| 266 BEGIN; | |
| 267 INSERT INTO t1 VALUES(1, randomblob(1500)); | |
| 268 INSERT INTO t1 VALUES(2, randomblob(1500)); | |
| 269 INSERT INTO t1 VALUES(3, randomblob(1500)); | |
| 270 SELECT * FROM counter; | |
| 271 } {3 0} | |
| 272 do_catchsql_test pager1-3.1.3 { | |
| 273 INSERT INTO t1 SELECT a+3, randomblob(1500) FROM t1 | |
| 274 } {1 {CHECK constraint failed: counter}} | |
| 275 do_execsql_test pager1-3.4 { SELECT * FROM counter } {3 0} | |
| 276 do_execsql_test pager1-3.5 { SELECT a FROM t1 } {1 2 3} | |
| 277 do_execsql_test pager1-3.6 { COMMIT } {} | |
| 278 | |
| 279 foreach {tn sql tcl} { | |
| 280 7 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 0 } { | |
| 281 testvfs tv -default 1 | |
| 282 tv devchar safe_append | |
| 283 } | |
| 284 8 { PRAGMA synchronous = NORMAL ; PRAGMA temp_store = 2 } { | |
| 285 testvfs tv -default 1 | |
| 286 tv devchar sequential | |
| 287 } | |
| 288 9 { PRAGMA synchronous = FULL } { } | |
| 289 10 { PRAGMA synchronous = NORMAL } { } | |
| 290 11 { PRAGMA synchronous = OFF } { } | |
| 291 12 { PRAGMA synchronous = FULL ; PRAGMA fullfsync = 1 } { } | |
| 292 13 { PRAGMA synchronous = FULL } { | |
| 293 testvfs tv -default 1 | |
| 294 tv devchar sequential | |
| 295 } | |
| 296 14 { PRAGMA locking_mode = EXCLUSIVE } { | |
| 297 } | |
| 298 } { | |
| 299 do_test pager1-3.$tn.1 { | |
| 300 eval $tcl | |
| 301 faultsim_delete_and_reopen | |
| 302 db func a_string a_string | |
| 303 execsql $sql | |
| 304 execsql { | |
| 305 PRAGMA auto_vacuum = 2; | |
| 306 PRAGMA cache_size = 10; | |
| 307 CREATE TABLE z(x INTEGER PRIMARY KEY, y); | |
| 308 BEGIN; | |
| 309 INSERT INTO z VALUES(NULL, a_string(800)); | |
| 310 INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 2 | |
| 311 INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 4 | |
| 312 INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 8 | |
| 313 INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 16 | |
| 314 INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 32 | |
| 315 INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 64 | |
| 316 INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 128 | |
| 317 INSERT INTO z SELECT NULL, a_string(800) FROM z; -- 256 | |
| 318 COMMIT; | |
| 319 } | |
| 320 execsql { PRAGMA auto_vacuum } | |
| 321 } {2} | |
| 322 do_execsql_test pager1-3.$tn.2 { | |
| 323 BEGIN; | |
| 324 INSERT INTO z VALUES(NULL, a_string(800)); | |
| 325 INSERT INTO z VALUES(NULL, a_string(800)); | |
| 326 SAVEPOINT one; | |
| 327 UPDATE z SET y = NULL WHERE x>256; | |
| 328 PRAGMA incremental_vacuum; | |
| 329 SELECT count(*) FROM z WHERE x < 100; | |
| 330 ROLLBACK TO one; | |
| 331 COMMIT; | |
| 332 } {99} | |
| 333 | |
| 334 do_execsql_test pager1-3.$tn.3 { | |
| 335 BEGIN; | |
| 336 SAVEPOINT one; | |
| 337 UPDATE z SET y = y||x; | |
| 338 ROLLBACK TO one; | |
| 339 COMMIT; | |
| 340 SELECT count(*) FROM z; | |
| 341 } {258} | |
| 342 | |
| 343 do_execsql_test pager1-3.$tn.4 { | |
| 344 SAVEPOINT one; | |
| 345 UPDATE z SET y = y||x; | |
| 346 ROLLBACK TO one; | |
| 347 } {} | |
| 348 do_execsql_test pager1-3.$tn.5 { | |
| 349 SELECT count(*) FROM z; | |
| 350 RELEASE one; | |
| 351 PRAGMA integrity_check; | |
| 352 } {258 ok} | |
| 353 | |
| 354 do_execsql_test pager1-3.$tn.6 { | |
| 355 SAVEPOINT one; | |
| 356 RELEASE one; | |
| 357 } {} | |
| 358 | |
| 359 db close | |
| 360 catch { tv delete } | |
| 361 } | |
| 362 | |
| 363 #------------------------------------------------------------------------- | |
| 364 # Hot journal rollback related test cases. | |
| 365 # | |
| 366 # pager1.4.1.*: Test that the pager module deletes very small invalid | |
| 367 # journal files. | |
| 368 # | |
| 369 # pager1.4.2.*: Test that if the master journal pointer at the end of a | |
| 370 # hot-journal file appears to be corrupt (checksum does not | |
| 371 # compute) the associated journal is rolled back (and no | |
| 372 # xAccess() call to check for the presence of any master | |
| 373 # journal file is made). | |
| 374 # | |
| 375 # pager1.4.3.*: Test that the contents of a hot-journal are ignored if the | |
| 376 # page-size or sector-size in the journal header appear to | |
| 377 # be invalid (too large, too small or not a power of 2). | |
| 378 # | |
| 379 # pager1.4.4.*: Test hot-journal rollback of journal file with a master | |
| 380 # journal pointer generated in various "PRAGMA synchronous" | |
| 381 # modes. | |
| 382 # | |
| 383 # pager1.4.5.*: Test that hot-journal rollback stops if it encounters a | |
| 384 # journal-record for which the checksum fails. | |
| 385 # | |
| 386 # pager1.4.6.*: Test that when rolling back a hot-journal that contains a | |
| 387 # master journal pointer, the master journal file is deleted | |
| 388 # after all the hot-journals that refer to it are deleted. | |
| 389 # | |
| 390 # pager1.4.7.*: Test that if a hot-journal file exists but a client can | |
| 391 # open it for reading only, the database cannot be accessed and | |
| 392 # SQLITE_CANTOPEN is returned. | |
| 393 # | |
| 394 do_test pager1.4.1.1 { | |
| 395 faultsim_delete_and_reopen | |
| 396 execsql { | |
| 397 CREATE TABLE x(y, z); | |
| 398 INSERT INTO x VALUES(1, 2); | |
| 399 } | |
| 400 set fd [open test.db-journal w] | |
| 401 puts -nonewline $fd "helloworld" | |
| 402 close $fd | |
| 403 file exists test.db-journal | |
| 404 } {1} | |
| 405 do_test pager1.4.1.2 { execsql { SELECT * FROM x } } {1 2} | |
| 406 do_test pager1.4.1.3 { file exists test.db-journal } {0} | |
| 407 | |
| 408 # Set up a [testvfs] to snapshot the file-system just before SQLite | |
| 409 # deletes the master-journal to commit a multi-file transaction. | |
| 410 # | |
| 411 # In subsequent test cases, invoking [faultsim_restore_and_reopen] sets | |
| 412 # up the file system to contain two databases, two hot-journal files and | |
| 413 # a master-journal. | |
| 414 # | |
| 415 do_test pager1.4.2.1 { | |
| 416 testvfs tstvfs -default 1 | |
| 417 tstvfs filter xDelete | |
| 418 tstvfs script xDeleteCallback | |
| 419 proc xDeleteCallback {method file args} { | |
| 420 set file [file tail $file] | |
| 421 if { [string match *mj* $file] } { faultsim_save } | |
| 422 } | |
| 423 faultsim_delete_and_reopen | |
| 424 db func a_string a_string | |
| 425 execsql { | |
| 426 ATTACH 'test.db2' AS aux; | |
| 427 PRAGMA journal_mode = DELETE; | |
| 428 PRAGMA main.cache_size = 10; | |
| 429 PRAGMA aux.cache_size = 10; | |
| 430 CREATE TABLE t1(a UNIQUE, b UNIQUE); | |
| 431 CREATE TABLE aux.t2(a UNIQUE, b UNIQUE); | |
| 432 INSERT INTO t1 VALUES(a_string(200), a_string(300)); | |
| 433 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; | |
| 434 INSERT INTO t1 SELECT a_string(200), a_string(300) FROM t1; | |
| 435 INSERT INTO t2 SELECT * FROM t1; | |
| 436 BEGIN; | |
| 437 INSERT INTO t1 SELECT a_string(201), a_string(301) FROM t1; | |
| 438 INSERT INTO t1 SELECT a_string(202), a_string(302) FROM t1; | |
| 439 INSERT INTO t1 SELECT a_string(203), a_string(303) FROM t1; | |
| 440 INSERT INTO t1 SELECT a_string(204), a_string(304) FROM t1; | |
| 441 REPLACE INTO t2 SELECT * FROM t1; | |
| 442 COMMIT; | |
| 443 } | |
| 444 db close | |
| 445 tstvfs delete | |
| 446 } {} | |
| 447 | |
| 448 if {$::tcl_platform(platform)!="windows"} { | |
| 449 do_test pager1.4.2.2 { | |
| 450 faultsim_restore_and_reopen | |
| 451 execsql { | |
| 452 SELECT count(*) FROM t1; | |
| 453 PRAGMA integrity_check; | |
| 454 } | |
| 455 } {4 ok} | |
| 456 do_test pager1.4.2.3 { | |
| 457 faultsim_restore_and_reopen | |
| 458 foreach f [glob test.db-mj*] { forcedelete $f } | |
| 459 execsql { | |
| 460 SELECT count(*) FROM t1; | |
| 461 PRAGMA integrity_check; | |
| 462 } | |
| 463 } {64 ok} | |
| 464 do_test pager1.4.2.4 { | |
| 465 faultsim_restore_and_reopen | |
| 466 hexio_write test.db-journal [expr [file size test.db-journal]-30] 123456 | |
| 467 execsql { | |
| 468 SELECT count(*) FROM t1; | |
| 469 PRAGMA integrity_check; | |
| 470 } | |
| 471 } {4 ok} | |
| 472 do_test pager1.4.2.5 { | |
| 473 faultsim_restore_and_reopen | |
| 474 hexio_write test.db-journal [expr [file size test.db-journal]-30] 123456 | |
| 475 foreach f [glob test.db-mj*] { forcedelete $f } | |
| 476 execsql { | |
| 477 SELECT count(*) FROM t1; | |
| 478 PRAGMA integrity_check; | |
| 479 } | |
| 480 } {4 ok} | |
| 481 } | |
| 482 | |
| 483 do_test pager1.4.3.1 { | |
| 484 testvfs tstvfs -default 1 | |
| 485 tstvfs filter xSync | |
| 486 tstvfs script xSyncCallback | |
| 487 proc xSyncCallback {method file args} { | |
| 488 set file [file tail $file] | |
| 489 if { 0==[string match *journal $file] } { faultsim_save } | |
| 490 } | |
| 491 faultsim_delete_and_reopen | |
| 492 execsql { | |
| 493 PRAGMA journal_mode = DELETE; | |
| 494 CREATE TABLE t1(a, b); | |
| 495 INSERT INTO t1 VALUES(1, 2); | |
| 496 INSERT INTO t1 VALUES(3, 4); | |
| 497 } | |
| 498 db close | |
| 499 tstvfs delete | |
| 500 } {} | |
| 501 | |
| 502 foreach {tn ofst value result} { | |
| 503 2 20 31 {1 2 3 4} | |
| 504 3 20 32 {1 2 3 4} | |
| 505 4 20 33 {1 2 3 4} | |
| 506 5 20 65536 {1 2 3 4} | |
| 507 6 20 131072 {1 2 3 4} | |
| 508 | |
| 509 7 24 511 {1 2 3 4} | |
| 510 8 24 513 {1 2 3 4} | |
| 511 9 24 131072 {1 2 3 4} | |
| 512 | |
| 513 10 32 65536 {1 2} | |
| 514 } { | |
| 515 do_test pager1.4.3.$tn { | |
| 516 faultsim_restore_and_reopen | |
| 517 hexio_write test.db-journal $ofst [format %.8x $value] | |
| 518 execsql { SELECT * FROM t1 } | |
| 519 } $result | |
| 520 } | |
| 521 db close | |
| 522 | |
| 523 # Set up a VFS that snapshots the file-system just before a master journal | |
| 524 # file is deleted to commit a multi-file transaction. Specifically, the | |
| 525 # file-system is saved just before the xDelete() call to remove the | |
| 526 # master journal file from the file-system. | |
| 527 # | |
| 528 set pwd [get_pwd] | |
| 529 testvfs tv -default 1 | |
| 530 tv script copy_on_mj_delete | |
| 531 set ::mj_filename_length 0 | |
| 532 proc copy_on_mj_delete {method filename args} { | |
| 533 if {[string match *mj* [file tail $filename]]} { | |
| 534 # | |
| 535 # NOTE: Is the file name relative? If so, add the length of the current | |
| 536 # directory. | |
| 537 # | |
| 538 if {[is_relative_file $filename]} { | |
| 539 set ::mj_filename_length \ | |
| 540 [expr {[string length $filename] + [string length $::pwd]}] | |
| 541 } else { | |
| 542 set ::mj_filename_length [string length $filename] | |
| 543 } | |
| 544 faultsim_save | |
| 545 } | |
| 546 return SQLITE_OK | |
| 547 } | |
| 548 | |
| 549 foreach {tn1 tcl} { | |
| 550 1 { set prefix "test.db" } | |
| 551 2 { | |
| 552 # This test depends on the underlying VFS being able to open paths | |
| 553 # 512 bytes in length. The idea is to create a hot-journal file that | |
| 554 # contains a master-journal pointer so large that it could contain | |
| 555 # a valid page record (if the file page-size is 512 bytes). So as to | |
| 556 # make sure SQLite doesn't get confused by this. | |
| 557 # | |
| 558 set nPadding [expr 511 - $::mj_filename_length] | |
| 559 if {$tcl_platform(platform)=="windows"} { | |
| 560 # TBD need to figure out how to do this correctly for Windows!!! | |
| 561 set nPadding [expr 255 - $::mj_filename_length] | |
| 562 } | |
| 563 | |
| 564 # We cannot just create a really long database file name to open, as | |
| 565 # Linux limits a single component of a path to 255 bytes by default | |
| 566 # (and presumably other systems have limits too). So create a directory | |
| 567 # hierarchy to work in. | |
| 568 # | |
| 569 set dirname "d123456789012345678901234567890/" | |
| 570 set nDir [expr $nPadding / 32] | |
| 571 if { $nDir } { | |
| 572 set p [string repeat $dirname $nDir] | |
| 573 file mkdir $p | |
| 574 cd $p | |
| 575 } | |
| 576 | |
| 577 set padding [string repeat x [expr $nPadding %32]] | |
| 578 set prefix "test.db${padding}" | |
| 579 } | |
| 580 } { | |
| 581 eval $tcl | |
| 582 foreach {tn2 sql} { | |
| 583 o { | |
| 584 PRAGMA main.synchronous=OFF; | |
| 585 PRAGMA aux.synchronous=OFF; | |
| 586 PRAGMA journal_mode = DELETE; | |
| 587 } | |
| 588 o512 { | |
| 589 PRAGMA main.synchronous=OFF; | |
| 590 PRAGMA aux.synchronous=OFF; | |
| 591 PRAGMA main.page_size = 512; | |
| 592 PRAGMA aux.page_size = 512; | |
| 593 PRAGMA journal_mode = DELETE; | |
| 594 } | |
| 595 n { | |
| 596 PRAGMA main.synchronous=NORMAL; | |
| 597 PRAGMA aux.synchronous=NORMAL; | |
| 598 PRAGMA journal_mode = DELETE; | |
| 599 } | |
| 600 f { | |
| 601 PRAGMA main.synchronous=FULL; | |
| 602 PRAGMA aux.synchronous=FULL; | |
| 603 PRAGMA journal_mode = DELETE; | |
| 604 } | |
| 605 } { | |
| 606 | |
| 607 set tn "${tn1}.${tn2}" | |
| 608 | |
| 609 # Set up a connection to have two databases, test.db (main) and | |
| 610 # test.db2 (aux). Then run a multi-file transaction on them. The | |
| 611 # VFS will snapshot the file-system just before the master-journal | |
| 612 # file is deleted to commit the transaction. | |
| 613 # | |
| 614 tv filter xDelete | |
| 615 do_test pager1-4.4.$tn.1 { | |
| 616 faultsim_delete_and_reopen $prefix | |
| 617 execsql " | |
| 618 ATTACH '${prefix}2' AS aux; | |
| 619 $sql | |
| 620 CREATE TABLE a(x); | |
| 621 CREATE TABLE aux.b(x); | |
| 622 INSERT INTO a VALUES('double-you'); | |
| 623 INSERT INTO a VALUES('why'); | |
| 624 INSERT INTO a VALUES('zed'); | |
| 625 INSERT INTO b VALUES('won'); | |
| 626 INSERT INTO b VALUES('too'); | |
| 627 INSERT INTO b VALUES('free'); | |
| 628 " | |
| 629 execsql { | |
| 630 BEGIN; | |
| 631 INSERT INTO a SELECT * FROM b WHERE rowid<=3; | |
| 632 INSERT INTO b SELECT * FROM a WHERE rowid<=3; | |
| 633 COMMIT; | |
| 634 } | |
| 635 } {} | |
| 636 tv filter {} | |
| 637 | |
| 638 # Check that the transaction was committed successfully. | |
| 639 # | |
| 640 do_execsql_test pager1-4.4.$tn.2 { | |
| 641 SELECT * FROM a | |
| 642 } {double-you why zed won too free} | |
| 643 do_execsql_test pager1-4.4.$tn.3 { | |
| 644 SELECT * FROM b | |
| 645 } {won too free double-you why zed} | |
| 646 | |
| 647 # Restore the file-system and reopen the databases. Check that it now | |
| 648 # appears that the transaction was not committed (because the file-system | |
| 649 # was restored to the state where it had not been). | |
| 650 # | |
| 651 do_test pager1-4.4.$tn.4 { | |
| 652 faultsim_restore_and_reopen $prefix | |
| 653 execsql "ATTACH '${prefix}2' AS aux" | |
| 654 } {} | |
| 655 do_execsql_test pager1-4.4.$tn.5 {SELECT * FROM a} {double-you why zed} | |
| 656 do_execsql_test pager1-4.4.$tn.6 {SELECT * FROM b} {won too free} | |
| 657 | |
| 658 # Restore the file-system again. This time, before reopening the databases, | |
| 659 # delete the master-journal file from the file-system. It now appears that | |
| 660 # the transaction was committed (no master-journal file == no rollback). | |
| 661 # | |
| 662 do_test pager1-4.4.$tn.7 { | |
| 663 faultsim_restore_and_reopen $prefix | |
| 664 foreach f [glob ${prefix}-mj*] { forcedelete $f } | |
| 665 execsql "ATTACH '${prefix}2' AS aux" | |
| 666 } {} | |
| 667 do_execsql_test pager1-4.4.$tn.8 { | |
| 668 SELECT * FROM a | |
| 669 } {double-you why zed won too free} | |
| 670 do_execsql_test pager1-4.4.$tn.9 { | |
| 671 SELECT * FROM b | |
| 672 } {won too free double-you why zed} | |
| 673 } | |
| 674 | |
| 675 cd $pwd | |
| 676 } | |
| 677 db close | |
| 678 tv delete | |
| 679 forcedelete $dirname | |
| 680 | |
| 681 | |
| 682 # Set up a VFS to make a copy of the file-system just before deleting a | |
| 683 # journal file to commit a transaction. The transaction modifies exactly | |
| 684 # two database pages (and page 1 - the change counter). | |
| 685 # | |
| 686 testvfs tv -default 1 | |
| 687 tv sectorsize 512 | |
| 688 tv script copy_on_journal_delete | |
| 689 tv filter xDelete | |
| 690 proc copy_on_journal_delete {method filename args} { | |
| 691 if {[string match *journal $filename]} faultsim_save | |
| 692 return SQLITE_OK | |
| 693 } | |
| 694 faultsim_delete_and_reopen | |
| 695 do_execsql_test pager1.4.5.1 { | |
| 696 PRAGMA journal_mode = DELETE; | |
| 697 PRAGMA page_size = 1024; | |
| 698 CREATE TABLE t1(a, b); | |
| 699 CREATE TABLE t2(a, b); | |
| 700 INSERT INTO t1 VALUES('I', 'II'); | |
| 701 INSERT INTO t2 VALUES('III', 'IV'); | |
| 702 BEGIN; | |
| 703 INSERT INTO t1 VALUES(1, 2); | |
| 704 INSERT INTO t2 VALUES(3, 4); | |
| 705 COMMIT; | |
| 706 } {delete} | |
| 707 tv filter {} | |
| 708 | |
| 709 # Check the transaction was committed: | |
| 710 # | |
| 711 do_execsql_test pager1.4.5.2 { | |
| 712 SELECT * FROM t1; | |
| 713 SELECT * FROM t2; | |
| 714 } {I II 1 2 III IV 3 4} | |
| 715 | |
| 716 # Now try four tests: | |
| 717 # | |
| 718 # pager1-4.5.3: Restore the file-system. Check that the whole transaction | |
| 719 # is rolled back. | |
| 720 # | |
| 721 # pager1-4.5.4: Restore the file-system. Corrupt the first record in the | |
| 722 # journal. Check the transaction is not rolled back. | |
| 723 # | |
| 724 # pager1-4.5.5: Restore the file-system. Corrupt the second record in the | |
| 725 # journal. Check that the first record in the transaction is | |
| 726 # played back, but not the second. | |
| 727 # | |
| 728 # pager1-4.5.6: Restore the file-system. Try to open the database with a | |
| 729 # readonly connection. This should fail, as a read-only | |
| 730 # connection cannot roll back the database file. | |
| 731 # | |
| 732 faultsim_restore_and_reopen | |
| 733 do_execsql_test pager1.4.5.3 { | |
| 734 SELECT * FROM t1; | |
| 735 SELECT * FROM t2; | |
| 736 } {I II III IV} | |
| 737 faultsim_restore_and_reopen | |
| 738 hexio_write test.db-journal [expr 512+4+1024 - 202] 0123456789ABCDEF | |
| 739 do_execsql_test pager1.4.5.4 { | |
| 740 SELECT * FROM t1; | |
| 741 SELECT * FROM t2; | |
| 742 } {I II 1 2 III IV 3 4} | |
| 743 faultsim_restore_and_reopen | |
| 744 hexio_write test.db-journal [expr 512+4+1024+4+4+1024 - 202] 0123456789ABCDEF | |
| 745 do_execsql_test pager1.4.5.5 { | |
| 746 SELECT * FROM t1; | |
| 747 SELECT * FROM t2; | |
| 748 } {I II III IV 3 4} | |
| 749 | |
| 750 faultsim_restore_and_reopen | |
| 751 db close | |
| 752 sqlite3 db test.db -readonly 1 | |
| 753 do_catchsql_test pager1.4.5.6 { | |
| 754 SELECT * FROM t1; | |
| 755 SELECT * FROM t2; | |
| 756 } {1 {attempt to write a readonly database}} | |
| 757 db close | |
| 758 | |
| 759 # Snapshot the file-system just before multi-file commit. Save the name | |
| 760 # of the master journal file in $::mj_filename. | |
| 761 # | |
| 762 tv script copy_on_mj_delete | |
| 763 tv filter xDelete | |
| 764 proc copy_on_mj_delete {method filename args} { | |
| 765 if {[string match *mj* [file tail $filename]]} { | |
| 766 set ::mj_filename $filename | |
| 767 faultsim_save | |
| 768 } | |
| 769 return SQLITE_OK | |
| 770 } | |
| 771 do_test pager1.4.6.1 { | |
| 772 faultsim_delete_and_reopen | |
| 773 execsql { | |
| 774 PRAGMA journal_mode = DELETE; | |
| 775 ATTACH 'test.db2' AS two; | |
| 776 CREATE TABLE t1(a, b); | |
| 777 CREATE TABLE two.t2(a, b); | |
| 778 INSERT INTO t1 VALUES(1, 't1.1'); | |
| 779 INSERT INTO t2 VALUES(1, 't2.1'); | |
| 780 BEGIN; | |
| 781 UPDATE t1 SET b = 't1.2'; | |
| 782 UPDATE t2 SET b = 't2.2'; | |
| 783 COMMIT; | |
| 784 } | |
| 785 tv filter {} | |
| 786 db close | |
| 787 } {} | |
| 788 | |
| 789 faultsim_restore_and_reopen | |
| 790 do_execsql_test pager1.4.6.2 { SELECT * FROM t1 } {1 t1.1} | |
| 791 do_test pager1.4.6.3 { file exists $::mj_filename } {1} | |
| 792 do_execsql_test pager1.4.6.4 { | |
| 793 ATTACH 'test.db2' AS two; | |
| 794 SELECT * FROM t2; | |
| 795 } {1 t2.1} | |
| 796 do_test pager1.4.6.5 { file exists $::mj_filename } {0} | |
| 797 | |
| 798 faultsim_restore_and_reopen | |
| 799 db close | |
| 800 do_test pager1.4.6.8 { | |
| 801 set ::mj_filename1 $::mj_filename | |
| 802 tv filter xDelete | |
| 803 sqlite3 db test.db2 | |
| 804 execsql { | |
| 805 PRAGMA journal_mode = DELETE; | |
| 806 ATTACH 'test.db3' AS three; | |
| 807 CREATE TABLE three.t3(a, b); | |
| 808 INSERT INTO t3 VALUES(1, 't3.1'); | |
| 809 BEGIN; | |
| 810 UPDATE t2 SET b = 't2.3'; | |
| 811 UPDATE t3 SET b = 't3.3'; | |
| 812 COMMIT; | |
| 813 } | |
| 814 expr {$::mj_filename1 != $::mj_filename} | |
| 815 } {1} | |
| 816 faultsim_restore_and_reopen | |
| 817 tv filter {} | |
| 818 | |
| 819 # The file-system now contains: | |
| 820 # | |
| 821 # * three databases | |
| 822 # * three hot-journal files | |
| 823 # * two master-journal files. | |
| 824 # | |
| 825 # The hot-journals associated with test.db2 and test.db3 point to | |
| 826 # master journal $::mj_filename. The hot-journal file associated with | |
| 827 # test.db points to master journal $::mj_filename1. So reading from | |
| 828 # test.db should delete $::mj_filename1. | |
| 829 # | |
| 830 do_test pager1.4.6.9 { | |
| 831 lsort [glob test.db*] | |
| 832 } [lsort [list \ | |
| 833 test.db test.db2 test.db3 \ | |
| 834 test.db-journal test.db2-journal test.db3-journal \ | |
| 835 [file tail $::mj_filename] [file tail $::mj_filename1] | |
| 836 ]] | |
| 837 | |
| 838 # The master-journal $::mj_filename1 contains pointers to test.db and | |
| 839 # test.db2. However the hot-journal associated with test.db2 points to | |
| 840 # a different master-journal. Therefore, reading from test.db only should | |
| 841 # be enough to cause SQLite to delete $::mj_filename1. | |
| 842 # | |
| 843 do_test pager1.4.6.10 { file exists $::mj_filename } {1} | |
| 844 do_test pager1.4.6.11 { file exists $::mj_filename1 } {1} | |
| 845 do_execsql_test pager1.4.6.12 { SELECT * FROM t1 } {1 t1.1} | |
| 846 do_test pager1.4.6.13 { file exists $::mj_filename } {1} | |
| 847 do_test pager1.4.6.14 { file exists $::mj_filename1 } {0} | |
| 848 | |
| 849 do_execsql_test pager1.4.6.12 { | |
| 850 ATTACH 'test.db2' AS two; | |
| 851 SELECT * FROM t2; | |
| 852 } {1 t2.1} | |
| 853 do_test pager1.4.6.13 { file exists $::mj_filename } {1} | |
| 854 do_execsql_test pager1.4.6.14 { | |
| 855 ATTACH 'test.db3' AS three; | |
| 856 SELECT * FROM t3; | |
| 857 } {1 t3.1} | |
| 858 do_test pager1.4.6.15 { file exists $::mj_filename } {0} | |
| 859 | |
| 860 db close | |
| 861 tv delete | |
| 862 | |
| 863 testvfs tv -default 1 | |
| 864 tv sectorsize 512 | |
| 865 tv script copy_on_journal_delete | |
| 866 tv filter xDelete | |
| 867 proc copy_on_journal_delete {method filename args} { | |
| 868 if {[string match *journal $filename]} faultsim_save | |
| 869 return SQLITE_OK | |
| 870 } | |
| 871 faultsim_delete_and_reopen | |
| 872 do_execsql_test pager1.4.7.1 { | |
| 873 PRAGMA journal_mode = DELETE; | |
| 874 CREATE TABLE t1(x PRIMARY KEY, y); | |
| 875 CREATE INDEX i1 ON t1(y); | |
| 876 INSERT INTO t1 VALUES('I', 'one'); | |
| 877 INSERT INTO t1 VALUES('II', 'four'); | |
| 878 INSERT INTO t1 VALUES('III', 'nine'); | |
| 879 BEGIN; | |
| 880 INSERT INTO t1 VALUES('IV', 'sixteen'); | |
| 881 INSERT INTO t1 VALUES('V' , 'twentyfive'); | |
| 882 COMMIT; | |
| 883 } {delete} | |
| 884 tv filter {} | |
| 885 db close | |
| 886 tv delete | |
| 887 catch { | |
| 888 test_syscall install fchmod | |
| 889 test_syscall fault 1 1 | |
| 890 } | |
| 891 do_test pager1.4.7.2 { | |
| 892 faultsim_restore_and_reopen | |
| 893 catch {file attributes test.db-journal -permissions r--------} | |
| 894 catch {file attributes test.db-journal -readonly 1} | |
| 895 catchsql { SELECT * FROM t1 } | |
| 896 } {1 {unable to open database file}} | |
| 897 catch { | |
| 898 test_syscall reset | |
| 899 test_syscall fault 0 0 | |
| 900 } | |
| 901 do_test pager1.4.7.3 { | |
| 902 db close | |
| 903 catch {file attributes test.db-journal -permissions rw-rw-rw-} | |
| 904 catch {file attributes test.db-journal -readonly 0} | |
| 905 delete_file test.db-journal | |
| 906 file exists test.db-journal | |
| 907 } {0} | |
| 908 do_test pager1.4.8.1 { | |
| 909 catch {file attributes test.db -permissions r--------} | |
| 910 catch {file attributes test.db -readonly 1} | |
| 911 sqlite3 db test.db | |
| 912 db eval { SELECT * FROM t1 } | |
| 913 sqlite3_db_readonly db main | |
| 914 } {1} | |
| 915 do_test pager1.4.8.2 { | |
| 916 sqlite3_db_readonly db xyz | |
| 917 } {-1} | |
| 918 do_test pager1.4.8.3 { | |
| 919 db close | |
| 920 catch {file attributes test.db -readonly 0} | |
| 921 catch {file attributes test.db -permissions rw-rw-rw-} msg | |
| 922 sqlite3 db test.db | |
| 923 db eval { SELECT * FROM t1 } | |
| 924 sqlite3_db_readonly db main | |
| 925 } {0} | |
| 926 | |
| 927 #------------------------------------------------------------------------- | |
| 928 # The following tests deal with multi-file commits. | |
| 929 # | |
| 930 # pager1-5.1.*: The case where a multi-file cannot be committed because | |
| 931 # another connection is holding a SHARED lock on one of the | |
| 932 # files. After the SHARED lock is removed, the COMMIT succeeds. | |
| 933 # | |
| 934 # pager1-5.2.*: Multi-file commits with journal_mode=memory. | |
| 935 # | |
| 936 # pager1-5.3.*: Multi-file commits with journal_mode=memory. | |
| 937 # | |
| 938 # pager1-5.4.*: Check that with synchronous=normal, the master-journal file | |
| 939 # name is added to a journal file immediately after the last | |
| 940 # journal record. But with synchronous=full, extra unused space | |
| 941 # is allocated between the last journal record and the | |
| 942 # master-journal file name so that the master-journal file | |
| 943 # name does not lie on the same sector as the last journal file | |
| 944 # record. | |
| 945 # | |
| 946 # pager1-5.5.*: Check that in journal_mode=PERSIST mode, a journal file is | |
| 947 # truncated to zero bytes when a multi-file transaction is | |
| 948 # committed (instead of the first couple of bytes being zeroed). | |
| 949 # | |
| 950 # | |
| 951 do_test pager1-5.1.1 { | |
| 952 faultsim_delete_and_reopen | |
| 953 execsql { | |
| 954 ATTACH 'test.db2' AS aux; | |
| 955 CREATE TABLE t1(a, b); | |
| 956 CREATE TABLE aux.t2(a, b); | |
| 957 INSERT INTO t1 VALUES(17, 'Lenin'); | |
| 958 INSERT INTO t1 VALUES(22, 'Stalin'); | |
| 959 INSERT INTO t1 VALUES(53, 'Khrushchev'); | |
| 960 } | |
| 961 } {} | |
| 962 do_test pager1-5.1.2 { | |
| 963 execsql { | |
| 964 BEGIN; | |
| 965 INSERT INTO t1 VALUES(64, 'Brezhnev'); | |
| 966 INSERT INTO t2 SELECT * FROM t1; | |
| 967 } | |
| 968 sqlite3 db2 test.db2 | |
| 969 execsql { | |
| 970 BEGIN; | |
| 971 SELECT * FROM t2; | |
| 972 } db2 | |
| 973 } {} | |
| 974 do_test pager1-5.1.3 { | |
| 975 catchsql COMMIT | |
| 976 } {1 {database is locked}} | |
| 977 do_test pager1-5.1.4 { | |
| 978 execsql COMMIT db2 | |
| 979 execsql COMMIT | |
| 980 execsql { SELECT * FROM t2 } db2 | |
| 981 } {17 Lenin 22 Stalin 53 Khrushchev 64 Brezhnev} | |
| 982 do_test pager1-5.1.5 { | |
| 983 db2 close | |
| 984 } {} | |
| 985 | |
| 986 do_test pager1-5.2.1 { | |
| 987 execsql { | |
| 988 PRAGMA journal_mode = memory; | |
| 989 BEGIN; | |
| 990 INSERT INTO t1 VALUES(84, 'Andropov'); | |
| 991 INSERT INTO t2 VALUES(84, 'Andropov'); | |
| 992 COMMIT; | |
| 993 } | |
| 994 } {memory} | |
| 995 do_test pager1-5.3.1 { | |
| 996 execsql { | |
| 997 PRAGMA journal_mode = off; | |
| 998 BEGIN; | |
| 999 INSERT INTO t1 VALUES(85, 'Gorbachev'); | |
| 1000 INSERT INTO t2 VALUES(85, 'Gorbachev'); | |
| 1001 COMMIT; | |
| 1002 } | |
| 1003 } {off} | |
| 1004 | |
| 1005 do_test pager1-5.4.1 { | |
| 1006 db close | |
| 1007 testvfs tv | |
| 1008 sqlite3 db test.db -vfs tv | |
| 1009 execsql { ATTACH 'test.db2' AS aux } | |
| 1010 | |
| 1011 tv filter xDelete | |
| 1012 tv script max_journal_size | |
| 1013 tv sectorsize 512 | |
| 1014 set ::max_journal 0 | |
| 1015 proc max_journal_size {method args} { | |
| 1016 set sz 0 | |
| 1017 catch { set sz [file size test.db-journal] } | |
| 1018 if {$sz > $::max_journal} { | |
| 1019 set ::max_journal $sz | |
| 1020 } | |
| 1021 return SQLITE_OK | |
| 1022 } | |
| 1023 execsql { | |
| 1024 PRAGMA journal_mode = DELETE; | |
| 1025 PRAGMA synchronous = NORMAL; | |
| 1026 BEGIN; | |
| 1027 INSERT INTO t1 VALUES(85, 'Gorbachev'); | |
| 1028 INSERT INTO t2 VALUES(85, 'Gorbachev'); | |
| 1029 COMMIT; | |
| 1030 } | |
| 1031 | |
| 1032 # The size of the journal file is now: | |
| 1033 # | |
| 1034 # 1) 512 byte header + | |
| 1035 # 2) 2 * (1024+8) byte records + | |
| 1036 # 3) 20+N bytes of master-journal pointer, where N is the size of | |
| 1037 # the master-journal name encoded as utf-8 with no nul term. | |
| 1038 # | |
| 1039 set mj_pointer [expr { | |
| 1040 20 + [string length "test.db-mjXXXXXX9XX"] | |
| 1041 }] | |
| 1042 # | |
| 1043 # NOTE: For item 3 above, if the current SQLite VFS lacks the concept of a | |
| 1044 # current directory, the length of the current directory name plus 1 | |
| 1045 # character for the directory separator character are NOT counted as | |
| 1046 # part of the total size; otherwise, they are. | |
| 1047 # | |
| 1048 ifcapable curdir { | |
| 1049 set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}] | |
| 1050 } | |
| 1051 expr {$::max_journal==(512+2*(1024+8)+$mj_pointer)} | |
| 1052 } 1 | |
| 1053 do_test pager1-5.4.2 { | |
| 1054 set ::max_journal 0 | |
| 1055 execsql { | |
| 1056 PRAGMA synchronous = full; | |
| 1057 BEGIN; | |
| 1058 DELETE FROM t1 WHERE b = 'Lenin'; | |
| 1059 DELETE FROM t2 WHERE b = 'Lenin'; | |
| 1060 COMMIT; | |
| 1061 } | |
| 1062 | |
| 1063 # In synchronous=full mode, the master-journal pointer is not written | |
| 1064 # directly after the last record in the journal file. Instead, it is | |
| 1065 # written starting at the next (in this case 512 byte) sector boundary. | |
| 1066 # | |
| 1067 set mj_pointer [expr { | |
| 1068 20 + [string length "test.db-mjXXXXXX9XX"] | |
| 1069 }] | |
| 1070 # | |
| 1071 # NOTE: If the current SQLite VFS lacks the concept of a current directory, | |
| 1072 # the length of the current directory name plus 1 character for the | |
| 1073 # directory separator character are NOT counted as part of the total | |
| 1074 # size; otherwise, they are. | |
| 1075 # | |
| 1076 ifcapable curdir { | |
| 1077 set mj_pointer [expr {$mj_pointer + [string length [get_pwd]] + 1}] | |
| 1078 } | |
| 1079 expr {$::max_journal==(((512+2*(1024+8)+511)/512)*512 + $mj_pointer)} | |
| 1080 } 1 | |
| 1081 db close | |
| 1082 tv delete | |
| 1083 | |
| 1084 do_test pager1-5.5.1 { | |
| 1085 sqlite3 db test.db | |
| 1086 execsql { | |
| 1087 ATTACH 'test.db2' AS aux; | |
| 1088 PRAGMA journal_mode = PERSIST; | |
| 1089 CREATE TABLE t3(a, b); | |
| 1090 INSERT INTO t3 SELECT randomblob(1500), randomblob(1500) FROM t1; | |
| 1091 UPDATE t3 SET b = randomblob(1500); | |
| 1092 } | |
| 1093 expr [file size test.db-journal] > 15000 | |
| 1094 } {1} | |
| 1095 do_test pager1-5.5.2 { | |
| 1096 execsql { | |
| 1097 PRAGMA synchronous = full; | |
| 1098 BEGIN; | |
| 1099 DELETE FROM t1 WHERE b = 'Stalin'; | |
| 1100 DELETE FROM t2 WHERE b = 'Stalin'; | |
| 1101 COMMIT; | |
| 1102 } | |
| 1103 file size test.db-journal | |
| 1104 } {0} | |
| 1105 | |
| 1106 | |
| 1107 #------------------------------------------------------------------------- | |
| 1108 # The following tests work with "PRAGMA max_page_count" | |
| 1109 # | |
| 1110 do_test pager1-6.1 { | |
| 1111 faultsim_delete_and_reopen | |
| 1112 execsql { | |
| 1113 PRAGMA auto_vacuum = none; | |
| 1114 PRAGMA max_page_count = 10; | |
| 1115 CREATE TABLE t2(a, b); | |
| 1116 CREATE TABLE t3(a, b); | |
| 1117 CREATE TABLE t4(a, b); | |
| 1118 CREATE TABLE t5(a, b); | |
| 1119 CREATE TABLE t6(a, b); | |
| 1120 CREATE TABLE t7(a, b); | |
| 1121 CREATE TABLE t8(a, b); | |
| 1122 CREATE TABLE t9(a, b); | |
| 1123 CREATE TABLE t10(a, b); | |
| 1124 } | |
| 1125 } {10} | |
| 1126 do_catchsql_test pager1-6.2 { | |
| 1127 CREATE TABLE t11(a, b) | |
| 1128 } {1 {database or disk is full}} | |
| 1129 do_execsql_test pager1-6.4 { PRAGMA max_page_count } {10} | |
| 1130 do_execsql_test pager1-6.5 { PRAGMA max_page_count = 15 } {15} | |
| 1131 do_execsql_test pager1-6.6 { CREATE TABLE t11(a, b) } {} | |
| 1132 do_execsql_test pager1-6.7 { | |
| 1133 BEGIN; | |
| 1134 INSERT INTO t11 VALUES(1, 2); | |
| 1135 PRAGMA max_page_count = 13; | |
| 1136 } {13} | |
| 1137 do_execsql_test pager1-6.8 { | |
| 1138 INSERT INTO t11 VALUES(3, 4); | |
| 1139 PRAGMA max_page_count = 10; | |
| 1140 } {11} | |
| 1141 do_execsql_test pager1-6.9 { COMMIT } {} | |
| 1142 | |
| 1143 do_execsql_test pager1-6.10 { PRAGMA max_page_count = 10 } {11} | |
| 1144 do_execsql_test pager1-6.11 { SELECT * FROM t11 } {1 2 3 4} | |
| 1145 do_execsql_test pager1-6.12 { PRAGMA max_page_count } {11} | |
| 1146 | |
| 1147 | |
| 1148 #------------------------------------------------------------------------- | |
| 1149 # The following tests work with "PRAGMA journal_mode=TRUNCATE" and | |
| 1150 # "PRAGMA locking_mode=EXCLUSIVE". | |
| 1151 # | |
| 1152 # Each test is specified with 5 variables. As follows: | |
| 1153 # | |
| 1154 # $tn: Test Number. Used as part of the [do_test] test names. | |
| 1155 # $sql: SQL to execute. | |
| 1156 # $res: Expected result of executing $sql. | |
| 1157 # $js: The expected size of the journal file, in bytes, after executing | |
| 1158 # the SQL script. Or -1 if the journal is not expected to exist. | |
| 1159 # $ws: The expected size of the WAL file, in bytes, after executing | |
| 1160 # the SQL script. Or -1 if the WAL is not expected to exist. | |
| 1161 # | |
| 1162 ifcapable wal { | |
| 1163 faultsim_delete_and_reopen | |
| 1164 foreach {tn sql res js ws} [subst { | |
| 1165 | |
| 1166 1 { | |
| 1167 CREATE TABLE t1(a, b); | |
| 1168 PRAGMA auto_vacuum=OFF; | |
| 1169 PRAGMA synchronous=NORMAL; | |
| 1170 PRAGMA page_size=1024; | |
| 1171 PRAGMA locking_mode=EXCLUSIVE; | |
| 1172 PRAGMA journal_mode=TRUNCATE; | |
| 1173 INSERT INTO t1 VALUES(1, 2); | |
| 1174 } {exclusive truncate} 0 -1 | |
| 1175 | |
| 1176 2 { | |
| 1177 BEGIN IMMEDIATE; | |
| 1178 SELECT * FROM t1; | |
| 1179 COMMIT; | |
| 1180 } {1 2} 0 -1 | |
| 1181 | |
| 1182 3 { | |
| 1183 BEGIN; | |
| 1184 SELECT * FROM t1; | |
| 1185 COMMIT; | |
| 1186 } {1 2} 0 -1 | |
| 1187 | |
| 1188 4 { PRAGMA journal_mode = WAL } wal -1 -1 | |
| 1189 5 { INSERT INTO t1 VALUES(3, 4) } {} -1 [wal_file_size 1 1024] | |
| 1190 6 { PRAGMA locking_mode = NORMAL } exclusive -1 [wal_file_size 1 1024] | |
| 1191 7 { INSERT INTO t1 VALUES(5, 6); } {} -1 [wal_file_size 2 1024] | |
| 1192 | |
| 1193 8 { PRAGMA journal_mode = TRUNCATE } truncate 0 -1 | |
| 1194 9 { INSERT INTO t1 VALUES(7, 8) } {} 0 -1 | |
| 1195 10 { SELECT * FROM t1 } {1 2 3 4 5 6 7 8} 0 -1 | |
| 1196 | |
| 1197 }] { | |
| 1198 do_execsql_test pager1-7.1.$tn.1 $sql $res | |
| 1199 catch { set J -1 ; set J [file size test.db-journal] } | |
| 1200 catch { set W -1 ; set W [file size test.db-wal] } | |
| 1201 do_test pager1-7.1.$tn.2 { list $J $W } [list $js $ws] | |
| 1202 } | |
| 1203 } | |
| 1204 | |
| 1205 do_test pager1-7.2.1 { | |
| 1206 faultsim_delete_and_reopen | |
| 1207 execsql { | |
| 1208 PRAGMA locking_mode = EXCLUSIVE; | |
| 1209 CREATE TABLE t1(a, b); | |
| 1210 BEGIN; | |
| 1211 PRAGMA journal_mode = delete; | |
| 1212 PRAGMA journal_mode = truncate; | |
| 1213 } | |
| 1214 } {exclusive delete truncate} | |
| 1215 do_test pager1-7.2.2 { | |
| 1216 execsql { INSERT INTO t1 VALUES(1, 2) } | |
| 1217 execsql { PRAGMA journal_mode = persist } | |
| 1218 } {truncate} | |
| 1219 do_test pager1-7.2.3 { | |
| 1220 execsql { COMMIT } | |
| 1221 execsql { | |
| 1222 PRAGMA journal_mode = persist; | |
| 1223 PRAGMA journal_size_limit; | |
| 1224 } | |
| 1225 } {persist -1} | |
| 1226 | |
| 1227 #------------------------------------------------------------------------- | |
| 1228 # The following tests, pager1-8.*, test that the special filenames | |
| 1229 # ":memory:" and "" open temporary databases. | |
| 1230 # | |
| 1231 foreach {tn filename} { | |
| 1232 1 :memory: | |
| 1233 2 "" | |
| 1234 } { | |
| 1235 do_test pager1-8.$tn.1 { | |
| 1236 faultsim_delete_and_reopen | |
| 1237 db close | |
| 1238 sqlite3 db $filename | |
| 1239 execsql { | |
| 1240 PRAGMA auto_vacuum = 1; | |
| 1241 CREATE TABLE x1(x); | |
| 1242 INSERT INTO x1 VALUES('Charles'); | |
| 1243 INSERT INTO x1 VALUES('James'); | |
| 1244 INSERT INTO x1 VALUES('Mary'); | |
| 1245 SELECT * FROM x1; | |
| 1246 } | |
| 1247 } {Charles James Mary} | |
| 1248 | |
| 1249 do_test pager1-8.$tn.2 { | |
| 1250 sqlite3 db2 $filename | |
| 1251 catchsql { SELECT * FROM x1 } db2 | |
| 1252 } {1 {no such table: x1}} | |
| 1253 | |
| 1254 do_execsql_test pager1-8.$tn.3 { | |
| 1255 BEGIN; | |
| 1256 INSERT INTO x1 VALUES('William'); | |
| 1257 INSERT INTO x1 VALUES('Anne'); | |
| 1258 ROLLBACK; | |
| 1259 } {} | |
| 1260 } | |
| 1261 | |
| 1262 #------------------------------------------------------------------------- | |
| 1263 # The next block of tests - pager1-9.* - deal with interactions between | |
| 1264 # the pager and the backup API. Test cases: | |
| 1265 # | |
| 1266 # pager1-9.1.*: Test that a backup completes successfully even if the | |
| 1267 # source db is written to during the backup op. | |
| 1268 # | |
| 1269 # pager1-9.2.*: Test that a backup completes successfully even if the | |
| 1270 # source db is written to and then rolled back during a | |
| 1271 # backup operation. | |
| 1272 # | |
| 1273 do_test pager1-9.0.1 { | |
| 1274 faultsim_delete_and_reopen | |
| 1275 db func a_string a_string | |
| 1276 execsql { | |
| 1277 PRAGMA cache_size = 10; | |
| 1278 BEGIN; | |
| 1279 CREATE TABLE ab(a, b, UNIQUE(a, b)); | |
| 1280 INSERT INTO ab VALUES( a_string(200), a_string(300) ); | |
| 1281 INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; | |
| 1282 INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; | |
| 1283 INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; | |
| 1284 INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; | |
| 1285 INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; | |
| 1286 INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; | |
| 1287 INSERT INTO ab SELECT a_string(200), a_string(300) FROM ab; | |
| 1288 COMMIT; | |
| 1289 } | |
| 1290 } {} | |
| 1291 do_test pager1-9.0.2 { | |
| 1292 sqlite3 db2 test.db2 | |
| 1293 db2 eval { PRAGMA cache_size = 10 } | |
| 1294 sqlite3_backup B db2 main db main | |
| 1295 list [B step 10000] [B finish] | |
| 1296 } {SQLITE_DONE SQLITE_OK} | |
| 1297 do_test pager1-9.0.3 { | |
| 1298 db one {SELECT md5sum(a, b) FROM ab} | |
| 1299 } [db2 one {SELECT md5sum(a, b) FROM ab}] | |
| 1300 | |
| 1301 do_test pager1-9.1.1 { | |
| 1302 execsql { UPDATE ab SET a = a_string(201) } | |
| 1303 sqlite3_backup B db2 main db main | |
| 1304 B step 30 | |
| 1305 } {SQLITE_OK} | |
| 1306 do_test pager1-9.1.2 { | |
| 1307 execsql { UPDATE ab SET b = a_string(301) } | |
| 1308 list [B step 10000] [B finish] | |
| 1309 } {SQLITE_DONE SQLITE_OK} | |
| 1310 do_test pager1-9.1.3 { | |
| 1311 db one {SELECT md5sum(a, b) FROM ab} | |
| 1312 } [db2 one {SELECT md5sum(a, b) FROM ab}] | |
| 1313 do_test pager1-9.1.4 { execsql { SELECT count(*) FROM ab } } {128} | |
| 1314 | |
| 1315 do_test pager1-9.2.1 { | |
| 1316 execsql { UPDATE ab SET a = a_string(202) } | |
| 1317 sqlite3_backup B db2 main db main | |
| 1318 B step 30 | |
| 1319 } {SQLITE_OK} | |
| 1320 do_test pager1-9.2.2 { | |
| 1321 execsql { | |
| 1322 BEGIN; | |
| 1323 UPDATE ab SET b = a_string(301); | |
| 1324 ROLLBACK; | |
| 1325 } | |
| 1326 list [B step 10000] [B finish] | |
| 1327 } {SQLITE_DONE SQLITE_OK} | |
| 1328 do_test pager1-9.2.3 { | |
| 1329 db one {SELECT md5sum(a, b) FROM ab} | |
| 1330 } [db2 one {SELECT md5sum(a, b) FROM ab}] | |
| 1331 do_test pager1-9.2.4 { execsql { SELECT count(*) FROM ab } } {128} | |
| 1332 db close | |
| 1333 db2 close | |
| 1334 | |
| 1335 do_test pager1-9.3.1 { | |
| 1336 testvfs tv -default 1 | |
| 1337 tv sectorsize 4096 | |
| 1338 faultsim_delete_and_reopen | |
| 1339 | |
| 1340 execsql { PRAGMA page_size = 1024 } | |
| 1341 for {set ii 0} {$ii < 4} {incr ii} { execsql "CREATE TABLE t${ii}(a, b)" } | |
| 1342 } {} | |
| 1343 do_test pager1-9.3.2 { | |
| 1344 sqlite3 db2 test.db2 | |
| 1345 | |
| 1346 execsql { | |
| 1347 PRAGMA page_size = 4096; | |
| 1348 PRAGMA synchronous = OFF; | |
| 1349 CREATE TABLE t1(a, b); | |
| 1350 CREATE TABLE t2(a, b); | |
| 1351 } db2 | |
| 1352 | |
| 1353 sqlite3_backup B db2 main db main | |
| 1354 B step 30 | |
| 1355 list [B step 10000] [B finish] | |
| 1356 } {SQLITE_DONE SQLITE_OK} | |
| 1357 do_test pager1-9.3.3 { | |
| 1358 db2 close | |
| 1359 db close | |
| 1360 tv delete | |
| 1361 file size test.db2 | |
| 1362 } [file size test.db] | |
| 1363 | |
| 1364 do_test pager1-9.4.1 { | |
| 1365 faultsim_delete_and_reopen | |
| 1366 sqlite3 db2 test.db2 | |
| 1367 execsql { | |
| 1368 PRAGMA page_size = 4096; | |
| 1369 CREATE TABLE t1(a, b); | |
| 1370 CREATE TABLE t2(a, b); | |
| 1371 } db2 | |
| 1372 sqlite3_backup B db2 main db main | |
| 1373 list [B step 10000] [B finish] | |
| 1374 } {SQLITE_DONE SQLITE_OK} | |
| 1375 do_test pager1-9.4.2 { | |
| 1376 list [file size test.db2] [file size test.db] | |
| 1377 } {1024 0} | |
| 1378 db2 close | |
| 1379 | |
| 1380 #------------------------------------------------------------------------- | |
| 1381 # Test that regardless of the value returned by xSectorSize(), the | |
| 1382 # minimum effective sector-size is 512 and the maximum 65536 bytes. | |
| 1383 # | |
| 1384 testvfs tv -default 1 | |
| 1385 foreach sectorsize { | |
| 1386 16 | |
| 1387 32 64 128 256 512 1024 2048 | |
| 1388 4096 8192 16384 32768 65536 131072 262144 | |
| 1389 } { | |
| 1390 tv sectorsize $sectorsize | |
| 1391 tv devchar {} | |
| 1392 set eff $sectorsize | |
| 1393 if {$sectorsize < 512} { set eff 512 } | |
| 1394 if {$sectorsize > 65536} { set eff 65536 } | |
| 1395 | |
| 1396 do_test pager1-10.$sectorsize.1 { | |
| 1397 faultsim_delete_and_reopen | |
| 1398 db func a_string a_string | |
| 1399 execsql { | |
| 1400 PRAGMA journal_mode = PERSIST; | |
| 1401 PRAGMA page_size = 1024; | |
| 1402 BEGIN; | |
| 1403 CREATE TABLE t1(a, b); | |
| 1404 CREATE TABLE t2(a, b); | |
| 1405 CREATE TABLE t3(a, b); | |
| 1406 COMMIT; | |
| 1407 } | |
| 1408 file size test.db-journal | |
| 1409 } [expr $sectorsize > 65536 ? 65536 : ($sectorsize<32 ? 512 : $sectorsize)] | |
| 1410 | |
| 1411 do_test pager1-10.$sectorsize.2 { | |
| 1412 execsql { | |
| 1413 INSERT INTO t3 VALUES(a_string(300), a_string(300)); | |
| 1414 INSERT INTO t3 SELECT * FROM t3; /* 2 */ | |
| 1415 INSERT INTO t3 SELECT * FROM t3; /* 4 */ | |
| 1416 INSERT INTO t3 SELECT * FROM t3; /* 8 */ | |
| 1417 INSERT INTO t3 SELECT * FROM t3; /* 16 */ | |
| 1418 INSERT INTO t3 SELECT * FROM t3; /* 32 */ | |
| 1419 } | |
| 1420 } {} | |
| 1421 | |
| 1422 do_test pager1-10.$sectorsize.3 { | |
| 1423 db close | |
| 1424 sqlite3 db test.db | |
| 1425 execsql { | |
| 1426 PRAGMA cache_size = 10; | |
| 1427 BEGIN; | |
| 1428 } | |
| 1429 recursive_select 32 t3 {db eval "INSERT INTO t2 VALUES(1, 2)"} | |
| 1430 execsql { | |
| 1431 COMMIT; | |
| 1432 SELECT * FROM t2; | |
| 1433 } | |
| 1434 } {1 2} | |
| 1435 | |
| 1436 do_test pager1-10.$sectorsize.4 { | |
| 1437 execsql { | |
| 1438 CREATE TABLE t6(a, b); | |
| 1439 CREATE TABLE t7(a, b); | |
| 1440 CREATE TABLE t5(a, b); | |
| 1441 DROP TABLE t6; | |
| 1442 DROP TABLE t7; | |
| 1443 } | |
| 1444 execsql { | |
| 1445 BEGIN; | |
| 1446 CREATE TABLE t6(a, b); | |
| 1447 } | |
| 1448 recursive_select 32 t3 {db eval "INSERT INTO t5 VALUES(1, 2)"} | |
| 1449 execsql { | |
| 1450 COMMIT; | |
| 1451 SELECT * FROM t5; | |
| 1452 } | |
| 1453 } {1 2} | |
| 1454 | |
| 1455 } | |
| 1456 db close | |
| 1457 | |
| 1458 tv sectorsize 4096 | |
| 1459 do_test pager1.10.x.1 { | |
| 1460 faultsim_delete_and_reopen | |
| 1461 execsql { | |
| 1462 PRAGMA auto_vacuum = none; | |
| 1463 PRAGMA page_size = 1024; | |
| 1464 CREATE TABLE t1(x); | |
| 1465 } | |
| 1466 for {set i 0} {$i<30} {incr i} { | |
| 1467 execsql { INSERT INTO t1 VALUES(zeroblob(900)) } | |
| 1468 } | |
| 1469 file size test.db | |
| 1470 } {32768} | |
| 1471 do_test pager1.10.x.2 { | |
| 1472 execsql { | |
| 1473 CREATE TABLE t2(x); | |
| 1474 DROP TABLE t2; | |
| 1475 } | |
| 1476 file size test.db | |
| 1477 } {33792} | |
| 1478 do_test pager1.10.x.3 { | |
| 1479 execsql { | |
| 1480 BEGIN; | |
| 1481 CREATE TABLE t2(x); | |
| 1482 } | |
| 1483 recursive_select 30 t1 | |
| 1484 execsql { | |
| 1485 CREATE TABLE t3(x); | |
| 1486 COMMIT; | |
| 1487 } | |
| 1488 } {} | |
| 1489 | |
| 1490 db close | |
| 1491 tv delete | |
| 1492 | |
| 1493 testvfs tv -default 1 | |
| 1494 faultsim_delete_and_reopen | |
| 1495 db func a_string a_string | |
| 1496 do_execsql_test pager1-11.1 { | |
| 1497 PRAGMA journal_mode = DELETE; | |
| 1498 PRAGMA cache_size = 10; | |
| 1499 BEGIN; | |
| 1500 CREATE TABLE zz(top PRIMARY KEY); | |
| 1501 INSERT INTO zz VALUES(a_string(222)); | |
| 1502 INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; | |
| 1503 INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; | |
| 1504 INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; | |
| 1505 INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; | |
| 1506 INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz; | |
| 1507 COMMIT; | |
| 1508 BEGIN; | |
| 1509 UPDATE zz SET top = a_string(345); | |
| 1510 } {delete} | |
| 1511 | |
| 1512 proc lockout {method args} { return SQLITE_IOERR } | |
| 1513 tv script lockout | |
| 1514 tv filter {xWrite xTruncate xSync} | |
| 1515 do_catchsql_test pager1-11.2 { COMMIT } {1 {disk I/O error}} | |
| 1516 | |
| 1517 tv script {} | |
| 1518 do_test pager1-11.3 { | |
| 1519 sqlite3 db2 test.db | |
| 1520 execsql { | |
| 1521 PRAGMA journal_mode = TRUNCATE; | |
| 1522 PRAGMA integrity_check; | |
| 1523 } db2 | |
| 1524 } {truncate ok} | |
| 1525 do_test pager1-11.4 { | |
| 1526 db2 close | |
| 1527 file exists test.db-journal | |
| 1528 } {0} | |
| 1529 do_execsql_test pager1-11.5 { SELECT count(*) FROM zz } {32} | |
| 1530 db close | |
| 1531 tv delete | |
| 1532 | |
| 1533 #------------------------------------------------------------------------- | |
| 1534 # Test "PRAGMA page_size" | |
| 1535 # | |
| 1536 testvfs tv -default 1 | |
| 1537 tv sectorsize 1024 | |
| 1538 foreach pagesize { | |
| 1539 512 1024 2048 4096 8192 16384 32768 | |
| 1540 } { | |
| 1541 faultsim_delete_and_reopen | |
| 1542 | |
| 1543 # The sector-size (according to the VFS) is 1024 bytes. So if the | |
| 1544 # page-size requested using "PRAGMA page_size" is greater than the | |
| 1545 # compile time value of SQLITE_MAX_PAGE_SIZE, then the effective | |
| 1546 # page-size remains 1024 bytes. | |
| 1547 # | |
| 1548 set eff $pagesize | |
| 1549 if {$eff > $::SQLITE_MAX_PAGE_SIZE} { set eff 1024 } | |
| 1550 | |
| 1551 do_test pager1-12.$pagesize.1 { | |
| 1552 sqlite3 db2 test.db | |
| 1553 execsql " | |
| 1554 PRAGMA page_size = $pagesize; | |
| 1555 CREATE VIEW v AS SELECT * FROM sqlite_master; | |
| 1556 " db2 | |
| 1557 file size test.db | |
| 1558 } $eff | |
| 1559 do_test pager1-12.$pagesize.2 { | |
| 1560 sqlite3 db2 test.db | |
| 1561 execsql { | |
| 1562 SELECT count(*) FROM v; | |
| 1563 PRAGMA main.page_size; | |
| 1564 } db2 | |
| 1565 } [list 1 $eff] | |
| 1566 do_test pager1-12.$pagesize.3 { | |
| 1567 execsql { | |
| 1568 SELECT count(*) FROM v; | |
| 1569 PRAGMA main.page_size; | |
| 1570 } | |
| 1571 } [list 1 $eff] | |
| 1572 db2 close | |
| 1573 } | |
| 1574 db close | |
| 1575 tv delete | |
| 1576 | |
| 1577 #------------------------------------------------------------------------- | |
| 1578 # Test specal "PRAGMA journal_mode=PERSIST" test cases. | |
| 1579 # | |
| 1580 # pager1-13.1.*: This tests a special case encountered in persistent | |
| 1581 # journal mode: If the journal associated with a transaction | |
| 1582 # is smaller than the journal file (because a previous | |
| 1583 # transaction left a very large non-hot journal file in the | |
| 1584 # file-system), then SQLite has to be careful that there is | |
| 1585 # not a journal-header left over from a previous transaction | |
| 1586 # immediately following the journal content just written. | |
| 1587 # If there is, and the process crashes so that the journal | |
| 1588 # becomes a hot-journal and must be rolled back by another | |
| 1589 # process, there is a danger that the other process may roll | |
| 1590 # back the aborted transaction, then continue copying data | |
| 1591 # from an older transaction from the remainder of the journal. | |
| 1592 # See the syncJournal() function for details. | |
| 1593 # | |
| 1594 # pager1-13.2.*: Same test as the previous. This time, throw an index into | |
| 1595 # the mix to make the integrity-check more likely to catch | |
| 1596 # errors. | |
| 1597 # | |
| 1598 testvfs tv -default 1 | |
| 1599 tv script xSyncCb | |
| 1600 tv filter xSync | |
| 1601 proc xSyncCb {method filename args} { | |
| 1602 set t [file tail $filename] | |
| 1603 if {$t == "test.db"} faultsim_save | |
| 1604 return SQLITE_OK | |
| 1605 } | |
| 1606 faultsim_delete_and_reopen | |
| 1607 db func a_string a_string | |
| 1608 | |
| 1609 # The UPDATE statement at the end of this test case creates a really big | |
| 1610 # journal. Since the cache-size is only 10 pages, the journal contains | |
| 1611 # frequent journal headers. | |
| 1612 # | |
| 1613 do_execsql_test pager1-13.1.1 { | |
| 1614 PRAGMA page_size = 1024; | |
| 1615 PRAGMA journal_mode = PERSIST; | |
| 1616 PRAGMA cache_size = 10; | |
| 1617 BEGIN; | |
| 1618 CREATE TABLE t1(a INTEGER PRIMARY KEY, b BLOB); | |
| 1619 INSERT INTO t1 VALUES(NULL, a_string(400)); | |
| 1620 INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 2 */ | |
| 1621 INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 4 */ | |
| 1622 INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 8 */ | |
| 1623 INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 16 */ | |
| 1624 INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 32 */ | |
| 1625 INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 64 */ | |
| 1626 INSERT INTO t1 SELECT NULL, a_string(400) FROM t1; /* 128 */ | |
| 1627 COMMIT; | |
| 1628 UPDATE t1 SET b = a_string(400); | |
| 1629 } {persist} | |
| 1630 | |
| 1631 if {$::tcl_platform(platform)!="windows"} { | |
| 1632 # Run transactions of increasing sizes. Eventually, one (or more than one) | |
| 1633 # of these will write just enough content that one of the old headers created | |
| 1634 # by the transaction in the block above lies immediately after the content | |
| 1635 # journalled by the current transaction. | |
| 1636 # | |
| 1637 for {set nUp 1} {$nUp<64} {incr nUp} { | |
| 1638 do_execsql_test pager1-13.1.2.$nUp.1 { | |
| 1639 UPDATE t1 SET b = a_string(399) WHERE a <= $nUp | |
| 1640 } {} | |
| 1641 do_execsql_test pager1-13.1.2.$nUp.2 { PRAGMA integrity_check } {ok} | |
| 1642 | |
| 1643 # Try to access the snapshot of the file-system. | |
| 1644 # | |
| 1645 sqlite3 db2 sv_test.db | |
| 1646 do_test pager1-13.1.2.$nUp.3 { | |
| 1647 execsql { SELECT sum(length(b)) FROM t1 } db2 | |
| 1648 } [expr {128*400 - ($nUp-1)}] | |
| 1649 do_test pager1-13.1.2.$nUp.4 { | |
| 1650 execsql { PRAGMA integrity_check } db2 | |
| 1651 } {ok} | |
| 1652 db2 close | |
| 1653 } | |
| 1654 } | |
| 1655 | |
| 1656 if {$::tcl_platform(platform)!="windows"} { | |
| 1657 # Same test as above. But this time with an index on the table. | |
| 1658 # | |
| 1659 do_execsql_test pager1-13.2.1 { | |
| 1660 CREATE INDEX i1 ON t1(b); | |
| 1661 UPDATE t1 SET b = a_string(400); | |
| 1662 } {} | |
| 1663 for {set nUp 1} {$nUp<64} {incr nUp} { | |
| 1664 do_execsql_test pager1-13.2.2.$nUp.1 { | |
| 1665 UPDATE t1 SET b = a_string(399) WHERE a <= $nUp | |
| 1666 } {} | |
| 1667 do_execsql_test pager1-13.2.2.$nUp.2 { PRAGMA integrity_check } {ok} | |
| 1668 sqlite3 db2 sv_test.db | |
| 1669 do_test pager1-13.2.2.$nUp.3 { | |
| 1670 execsql { SELECT sum(length(b)) FROM t1 } db2 | |
| 1671 } [expr {128*400 - ($nUp-1)}] | |
| 1672 do_test pager1-13.2.2.$nUp.4 { | |
| 1673 execsql { PRAGMA integrity_check } db2 | |
| 1674 } {ok} | |
| 1675 db2 close | |
| 1676 } | |
| 1677 } | |
| 1678 | |
| 1679 db close | |
| 1680 tv delete | |
| 1681 | |
| 1682 #------------------------------------------------------------------------- | |
| 1683 # Test specal "PRAGMA journal_mode=OFF" test cases. | |
| 1684 # | |
| 1685 faultsim_delete_and_reopen | |
| 1686 do_execsql_test pager1-14.1.1 { | |
| 1687 PRAGMA journal_mode = OFF; | |
| 1688 CREATE TABLE t1(a, b); | |
| 1689 BEGIN; | |
| 1690 INSERT INTO t1 VALUES(1, 2); | |
| 1691 COMMIT; | |
| 1692 SELECT * FROM t1; | |
| 1693 } {off 1 2} | |
| 1694 do_catchsql_test pager1-14.1.2 { | |
| 1695 BEGIN; | |
| 1696 INSERT INTO t1 VALUES(3, 4); | |
| 1697 ROLLBACK; | |
| 1698 } {0 {}} | |
| 1699 do_execsql_test pager1-14.1.3 { | |
| 1700 SELECT * FROM t1; | |
| 1701 } {1 2} | |
| 1702 do_catchsql_test pager1-14.1.4 { | |
| 1703 BEGIN; | |
| 1704 INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; | |
| 1705 INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1; | |
| 1706 } {1 {UNIQUE constraint failed: t1.rowid}} | |
| 1707 do_execsql_test pager1-14.1.5 { | |
| 1708 COMMIT; | |
| 1709 SELECT * FROM t1; | |
| 1710 } {1 2 2 2} | |
| 1711 | |
| 1712 #------------------------------------------------------------------------- | |
| 1713 # Test opening and closing the pager sub-system with different values | |
| 1714 # for the sqlite3_vfs.szOsFile variable. | |
| 1715 # | |
| 1716 faultsim_delete_and_reopen | |
| 1717 do_execsql_test pager1-15.0 { | |
| 1718 CREATE TABLE tx(y, z); | |
| 1719 INSERT INTO tx VALUES('Ayutthaya', 'Beijing'); | |
| 1720 INSERT INTO tx VALUES('London', 'Tokyo'); | |
| 1721 } {} | |
| 1722 db close | |
| 1723 for {set i 0} {$i<513} {incr i 3} { | |
| 1724 testvfs tv -default 1 -szosfile $i | |
| 1725 sqlite3 db test.db | |
| 1726 do_execsql_test pager1-15.$i.1 { | |
| 1727 SELECT * FROM tx; | |
| 1728 } {Ayutthaya Beijing London Tokyo} | |
| 1729 db close | |
| 1730 tv delete | |
| 1731 } | |
| 1732 | |
| 1733 #------------------------------------------------------------------------- | |
| 1734 # Check that it is not possible to open a database file if the full path | |
| 1735 # to the associated journal file will be longer than sqlite3_vfs.mxPathname. | |
| 1736 # | |
| 1737 testvfs tv -default 1 | |
| 1738 tv script xOpenCb | |
| 1739 tv filter xOpen | |
| 1740 proc xOpenCb {method filename args} { | |
| 1741 set ::file_len [string length $filename] | |
| 1742 } | |
| 1743 sqlite3 db test.db | |
| 1744 db close | |
| 1745 tv delete | |
| 1746 | |
| 1747 for {set ii [expr $::file_len-5]} {$ii < [expr $::file_len+20]} {incr ii} { | |
| 1748 testvfs tv -default 1 -mxpathname $ii | |
| 1749 | |
| 1750 # The length of the full path to file "test.db-journal" is ($::file_len+8). | |
| 1751 # If the configured sqlite3_vfs.mxPathname value greater than or equal to | |
| 1752 # this, then the file can be opened. Otherwise, it cannot. | |
| 1753 # | |
| 1754 if {$ii >= [expr $::file_len+8]} { | |
| 1755 set res {0 {}} | |
| 1756 } else { | |
| 1757 set res {1 {unable to open database file}} | |
| 1758 } | |
| 1759 | |
| 1760 do_test pager1-16.1.$ii { | |
| 1761 list [catch { sqlite3 db test.db } msg] $msg | |
| 1762 } $res | |
| 1763 | |
| 1764 catch {db close} | |
| 1765 tv delete | |
| 1766 } | |
| 1767 | |
| 1768 | |
| 1769 #------------------------------------------------------------------------- | |
| 1770 # Test the pagers response to the b-tree layer requesting illegal page | |
| 1771 # numbers: | |
| 1772 # | |
| 1773 # + The locking page, | |
| 1774 # + Page 0, | |
| 1775 # + A page with a page number greater than (2^31-1). | |
| 1776 # | |
| 1777 # These tests will not work if SQLITE_DIRECT_OVERFLOW_READ is defined. In | |
| 1778 # that case IO errors are sometimes reported instead of SQLITE_CORRUPT. | |
| 1779 # | |
| 1780 ifcapable !direct_read { | |
| 1781 do_test pager1-18.1 { | |
| 1782 faultsim_delete_and_reopen | |
| 1783 db func a_string a_string | |
| 1784 execsql { | |
| 1785 PRAGMA page_size = 1024; | |
| 1786 CREATE TABLE t1(a, b); | |
| 1787 INSERT INTO t1 VALUES(a_string(500), a_string(200)); | |
| 1788 INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; | |
| 1789 INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; | |
| 1790 INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; | |
| 1791 INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; | |
| 1792 INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; | |
| 1793 INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; | |
| 1794 INSERT INTO t1 SELECT a_string(500), a_string(200) FROM t1; | |
| 1795 } | |
| 1796 } {} | |
| 1797 do_test pager1-18.2 { | |
| 1798 set root [db one "SELECT rootpage FROM sqlite_master"] | |
| 1799 set lockingpage [expr (0x10000/1024) + 1] | |
| 1800 execsql { | |
| 1801 PRAGMA writable_schema = 1; | |
| 1802 UPDATE sqlite_master SET rootpage = $lockingpage; | |
| 1803 } | |
| 1804 sqlite3 db2 test.db | |
| 1805 catchsql { SELECT count(*) FROM t1 } db2 | |
| 1806 } {1 {database disk image is malformed}} | |
| 1807 db2 close | |
| 1808 do_test pager1-18.3.1 { | |
| 1809 execsql { | |
| 1810 CREATE TABLE t2(x); | |
| 1811 INSERT INTO t2 VALUES(a_string(5000)); | |
| 1812 } | |
| 1813 set pgno [expr ([file size test.db] / 1024)-2] | |
| 1814 hexio_write test.db [expr ($pgno-1)*1024] 00000000 | |
| 1815 sqlite3 db2 test.db | |
| 1816 # even though x is malformed, because typeof() does | |
| 1817 # not load the content of x, the error is not noticed. | |
| 1818 catchsql { SELECT typeof(x) FROM t2 } db2 | |
| 1819 } {0 text} | |
| 1820 do_test pager1-18.3.2 { | |
| 1821 # in this case, the value of x is loaded and so the error is | |
| 1822 # detected | |
| 1823 catchsql { SELECT length(x||'') FROM t2 } db2 | |
| 1824 } {1 {database disk image is malformed}} | |
| 1825 db2 close | |
| 1826 do_test pager1-18.3.3 { | |
| 1827 execsql { | |
| 1828 DELETE FROM t2; | |
| 1829 INSERT INTO t2 VALUES(randomblob(5000)); | |
| 1830 } | |
| 1831 set pgno [expr ([file size test.db] / 1024)-2] | |
| 1832 hexio_write test.db [expr ($pgno-1)*1024] 00000000 | |
| 1833 sqlite3 db2 test.db | |
| 1834 # even though x is malformed, because length() and typeof() do | |
| 1835 # not load the content of x, the error is not noticed. | |
| 1836 catchsql { SELECT length(x), typeof(x) FROM t2 } db2 | |
| 1837 } {0 {5000 blob}} | |
| 1838 do_test pager1-18.3.4 { | |
| 1839 # in this case, the value of x is loaded and so the error is | |
| 1840 # detected | |
| 1841 catchsql { SELECT length(x||'') FROM t2 } db2 | |
| 1842 } {1 {database disk image is malformed}} | |
| 1843 db2 close | |
| 1844 do_test pager1-18.4 { | |
| 1845 hexio_write test.db [expr ($pgno-1)*1024] 90000000 | |
| 1846 sqlite3 db2 test.db | |
| 1847 catchsql { SELECT length(x||'') FROM t2 } db2 | |
| 1848 } {1 {database disk image is malformed}} | |
| 1849 db2 close | |
| 1850 do_test pager1-18.5 { | |
| 1851 sqlite3 db "" | |
| 1852 execsql { | |
| 1853 CREATE TABLE t1(a, b); | |
| 1854 CREATE TABLE t2(a, b); | |
| 1855 PRAGMA writable_schema = 1; | |
| 1856 UPDATE sqlite_master SET rootpage=5 WHERE tbl_name = 't1'; | |
| 1857 PRAGMA writable_schema = 0; | |
| 1858 ALTER TABLE t1 RENAME TO x1; | |
| 1859 } | |
| 1860 catchsql { SELECT * FROM x1 } | |
| 1861 } {1 {database disk image is malformed}} | |
| 1862 db close | |
| 1863 | |
| 1864 do_test pager1-18.6 { | |
| 1865 faultsim_delete_and_reopen | |
| 1866 db func a_string a_string | |
| 1867 execsql { | |
| 1868 PRAGMA page_size = 1024; | |
| 1869 CREATE TABLE t1(x); | |
| 1870 INSERT INTO t1 VALUES(a_string(800)); | |
| 1871 INSERT INTO t1 VALUES(a_string(800)); | |
| 1872 } | |
| 1873 | |
| 1874 set root [db one "SELECT rootpage FROM sqlite_master"] | |
| 1875 db close | |
| 1876 | |
| 1877 hexio_write test.db [expr ($root-1)*1024 + 8] 00000000 | |
| 1878 sqlite3 db test.db | |
| 1879 catchsql { SELECT length(x) FROM t1 } | |
| 1880 } {1 {database disk image is malformed}} | |
| 1881 } | |
| 1882 | |
| 1883 do_test pager1-19.1 { | |
| 1884 sqlite3 db "" | |
| 1885 db func a_string a_string | |
| 1886 execsql { | |
| 1887 PRAGMA page_size = 512; | |
| 1888 PRAGMA auto_vacuum = 1; | |
| 1889 CREATE TABLE t1(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, | |
| 1890 ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, | |
| 1891 ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn, | |
| 1892 da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn, | |
| 1893 ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, | |
| 1894 fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, | |
| 1895 ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn, | |
| 1896 ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn, | |
| 1897 ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix, | |
| 1898 ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn, | |
| 1899 ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn, | |
| 1900 la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln, | |
| 1901 ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn | |
| 1902 ); | |
| 1903 CREATE TABLE t2(aa, ab, ac, ad, ae, af, ag, ah, ai, aj, ak, al, am, an, | |
| 1904 ba, bb, bc, bd, be, bf, bg, bh, bi, bj, bk, bl, bm, bn, | |
| 1905 ca, cb, cc, cd, ce, cf, cg, ch, ci, cj, ck, cl, cm, cn, | |
| 1906 da, db, dc, dd, de, df, dg, dh, di, dj, dk, dl, dm, dn, | |
| 1907 ea, eb, ec, ed, ee, ef, eg, eh, ei, ej, ek, el, em, en, | |
| 1908 fa, fb, fc, fd, fe, ff, fg, fh, fi, fj, fk, fl, fm, fn, | |
| 1909 ga, gb, gc, gd, ge, gf, gg, gh, gi, gj, gk, gl, gm, gn, | |
| 1910 ha, hb, hc, hd, he, hf, hg, hh, hi, hj, hk, hl, hm, hn, | |
| 1911 ia, ib, ic, id, ie, if, ig, ih, ii, ij, ik, il, im, ix, | |
| 1912 ja, jb, jc, jd, je, jf, jg, jh, ji, jj, jk, jl, jm, jn, | |
| 1913 ka, kb, kc, kd, ke, kf, kg, kh, ki, kj, kk, kl, km, kn, | |
| 1914 la, lb, lc, ld, le, lf, lg, lh, li, lj, lk, ll, lm, ln, | |
| 1915 ma, mb, mc, md, me, mf, mg, mh, mi, mj, mk, ml, mm, mn | |
| 1916 ); | |
| 1917 INSERT INTO t1(aa) VALUES( a_string(100000) ); | |
| 1918 INSERT INTO t2(aa) VALUES( a_string(100000) ); | |
| 1919 VACUUM; | |
| 1920 } | |
| 1921 } {} | |
| 1922 | |
| 1923 #------------------------------------------------------------------------- | |
| 1924 # Test a couple of special cases that come up while committing | |
| 1925 # transactions: | |
| 1926 # | |
| 1927 # pager1-20.1.*: Committing an in-memory database transaction when the | |
| 1928 # database has not been modified at all. | |
| 1929 # | |
| 1930 # pager1-20.2.*: As above, but with a normal db in exclusive-locking mode. | |
| 1931 # | |
| 1932 # pager1-20.3.*: Committing a transaction in WAL mode where the database has | |
| 1933 # been modified, but all dirty pages have been flushed to | |
| 1934 # disk before the commit. | |
| 1935 # | |
| 1936 do_test pager1-20.1.1 { | |
| 1937 catch {db close} | |
| 1938 sqlite3 db :memory: | |
| 1939 execsql { | |
| 1940 CREATE TABLE one(two, three); | |
| 1941 INSERT INTO one VALUES('a', 'b'); | |
| 1942 } | |
| 1943 } {} | |
| 1944 do_test pager1-20.1.2 { | |
| 1945 execsql { | |
| 1946 BEGIN EXCLUSIVE; | |
| 1947 COMMIT; | |
| 1948 } | |
| 1949 } {} | |
| 1950 | |
| 1951 do_test pager1-20.2.1 { | |
| 1952 faultsim_delete_and_reopen | |
| 1953 execsql { | |
| 1954 PRAGMA locking_mode = exclusive; | |
| 1955 PRAGMA journal_mode = persist; | |
| 1956 CREATE TABLE one(two, three); | |
| 1957 INSERT INTO one VALUES('a', 'b'); | |
| 1958 } | |
| 1959 } {exclusive persist} | |
| 1960 do_test pager1-20.2.2 { | |
| 1961 execsql { | |
| 1962 BEGIN EXCLUSIVE; | |
| 1963 COMMIT; | |
| 1964 } | |
| 1965 } {} | |
| 1966 | |
| 1967 ifcapable wal { | |
| 1968 do_test pager1-20.3.1 { | |
| 1969 faultsim_delete_and_reopen | |
| 1970 db func a_string a_string | |
| 1971 execsql { | |
| 1972 PRAGMA cache_size = 10; | |
| 1973 PRAGMA journal_mode = wal; | |
| 1974 BEGIN; | |
| 1975 CREATE TABLE t1(x); | |
| 1976 CREATE TABLE t2(y); | |
| 1977 INSERT INTO t1 VALUES(a_string(800)); | |
| 1978 INSERT INTO t1 SELECT a_string(800) FROM t1; /* 2 */ | |
| 1979 INSERT INTO t1 SELECT a_string(800) FROM t1; /* 4 */ | |
| 1980 INSERT INTO t1 SELECT a_string(800) FROM t1; /* 8 */ | |
| 1981 INSERT INTO t1 SELECT a_string(800) FROM t1; /* 16 */ | |
| 1982 INSERT INTO t1 SELECT a_string(800) FROM t1; /* 32 */ | |
| 1983 COMMIT; | |
| 1984 } | |
| 1985 } {wal} | |
| 1986 do_test pager1-20.3.2 { | |
| 1987 execsql { | |
| 1988 BEGIN; | |
| 1989 INSERT INTO t2 VALUES('xxxx'); | |
| 1990 } | |
| 1991 recursive_select 32 t1 | |
| 1992 execsql COMMIT | |
| 1993 } {} | |
| 1994 } | |
| 1995 | |
| 1996 #------------------------------------------------------------------------- | |
| 1997 # Test that a WAL database may not be opened if: | |
| 1998 # | |
| 1999 # pager1-21.1.*: The VFS has an iVersion less than 2, or | |
| 2000 # pager1-21.2.*: The VFS does not provide xShmXXX() methods. | |
| 2001 # | |
| 2002 ifcapable wal { | |
| 2003 do_test pager1-21.0 { | |
| 2004 faultsim_delete_and_reopen | |
| 2005 execsql { | |
| 2006 PRAGMA journal_mode = WAL; | |
| 2007 CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def'); | |
| 2008 INSERT INTO ko DEFAULT VALUES; | |
| 2009 } | |
| 2010 } {wal} | |
| 2011 do_test pager1-21.1 { | |
| 2012 testvfs tv -noshm 1 | |
| 2013 sqlite3 db2 test.db -vfs tv | |
| 2014 catchsql { SELECT * FROM ko } db2 | |
| 2015 } {1 {unable to open database file}} | |
| 2016 db2 close | |
| 2017 tv delete | |
| 2018 do_test pager1-21.2 { | |
| 2019 testvfs tv -iversion 1 | |
| 2020 sqlite3 db2 test.db -vfs tv | |
| 2021 catchsql { SELECT * FROM ko } db2 | |
| 2022 } {1 {unable to open database file}} | |
| 2023 db2 close | |
| 2024 tv delete | |
| 2025 } | |
| 2026 | |
| 2027 #------------------------------------------------------------------------- | |
| 2028 # Test that a "PRAGMA wal_checkpoint": | |
| 2029 # | |
| 2030 # pager1-22.1.*: is a no-op on a non-WAL db, and | |
| 2031 # pager1-22.2.*: does not cause xSync calls with a synchronous=off db. | |
| 2032 # | |
| 2033 ifcapable wal { | |
| 2034 do_test pager1-22.1.1 { | |
| 2035 faultsim_delete_and_reopen | |
| 2036 execsql { | |
| 2037 CREATE TABLE ko(c DEFAULT 'abc', b DEFAULT 'def'); | |
| 2038 INSERT INTO ko DEFAULT VALUES; | |
| 2039 } | |
| 2040 execsql { PRAGMA wal_checkpoint } | |
| 2041 } {0 -1 -1} | |
| 2042 do_test pager1-22.2.1 { | |
| 2043 testvfs tv -default 1 | |
| 2044 tv filter xSync | |
| 2045 tv script xSyncCb | |
| 2046 proc xSyncCb {args} {incr ::synccount} | |
| 2047 set ::synccount 0 | |
| 2048 sqlite3 db test.db | |
| 2049 execsql { | |
| 2050 PRAGMA synchronous = off; | |
| 2051 PRAGMA journal_mode = WAL; | |
| 2052 INSERT INTO ko DEFAULT VALUES; | |
| 2053 } | |
| 2054 execsql { PRAGMA wal_checkpoint } | |
| 2055 set synccount | |
| 2056 } {0} | |
| 2057 db close | |
| 2058 tv delete | |
| 2059 } | |
| 2060 | |
| 2061 #------------------------------------------------------------------------- | |
| 2062 # Tests for changing journal mode. | |
| 2063 # | |
| 2064 # pager1-23.1.*: Test that when changing from PERSIST to DELETE mode, | |
| 2065 # the journal file is deleted. | |
| 2066 # | |
| 2067 # pager1-23.2.*: Same test as above, but while a shared lock is held | |
| 2068 # on the database file. | |
| 2069 # | |
| 2070 # pager1-23.3.*: Same test as above, but while a reserved lock is held | |
| 2071 # on the database file. | |
| 2072 # | |
| 2073 # pager1-23.4.*: And, for fun, while holding an exclusive lock. | |
| 2074 # | |
| 2075 # pager1-23.5.*: Try to set various different journal modes with an | |
| 2076 # in-memory database (only MEMORY and OFF should work). | |
| 2077 # | |
| 2078 # pager1-23.6.*: Try to set locking_mode=normal on an in-memory database | |
| 2079 # (doesn't work - in-memory databases always use | |
| 2080 # locking_mode=exclusive). | |
| 2081 # | |
| 2082 do_test pager1-23.1.1 { | |
| 2083 faultsim_delete_and_reopen | |
| 2084 execsql { | |
| 2085 PRAGMA journal_mode = PERSIST; | |
| 2086 CREATE TABLE t1(a, b); | |
| 2087 } | |
| 2088 file exists test.db-journal | |
| 2089 } {1} | |
| 2090 do_test pager1-23.1.2 { | |
| 2091 execsql { PRAGMA journal_mode = DELETE } | |
| 2092 file exists test.db-journal | |
| 2093 } {0} | |
| 2094 | |
| 2095 do_test pager1-23.2.1 { | |
| 2096 execsql { | |
| 2097 PRAGMA journal_mode = PERSIST; | |
| 2098 INSERT INTO t1 VALUES('Canberra', 'ACT'); | |
| 2099 } | |
| 2100 db eval { SELECT * FROM t1 } { | |
| 2101 db eval { PRAGMA journal_mode = DELETE } | |
| 2102 } | |
| 2103 execsql { PRAGMA journal_mode } | |
| 2104 } {delete} | |
| 2105 do_test pager1-23.2.2 { | |
| 2106 file exists test.db-journal | |
| 2107 } {0} | |
| 2108 | |
| 2109 do_test pager1-23.3.1 { | |
| 2110 execsql { | |
| 2111 PRAGMA journal_mode = PERSIST; | |
| 2112 INSERT INTO t1 VALUES('Darwin', 'NT'); | |
| 2113 BEGIN IMMEDIATE; | |
| 2114 } | |
| 2115 db eval { PRAGMA journal_mode = DELETE } | |
| 2116 execsql { PRAGMA journal_mode } | |
| 2117 } {delete} | |
| 2118 do_test pager1-23.3.2 { | |
| 2119 file exists test.db-journal | |
| 2120 } {0} | |
| 2121 do_test pager1-23.3.3 { | |
| 2122 execsql COMMIT | |
| 2123 } {} | |
| 2124 | |
| 2125 do_test pager1-23.4.1 { | |
| 2126 execsql { | |
| 2127 PRAGMA journal_mode = PERSIST; | |
| 2128 INSERT INTO t1 VALUES('Adelaide', 'SA'); | |
| 2129 BEGIN EXCLUSIVE; | |
| 2130 } | |
| 2131 db eval { PRAGMA journal_mode = DELETE } | |
| 2132 execsql { PRAGMA journal_mode } | |
| 2133 } {delete} | |
| 2134 do_test pager1-23.4.2 { | |
| 2135 file exists test.db-journal | |
| 2136 } {0} | |
| 2137 do_test pager1-23.4.3 { | |
| 2138 execsql COMMIT | |
| 2139 } {} | |
| 2140 | |
| 2141 do_test pager1-23.5.1 { | |
| 2142 faultsim_delete_and_reopen | |
| 2143 sqlite3 db :memory: | |
| 2144 } {} | |
| 2145 foreach {tn mode possible} { | |
| 2146 2 off 1 | |
| 2147 3 memory 1 | |
| 2148 4 persist 0 | |
| 2149 5 delete 0 | |
| 2150 6 wal 0 | |
| 2151 7 truncate 0 | |
| 2152 } { | |
| 2153 do_test pager1-23.5.$tn.1 { | |
| 2154 execsql "PRAGMA journal_mode = off" | |
| 2155 execsql "PRAGMA journal_mode = $mode" | |
| 2156 } [if $possible {list $mode} {list off}] | |
| 2157 do_test pager1-23.5.$tn.2 { | |
| 2158 execsql "PRAGMA journal_mode = memory" | |
| 2159 execsql "PRAGMA journal_mode = $mode" | |
| 2160 } [if $possible {list $mode} {list memory}] | |
| 2161 } | |
| 2162 do_test pager1-23.6.1 { | |
| 2163 execsql {PRAGMA locking_mode = normal} | |
| 2164 } {exclusive} | |
| 2165 do_test pager1-23.6.2 { | |
| 2166 execsql {PRAGMA locking_mode = exclusive} | |
| 2167 } {exclusive} | |
| 2168 do_test pager1-23.6.3 { | |
| 2169 execsql {PRAGMA locking_mode} | |
| 2170 } {exclusive} | |
| 2171 do_test pager1-23.6.4 { | |
| 2172 execsql {PRAGMA main.locking_mode} | |
| 2173 } {exclusive} | |
| 2174 | |
| 2175 #------------------------------------------------------------------------- | |
| 2176 # | |
| 2177 do_test pager1-24.1.1 { | |
| 2178 faultsim_delete_and_reopen | |
| 2179 db func a_string a_string | |
| 2180 execsql { | |
| 2181 PRAGMA cache_size = 10; | |
| 2182 PRAGMA auto_vacuum = FULL; | |
| 2183 CREATE TABLE x1(x, y, z, PRIMARY KEY(y, z)); | |
| 2184 CREATE TABLE x2(x, y, z, PRIMARY KEY(y, z)); | |
| 2185 INSERT INTO x2 VALUES(a_string(400), a_string(500), a_string(600)); | |
| 2186 INSERT INTO x2 SELECT a_string(600), a_string(400), a_string(500) FROM x2; | |
| 2187 INSERT INTO x2 SELECT a_string(500), a_string(600), a_string(400) FROM x2; | |
| 2188 INSERT INTO x2 SELECT a_string(400), a_string(500), a_string(600) FROM x2; | |
| 2189 INSERT INTO x2 SELECT a_string(600), a_string(400), a_string(500) FROM x2; | |
| 2190 INSERT INTO x2 SELECT a_string(500), a_string(600), a_string(400) FROM x2; | |
| 2191 INSERT INTO x2 SELECT a_string(400), a_string(500), a_string(600) FROM x2; | |
| 2192 INSERT INTO x1 SELECT * FROM x2; | |
| 2193 } | |
| 2194 } {} | |
| 2195 do_test pager1-24.1.2 { | |
| 2196 execsql { | |
| 2197 BEGIN; | |
| 2198 DELETE FROM x1 WHERE rowid<32; | |
| 2199 } | |
| 2200 recursive_select 64 x2 | |
| 2201 } {} | |
| 2202 do_test pager1-24.1.3 { | |
| 2203 execsql { | |
| 2204 UPDATE x1 SET z = a_string(300) WHERE rowid>40; | |
| 2205 COMMIT; | |
| 2206 PRAGMA integrity_check; | |
| 2207 SELECT count(*) FROM x1; | |
| 2208 } | |
| 2209 } {ok 33} | |
| 2210 | |
| 2211 do_test pager1-24.1.4 { | |
| 2212 execsql { | |
| 2213 DELETE FROM x1; | |
| 2214 INSERT INTO x1 SELECT * FROM x2; | |
| 2215 BEGIN; | |
| 2216 DELETE FROM x1 WHERE rowid<32; | |
| 2217 UPDATE x1 SET z = a_string(299) WHERE rowid>40; | |
| 2218 } | |
| 2219 recursive_select 64 x2 {db eval COMMIT} | |
| 2220 execsql { | |
| 2221 PRAGMA integrity_check; | |
| 2222 SELECT count(*) FROM x1; | |
| 2223 } | |
| 2224 } {ok 33} | |
| 2225 | |
| 2226 do_test pager1-24.1.5 { | |
| 2227 execsql { | |
| 2228 DELETE FROM x1; | |
| 2229 INSERT INTO x1 SELECT * FROM x2; | |
| 2230 } | |
| 2231 recursive_select 64 x2 { db eval {CREATE TABLE x3(x, y, z)} } | |
| 2232 execsql { SELECT * FROM x3 } | |
| 2233 } {} | |
| 2234 | |
| 2235 #------------------------------------------------------------------------- | |
| 2236 # | |
| 2237 do_test pager1-25-1 { | |
| 2238 faultsim_delete_and_reopen | |
| 2239 execsql { | |
| 2240 BEGIN; | |
| 2241 SAVEPOINT abc; | |
| 2242 CREATE TABLE t1(a, b); | |
| 2243 ROLLBACK TO abc; | |
| 2244 COMMIT; | |
| 2245 } | |
| 2246 db close | |
| 2247 } {} | |
| 2248 do_test pager1-25-2 { | |
| 2249 faultsim_delete_and_reopen | |
| 2250 execsql { | |
| 2251 SAVEPOINT abc; | |
| 2252 CREATE TABLE t1(a, b); | |
| 2253 ROLLBACK TO abc; | |
| 2254 COMMIT; | |
| 2255 } | |
| 2256 db close | |
| 2257 } {} | |
| 2258 | |
| 2259 #------------------------------------------------------------------------- | |
| 2260 # Sector-size tests. | |
| 2261 # | |
| 2262 do_test pager1-26.1 { | |
| 2263 testvfs tv -default 1 | |
| 2264 tv sectorsize 4096 | |
| 2265 faultsim_delete_and_reopen | |
| 2266 db func a_string a_string | |
| 2267 execsql { | |
| 2268 PRAGMA page_size = 512; | |
| 2269 CREATE TABLE tbl(a PRIMARY KEY, b UNIQUE); | |
| 2270 BEGIN; | |
| 2271 INSERT INTO tbl VALUES(a_string(25), a_string(600)); | |
| 2272 INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; | |
| 2273 INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; | |
| 2274 INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; | |
| 2275 INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; | |
| 2276 INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; | |
| 2277 INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; | |
| 2278 INSERT INTO tbl SELECT a_string(25), a_string(600) FROM tbl; | |
| 2279 COMMIT; | |
| 2280 } | |
| 2281 } {} | |
| 2282 do_execsql_test pager1-26.1 { | |
| 2283 UPDATE tbl SET b = a_string(550); | |
| 2284 } {} | |
| 2285 db close | |
| 2286 tv delete | |
| 2287 | |
| 2288 #------------------------------------------------------------------------- | |
| 2289 # | |
| 2290 do_test pager1.27.1 { | |
| 2291 faultsim_delete_and_reopen | |
| 2292 sqlite3_pager_refcounts db | |
| 2293 execsql { | |
| 2294 BEGIN; | |
| 2295 CREATE TABLE t1(a, b); | |
| 2296 } | |
| 2297 sqlite3_pager_refcounts db | |
| 2298 execsql COMMIT | |
| 2299 } {} | |
| 2300 | |
| 2301 #------------------------------------------------------------------------- | |
| 2302 # Test that attempting to open a write-transaction with | |
| 2303 # locking_mode=exclusive in WAL mode fails if there are other clients on | |
| 2304 # the same database. | |
| 2305 # | |
| 2306 catch { db close } | |
| 2307 ifcapable wal { | |
| 2308 do_multiclient_test tn { | |
| 2309 do_test pager1-28.$tn.1 { | |
| 2310 sql1 { | |
| 2311 PRAGMA journal_mode = WAL; | |
| 2312 CREATE TABLE t1(a, b); | |
| 2313 INSERT INTO t1 VALUES('a', 'b'); | |
| 2314 } | |
| 2315 } {wal} | |
| 2316 do_test pager1-28.$tn.2 { sql2 { SELECT * FROM t1 } } {a b} | |
| 2317 | |
| 2318 do_test pager1-28.$tn.3 { sql1 { PRAGMA locking_mode=exclusive } } {exclusiv
e} | |
| 2319 do_test pager1-28.$tn.4 { | |
| 2320 csql1 { BEGIN; INSERT INTO t1 VALUES('c', 'd'); } | |
| 2321 } {1 {database is locked}} | |
| 2322 code2 { db2 close ; sqlite3 db2 test.db } | |
| 2323 do_test pager1-28.$tn.4 { | |
| 2324 sql1 { INSERT INTO t1 VALUES('c', 'd'); COMMIT } | |
| 2325 } {} | |
| 2326 } | |
| 2327 } | |
| 2328 | |
| 2329 #------------------------------------------------------------------------- | |
| 2330 # Normally, when changing from journal_mode=PERSIST to DELETE the pager | |
| 2331 # attempts to delete the journal file. However, if it cannot obtain a | |
| 2332 # RESERVED lock on the database file, this step is skipped. | |
| 2333 # | |
| 2334 do_multiclient_test tn { | |
| 2335 do_test pager1-28.$tn.1 { | |
| 2336 sql1 { | |
| 2337 PRAGMA journal_mode = PERSIST; | |
| 2338 CREATE TABLE t1(a, b); | |
| 2339 INSERT INTO t1 VALUES('a', 'b'); | |
| 2340 } | |
| 2341 } {persist} | |
| 2342 do_test pager1-28.$tn.2 { file exists test.db-journal } 1 | |
| 2343 do_test pager1-28.$tn.3 { sql1 { PRAGMA journal_mode = DELETE } } delete | |
| 2344 do_test pager1-28.$tn.4 { file exists test.db-journal } 0 | |
| 2345 | |
| 2346 do_test pager1-28.$tn.5 { | |
| 2347 sql1 { | |
| 2348 PRAGMA journal_mode = PERSIST; | |
| 2349 INSERT INTO t1 VALUES('c', 'd'); | |
| 2350 } | |
| 2351 } {persist} | |
| 2352 do_test pager1-28.$tn.6 { file exists test.db-journal } 1 | |
| 2353 do_test pager1-28.$tn.7 { | |
| 2354 sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); } | |
| 2355 } {} | |
| 2356 do_test pager1-28.$tn.8 { file exists test.db-journal } 1 | |
| 2357 do_test pager1-28.$tn.9 { sql1 { PRAGMA journal_mode = DELETE } } delete | |
| 2358 do_test pager1-28.$tn.10 { file exists test.db-journal } 1 | |
| 2359 | |
| 2360 do_test pager1-28.$tn.11 { sql2 COMMIT } {} | |
| 2361 do_test pager1-28.$tn.12 { file exists test.db-journal } 0 | |
| 2362 | |
| 2363 do_test pager1-28-$tn.13 { | |
| 2364 code1 { set channel [db incrblob -readonly t1 a 2] } | |
| 2365 sql1 { | |
| 2366 PRAGMA journal_mode = PERSIST; | |
| 2367 INSERT INTO t1 VALUES('g', 'h'); | |
| 2368 } | |
| 2369 } {persist} | |
| 2370 do_test pager1-28.$tn.14 { file exists test.db-journal } 1 | |
| 2371 do_test pager1-28.$tn.15 { | |
| 2372 sql2 { BEGIN; INSERT INTO t1 VALUES('e', 'f'); } | |
| 2373 } {} | |
| 2374 do_test pager1-28.$tn.16 { sql1 { PRAGMA journal_mode = DELETE } } delete | |
| 2375 do_test pager1-28.$tn.17 { file exists test.db-journal } 1 | |
| 2376 | |
| 2377 do_test pager1-28.$tn.17 { csql2 { COMMIT } } {1 {database is locked}} | |
| 2378 do_test pager1-28-$tn.18 { code1 { read $channel } } c | |
| 2379 do_test pager1-28-$tn.19 { code1 { close $channel } } {} | |
| 2380 do_test pager1-28.$tn.20 { sql2 { COMMIT } } {} | |
| 2381 } | |
| 2382 | |
| 2383 do_test pager1-29.1 { | |
| 2384 faultsim_delete_and_reopen | |
| 2385 execsql { | |
| 2386 PRAGMA page_size = 1024; | |
| 2387 PRAGMA auto_vacuum = full; | |
| 2388 PRAGMA locking_mode=exclusive; | |
| 2389 CREATE TABLE t1(a, b); | |
| 2390 INSERT INTO t1 VALUES(1, 2); | |
| 2391 } | |
| 2392 file size test.db | |
| 2393 } [expr 1024*3] | |
| 2394 do_test pager1-29.2 { | |
| 2395 execsql { | |
| 2396 PRAGMA page_size = 4096; | |
| 2397 VACUUM; | |
| 2398 } | |
| 2399 file size test.db | |
| 2400 } [expr 4096*3] | |
| 2401 | |
| 2402 #------------------------------------------------------------------------- | |
| 2403 # Test that if an empty database file (size 0 bytes) is opened in | |
| 2404 # exclusive-locking mode, any journal file is deleted from the file-system | |
| 2405 # without being rolled back. And that the RESERVED lock obtained while | |
| 2406 # doing this is not released. | |
| 2407 # | |
| 2408 do_test pager1-30.1 { | |
| 2409 db close | |
| 2410 delete_file test.db | |
| 2411 delete_file test.db-journal | |
| 2412 set fd [open test.db-journal w] | |
| 2413 seek $fd [expr 512+1032*2] | |
| 2414 puts -nonewline $fd x | |
| 2415 close $fd | |
| 2416 | |
| 2417 sqlite3 db test.db | |
| 2418 execsql { | |
| 2419 PRAGMA locking_mode=EXCLUSIVE; | |
| 2420 SELECT count(*) FROM sqlite_master; | |
| 2421 PRAGMA lock_status; | |
| 2422 } | |
| 2423 } {exclusive 0 main reserved temp closed} | |
| 2424 | |
| 2425 #------------------------------------------------------------------------- | |
| 2426 # Test that if the "page-size" field in a journal-header is 0, the journal | |
| 2427 # file can still be rolled back. This is required for backward compatibility - | |
| 2428 # versions of SQLite prior to 3.5.8 always set this field to zero. | |
| 2429 # | |
| 2430 if {$tcl_platform(platform)=="unix"} { | |
| 2431 do_test pager1-31.1 { | |
| 2432 faultsim_delete_and_reopen | |
| 2433 execsql { | |
| 2434 PRAGMA cache_size = 10; | |
| 2435 PRAGMA page_size = 1024; | |
| 2436 CREATE TABLE t1(x, y, UNIQUE(x, y)); | |
| 2437 INSERT INTO t1 VALUES(randomblob(1500), randomblob(1500)); | |
| 2438 INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; | |
| 2439 INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; | |
| 2440 INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; | |
| 2441 INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; | |
| 2442 INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; | |
| 2443 INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; | |
| 2444 INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; | |
| 2445 INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; | |
| 2446 INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; | |
| 2447 INSERT INTO t1 SELECT randomblob(1500), randomblob(1500) FROM t1; | |
| 2448 BEGIN; | |
| 2449 UPDATE t1 SET y = randomblob(1499); | |
| 2450 } | |
| 2451 copy_file test.db test.db2 | |
| 2452 copy_file test.db-journal test.db2-journal | |
| 2453 | |
| 2454 hexio_write test.db2-journal 24 00000000 | |
| 2455 sqlite3 db2 test.db2 | |
| 2456 execsql { PRAGMA integrity_check } db2 | |
| 2457 } {ok} | |
| 2458 } | |
| 2459 | |
| 2460 #------------------------------------------------------------------------- | |
| 2461 # Test that a database file can be "pre-hinted" to a certain size and that | |
| 2462 # subsequent spilling of the pager cache does not result in the database | |
| 2463 # file being shrunk. | |
| 2464 # | |
| 2465 catch {db close} | |
| 2466 forcedelete test.db | |
| 2467 | |
| 2468 do_test pager1-32.1 { | |
| 2469 sqlite3 db test.db | |
| 2470 execsql { | |
| 2471 CREATE TABLE t1(x, y); | |
| 2472 } | |
| 2473 db close | |
| 2474 sqlite3 db test.db | |
| 2475 execsql { | |
| 2476 BEGIN; | |
| 2477 INSERT INTO t1 VALUES(1, randomblob(10000)); | |
| 2478 } | |
| 2479 file_control_chunksize_test db main 1024 | |
| 2480 file_control_sizehint_test db main 20971520; # 20MB | |
| 2481 execsql { | |
| 2482 PRAGMA cache_size = 10; | |
| 2483 INSERT INTO t1 VALUES(1, randomblob(10000)); | |
| 2484 INSERT INTO t1 VALUES(2, randomblob(10000)); | |
| 2485 INSERT INTO t1 SELECT x+2, randomblob(10000) from t1; | |
| 2486 INSERT INTO t1 SELECT x+4, randomblob(10000) from t1; | |
| 2487 INSERT INTO t1 SELECT x+8, randomblob(10000) from t1; | |
| 2488 INSERT INTO t1 SELECT x+16, randomblob(10000) from t1; | |
| 2489 SELECT count(*) FROM t1; | |
| 2490 COMMIT; | |
| 2491 } | |
| 2492 db close | |
| 2493 file size test.db | |
| 2494 } {20971520} | |
| 2495 | |
| 2496 # Cleanup 20MB file left by the previous test. | |
| 2497 forcedelete test.db | |
| 2498 | |
| 2499 #------------------------------------------------------------------------- | |
| 2500 # Test that if a transaction is committed in journal_mode=DELETE mode, | |
| 2501 # and the call to unlink() returns an ENOENT error, the COMMIT does not | |
| 2502 # succeed. | |
| 2503 # | |
| 2504 if {$::tcl_platform(platform)=="unix"} { | |
| 2505 do_test pager1-33.1 { | |
| 2506 sqlite3 db test.db | |
| 2507 execsql { | |
| 2508 CREATE TABLE t1(x); | |
| 2509 INSERT INTO t1 VALUES('one'); | |
| 2510 INSERT INTO t1 VALUES('two'); | |
| 2511 BEGIN; | |
| 2512 INSERT INTO t1 VALUES('three'); | |
| 2513 INSERT INTO t1 VALUES('four'); | |
| 2514 } | |
| 2515 forcedelete bak-journal | |
| 2516 file rename test.db-journal bak-journal | |
| 2517 | |
| 2518 catchsql COMMIT | |
| 2519 } {1 {disk I/O error}} | |
| 2520 | |
| 2521 do_test pager1-33.2 { | |
| 2522 file rename bak-journal test.db-journal | |
| 2523 execsql { SELECT * FROM t1 } | |
| 2524 } {one two} | |
| 2525 } | |
| 2526 | |
| 2527 #------------------------------------------------------------------------- | |
| 2528 # Test that appending pages to the database file then moving those pages | |
| 2529 # to the free-list before the transaction is committed does not cause | |
| 2530 # an error. | |
| 2531 # | |
| 2532 foreach {tn pragma strsize} { | |
| 2533 1 { PRAGMA mmap_size = 0 } 2400 | |
| 2534 2 { } 2400 | |
| 2535 3 { PRAGMA mmap_size = 0 } 4400 | |
| 2536 4 { } 4400 | |
| 2537 } { | |
| 2538 reset_db | |
| 2539 db func a_string a_string | |
| 2540 db eval $pragma | |
| 2541 do_execsql_test 34.$tn.1 { | |
| 2542 CREATE TABLE t1(a, b); | |
| 2543 INSERT INTO t1 VALUES(1, 2); | |
| 2544 } | |
| 2545 do_execsql_test 34.$tn.2 { | |
| 2546 BEGIN; | |
| 2547 INSERT INTO t1 VALUES(2, a_string($strsize)); | |
| 2548 DELETE FROM t1 WHERE oid=2; | |
| 2549 COMMIT; | |
| 2550 PRAGMA integrity_check; | |
| 2551 } {ok} | |
| 2552 } | |
| 2553 | |
| 2554 #------------------------------------------------------------------------- | |
| 2555 # | |
| 2556 reset_db | |
| 2557 do_test 35 { | |
| 2558 sqlite3 db test.db | |
| 2559 | |
| 2560 execsql { | |
| 2561 CREATE TABLE t1(x, y); | |
| 2562 PRAGMA journal_mode = WAL; | |
| 2563 INSERT INTO t1 VALUES(1, 2); | |
| 2564 } | |
| 2565 | |
| 2566 execsql { | |
| 2567 BEGIN; | |
| 2568 CREATE TABLE t2(a, b); | |
| 2569 } | |
| 2570 | |
| 2571 hexio_write test.db-shm [expr 16*1024] [string repeat 0055 8192] | |
| 2572 catchsql ROLLBACK | |
| 2573 } {0 {}} | |
| 2574 | |
| 2575 do_multiclient_test tn { | |
| 2576 sql1 { | |
| 2577 PRAGMA auto_vacuum = 0; | |
| 2578 CREATE TABLE t1(x, y); | |
| 2579 INSERT INTO t1 VALUES(1, 2); | |
| 2580 } | |
| 2581 | |
| 2582 do_test 36.$tn.1 { | |
| 2583 sql2 { PRAGMA max_page_count = 2 } | |
| 2584 list [catch { sql2 { CREATE TABLE t2(x) } } msg] $msg | |
| 2585 } {1 {database or disk is full}} | |
| 2586 | |
| 2587 sql1 { PRAGMA checkpoint_fullfsync = 1 } | |
| 2588 sql1 { CREATE TABLE t2(x) } | |
| 2589 | |
| 2590 do_test 36.$tn.2 { | |
| 2591 sql2 { INSERT INTO t2 VALUES('xyz') } | |
| 2592 list [catch { sql2 { CREATE TABLE t3(x) } } msg] $msg | |
| 2593 } {1 {database or disk is full}} | |
| 2594 } | |
| 2595 | |
| 2596 forcedelete test1 test2 | |
| 2597 foreach {tn uri} { | |
| 2598 1 {file:?mode=memory&cache=shared} | |
| 2599 2 {file:one?mode=memory&cache=shared} | |
| 2600 3 {file:test1?cache=shared} | |
| 2601 4 {file:test2?another=parameter&yet=anotherone} | |
| 2602 } { | |
| 2603 do_test 37.$tn { | |
| 2604 catch { db close } | |
| 2605 sqlite3_shutdown | |
| 2606 sqlite3_config_uri 1 | |
| 2607 sqlite3 db $uri | |
| 2608 | |
| 2609 db eval { | |
| 2610 CREATE TABLE t1(x); | |
| 2611 INSERT INTO t1 VALUES(1); | |
| 2612 SELECT * FROM t1; | |
| 2613 } | |
| 2614 } {1} | |
| 2615 | |
| 2616 do_execsql_test 37.$tn.2 { | |
| 2617 VACUUM; | |
| 2618 SELECT * FROM t1; | |
| 2619 } {1} | |
| 2620 | |
| 2621 db close | |
| 2622 sqlite3_shutdown | |
| 2623 sqlite3_config_uri 0 | |
| 2624 } | |
| 2625 | |
| 2626 do_test 38.1 { | |
| 2627 catch { db close } | |
| 2628 forcedelete test.db | |
| 2629 set fd [open test.db w] | |
| 2630 puts $fd "hello world" | |
| 2631 close $fd | |
| 2632 sqlite3 db test.db | |
| 2633 catchsql { CREATE TABLE t1(x) } | |
| 2634 } {1 {file is encrypted or is not a database}} | |
| 2635 do_test 38.2 { | |
| 2636 catch { db close } | |
| 2637 forcedelete test.db | |
| 2638 } {} | |
| 2639 | |
| 2640 do_test 39.1 { | |
| 2641 sqlite3 db test.db | |
| 2642 execsql { | |
| 2643 PRAGMA auto_vacuum = 1; | |
| 2644 CREATE TABLE t1(x); | |
| 2645 INSERT INTO t1 VALUES('xxx'); | |
| 2646 INSERT INTO t1 VALUES('two'); | |
| 2647 INSERT INTO t1 VALUES(randomblob(400)); | |
| 2648 INSERT INTO t1 VALUES(randomblob(400)); | |
| 2649 INSERT INTO t1 VALUES(randomblob(400)); | |
| 2650 INSERT INTO t1 VALUES(randomblob(400)); | |
| 2651 BEGIN; | |
| 2652 UPDATE t1 SET x = 'one' WHERE rowid=1; | |
| 2653 } | |
| 2654 set ::stmt [sqlite3_prepare db "SELECT * FROM t1 ORDER BY rowid" -1 dummy] | |
| 2655 sqlite3_step $::stmt | |
| 2656 sqlite3_column_text $::stmt 0 | |
| 2657 } {one} | |
| 2658 do_test 39.2 { | |
| 2659 execsql { CREATE TABLE t2(x) } | |
| 2660 sqlite3_step $::stmt | |
| 2661 sqlite3_column_text $::stmt 0 | |
| 2662 } {two} | |
| 2663 do_test 39.3 { | |
| 2664 sqlite3_finalize $::stmt | |
| 2665 execsql COMMIT | |
| 2666 } {} | |
| 2667 | |
| 2668 do_execsql_test 39.4 { | |
| 2669 PRAGMA auto_vacuum = 2; | |
| 2670 CREATE TABLE t3(x); | |
| 2671 CREATE TABLE t4(x); | |
| 2672 | |
| 2673 DROP TABLE t2; | |
| 2674 DROP TABLE t3; | |
| 2675 DROP TABLE t4; | |
| 2676 } | |
| 2677 do_test 39.5 { | |
| 2678 db close | |
| 2679 sqlite3 db test.db | |
| 2680 execsql { | |
| 2681 PRAGMA cache_size = 1; | |
| 2682 PRAGMA incremental_vacuum; | |
| 2683 PRAGMA integrity_check; | |
| 2684 } | |
| 2685 } {ok} | |
| 2686 | |
| 2687 do_test 40.1 { | |
| 2688 reset_db | |
| 2689 execsql { | |
| 2690 PRAGMA auto_vacuum = 1; | |
| 2691 CREATE TABLE t1(x PRIMARY KEY); | |
| 2692 INSERT INTO t1 VALUES(randomblob(1200)); | |
| 2693 PRAGMA page_count; | |
| 2694 } | |
| 2695 } {6} | |
| 2696 do_test 40.2 { | |
| 2697 execsql { | |
| 2698 INSERT INTO t1 VALUES(randomblob(1200)); | |
| 2699 INSERT INTO t1 VALUES(randomblob(1200)); | |
| 2700 INSERT INTO t1 VALUES(randomblob(1200)); | |
| 2701 } | |
| 2702 } {} | |
| 2703 do_test 40.3 { | |
| 2704 db close | |
| 2705 sqlite3 db test.db | |
| 2706 execsql { | |
| 2707 PRAGMA cache_size = 1; | |
| 2708 CREATE TABLE t2(x); | |
| 2709 PRAGMA integrity_check; | |
| 2710 } | |
| 2711 } {ok} | |
| 2712 | |
| 2713 do_test 41.1 { | |
| 2714 reset_db | |
| 2715 execsql { | |
| 2716 CREATE TABLE t1(x PRIMARY KEY); | |
| 2717 INSERT INTO t1 VALUES(randomblob(200)); | |
| 2718 INSERT INTO t1 SELECT randomblob(200) FROM t1; | |
| 2719 INSERT INTO t1 SELECT randomblob(200) FROM t1; | |
| 2720 INSERT INTO t1 SELECT randomblob(200) FROM t1; | |
| 2721 INSERT INTO t1 SELECT randomblob(200) FROM t1; | |
| 2722 INSERT INTO t1 SELECT randomblob(200) FROM t1; | |
| 2723 INSERT INTO t1 SELECT randomblob(200) FROM t1; | |
| 2724 } | |
| 2725 } {} | |
| 2726 do_test 41.2 { | |
| 2727 testvfs tv -default 1 | |
| 2728 tv sectorsize 16384; | |
| 2729 tv devchar [list] | |
| 2730 db close | |
| 2731 sqlite3 db test.db | |
| 2732 execsql { | |
| 2733 PRAGMA cache_size = 1; | |
| 2734 DELETE FROM t1 WHERE rowid%4; | |
| 2735 PRAGMA integrity_check; | |
| 2736 } | |
| 2737 } {ok} | |
| 2738 db close | |
| 2739 tv delete | |
| 2740 | |
| 2741 set pending_prev [sqlite3_test_control_pending_byte 0x1000000] | |
| 2742 do_test 42.1 { | |
| 2743 reset_db | |
| 2744 execsql { | |
| 2745 CREATE TABLE t1(x, y); | |
| 2746 INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); | |
| 2747 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2748 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2749 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2750 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2751 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2752 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2753 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2754 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2755 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2756 } | |
| 2757 db close | |
| 2758 sqlite3_test_control_pending_byte 0x0010000 | |
| 2759 sqlite3 db test.db | |
| 2760 db eval { PRAGMA mmap_size = 0 } | |
| 2761 catchsql { SELECT sum(length(y)) FROM t1 } | |
| 2762 } {1 {database disk image is malformed}} | |
| 2763 do_test 42.2 { | |
| 2764 reset_db | |
| 2765 execsql { | |
| 2766 CREATE TABLE t1(x, y); | |
| 2767 INSERT INTO t1 VALUES(randomblob(200), randomblob(200)); | |
| 2768 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2769 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2770 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2771 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2772 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2773 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2774 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2775 INSERT INTO t1 SELECT randomblob(200), randomblob(200) FROM t1; | |
| 2776 } | |
| 2777 db close | |
| 2778 | |
| 2779 testvfs tv -default 1 | |
| 2780 tv sectorsize 16384; | |
| 2781 tv devchar [list] | |
| 2782 sqlite3 db test.db -vfs tv | |
| 2783 execsql { UPDATE t1 SET x = randomblob(200) } | |
| 2784 } {} | |
| 2785 db close | |
| 2786 tv delete | |
| 2787 sqlite3_test_control_pending_byte $pending_prev | |
| 2788 | |
| 2789 do_test 43.1 { | |
| 2790 reset_db | |
| 2791 execsql { | |
| 2792 CREATE TABLE t1(x, y); | |
| 2793 INSERT INTO t1 VALUES(1, 2); | |
| 2794 CREATE TABLE t2(x, y); | |
| 2795 INSERT INTO t2 VALUES(1, 2); | |
| 2796 CREATE TABLE t3(x, y); | |
| 2797 INSERT INTO t3 VALUES(1, 2); | |
| 2798 } | |
| 2799 db close | |
| 2800 sqlite3 db test.db | |
| 2801 | |
| 2802 db eval { PRAGMA mmap_size = 0 } | |
| 2803 db eval { SELECT * FROM t1 } | |
| 2804 sqlite3_db_status db CACHE_MISS 0 | |
| 2805 } {0 2 0} | |
| 2806 | |
| 2807 do_test 43.2 { | |
| 2808 db eval { SELECT * FROM t2 } | |
| 2809 sqlite3_db_status db CACHE_MISS 1 | |
| 2810 } {0 3 0} | |
| 2811 | |
| 2812 do_test 43.3 { | |
| 2813 db eval { SELECT * FROM t3 } | |
| 2814 sqlite3_db_status db CACHE_MISS 0 | |
| 2815 } {0 1 0} | |
| 2816 | |
| 2817 finish_test | |
| OLD | NEW |