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