/ Check-in [78fc35ff]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Fix an assert in pager.c. And various test cases that fail with the in-memory journal permutation.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | mistake
Files: files | file ages | folders
SHA1: 78fc35ff4b01d4a583009ec8b8bf876738ca7b92
User & Date: dan 2010-07-03 13:45:53
Context
2010-07-03
13:50
Fix an assert in pager.c. And various test cases that fail with the in-memory journal permutation. check-in: 622378db user: dan tags: trunk
13:45
Fix an assert in pager.c. And various test cases that fail with the in-memory journal permutation. Closed-Leaf check-in: 78fc35ff user: dan tags: mistake
12:26
Remove dead code from the pager. check-in: 7cbe175a user: drh tags: mistake
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

5161
5162
5163
5164
5165
5166
5167

5168


5169
5170
5171
5172
5173
5174
5175
      ** Otherwise, if the optimization is both enabled and applicable,
      ** then call pager_incr_changecounter() to update the change-counter
      ** in 'direct' mode. In this case the journal file will never be
      ** created for this transaction.
      */
  #ifdef SQLITE_ENABLE_ATOMIC_WRITE
      PgHdr *pPg;

      assert( isOpen(pPager->jfd) || pPager->journalMode==PAGER_JOURNALMODE_OFF );


      if( !zMaster && isOpen(pPager->jfd) 
       && pPager->journalOff==jrnlBufferSize(pPager) 
       && pPager->dbSize>=pPager->dbFileSize
       && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
      ){
        /* Update the db file change counter via the direct-write method. The 
        ** following call will modify the in-memory representation of page 1 







>
|
>
>







5161
5162
5163
5164
5165
5166
5167
5168
5169
5170
5171
5172
5173
5174
5175
5176
5177
5178
      ** Otherwise, if the optimization is both enabled and applicable,
      ** then call pager_incr_changecounter() to update the change-counter
      ** in 'direct' mode. In this case the journal file will never be
      ** created for this transaction.
      */
  #ifdef SQLITE_ENABLE_ATOMIC_WRITE
      PgHdr *pPg;
      assert( isOpen(pPager->jfd) 
           || pPager->journalMode==PAGER_JOURNALMODE_OFF 
           || pPager->journalMode==PAGER_JOURNALMODE_WAL 
      );
      if( !zMaster && isOpen(pPager->jfd) 
       && pPager->journalOff==jrnlBufferSize(pPager) 
       && pPager->dbSize>=pPager->dbFileSize
       && (0==(pPg = sqlite3PcacheDirtyList(pPager->pPCache)) || 0==pPg->pDirty)
      ){
        /* Update the db file change counter via the direct-write method. The 
        ** following call will modify the in-memory representation of page 1 

Changes to test/jrnlmode.test.

499
500
501
502
503
504
505
506
















507
        PRAGMA journal_mode = DELETE;
        BEGIN IMMEDIATE; INSERT INTO t4 VALUES(1,2); COMMIT;
      }
      file exists test.db-journal
    } {0}
  }
}

















finish_test








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

499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
        PRAGMA journal_mode = DELETE;
        BEGIN IMMEDIATE; INSERT INTO t4 VALUES(1,2); COMMIT;
      }
      file exists test.db-journal
    } {0}
  }
}

ifcapable pragma {
  catch { db close }
  do_test jrnlmode-7.1 {
    foreach f [glob -nocomplain test.db*] { file delete -force $f }
    sqlite3 db test.db
    execsql {
      PRAGMA journal_mode = memory;
      PRAGMA auto_vacuum = 0;
      PRAGMA page_size = 1024;
      PRAGMA user_version = 5;
      PRAGMA user_version;
    }
  } {memory 5}
  do_test jrnlmode-7.2 { file size test.db } {1024}
}

finish_test

Changes to test/pager1.test.

555
556
557
558
559
560
561

562
563
564
565
566
567

568
569
570
571

572
573
574
575

576
577
578
579
580
581
582
...
661
662
663
664
665
666
667

668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
...
738
739
740
741
742
743
744

745
746
747
748
749
750
751
...
768
769
770
771
772
773
774

775
776
777
778
779
780
781
...
835
836
837
838
839
840
841

842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
....
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
....
1389
1390
1391
1392
1393
1394
1395

1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
  }
} {
  eval $tcl
  foreach {tn2 sql} {
    o { 
      PRAGMA main.synchronous=OFF;
      PRAGMA aux.synchronous=OFF;

    }
    o512 { 
      PRAGMA main.synchronous=OFF;
      PRAGMA aux.synchronous=OFF;
      PRAGMA main.page_size = 512;
      PRAGMA aux.page_size = 512;

    }
    n { 
      PRAGMA main.synchronous=NORMAL;
      PRAGMA aux.synchronous=NORMAL;

    }
    f { 
      PRAGMA main.synchronous=FULL;
      PRAGMA aux.synchronous=FULL;

    }
  } {

    set tn "${tn1}.${tn2}"
  
    # Set up a connection to have two databases, test.db (main) and 
    # test.db2 (aux). Then run a multi-file transaction on them. The
................................................................................
tv filter xDelete
proc copy_on_journal_delete {method filename args} {
  if {[string match *journal $filename]} faultsim_save 
  return SQLITE_OK
}
faultsim_delete_and_reopen
do_execsql_test pager1.4.5.1 {

  PRAGMA page_size = 1024;
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(a, b);
  INSERT INTO t1 VALUES('I', 'II');
  INSERT INTO t2 VALUES('III', 'IV');
  BEGIN;
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t2 VALUES(3, 4);
  COMMIT;
} {}
tv filter {}

# Check the transaction was committed:
#
do_execsql_test pager1.4.5.2 {
  SELECT * FROM t1;
  SELECT * FROM t2;
................................................................................
    faultsim_save 
  }
  return SQLITE_OK
}
do_test pager1.4.6.1 {
  faultsim_delete_and_reopen
  execsql {

    ATTACH 'test.db2' AS two;
    CREATE TABLE t1(a, b);
    CREATE TABLE two.t2(a, b);
    INSERT INTO t1 VALUES(1, 't1.1');
    INSERT INTO t2 VALUES(1, 't2.1');
    BEGIN;
      UPDATE t1 SET b = 't1.2';
................................................................................
faultsim_restore_and_reopen
db close
do_test pager1.4.6.8 {
  set ::mj_filename1 $::mj_filename
  tv filter xDelete
  sqlite3 db test.db2
  execsql {

    ATTACH 'test.db3' AS three;
    CREATE TABLE three.t3(a, b);
    INSERT INTO t3 VALUES(1, 't3.1');
    BEGIN;
      UPDATE t2 SET b = 't2.3';
      UPDATE t3 SET b = 't3.3';
    COMMIT;
................................................................................
tv filter xDelete
proc copy_on_journal_delete {method filename args} {
  if {[string match *journal $filename]} faultsim_save 
  return SQLITE_OK
}
faultsim_delete_and_reopen
do_execsql_test pager1.4.7.1 {

  CREATE TABLE t1(x PRIMARY KEY, y);
  CREATE INDEX i1 ON t1(y);
  INSERT INTO t1 VALUES('I',   'one');
  INSERT INTO t1 VALUES('II',  'four');
  INSERT INTO t1 VALUES('III', 'nine');
  BEGIN;
    INSERT INTO t1 VALUES('IV', 'sixteen');
    INSERT INTO t1 VALUES('V' , 'twentyfive');
  COMMIT;
} {}
tv filter {}
db close
tv delete 
do_test pager1.4.7.2 {
  faultsim_restore_and_reopen
  catch {file attributes test.db-journal -permissions r--------}
  catch {file attributes test.db-journal -readonly 1}
................................................................................
    execsql {
      CREATE TABLE t6(a, b);
      CREATE TABLE t7(a, b);
      CREATE TABLE t5(a, b);
      DROP TABLE t6;
      DROP TABLE t7;
    }
    if {$eff==65536} breakpoint
    execsql {
      BEGIN;
        CREATE TABLE t6(a, b);
    }
    recursive_select 32 t3 {db eval "INSERT INTO t5 VALUES(1, 2)"}
    execsql {
      COMMIT;
................................................................................
db close
tv delete

testvfs tv -default 1
faultsim_delete_and_reopen
db func a_string a_string
do_execsql_test pager1-11.1 {

  PRAGMA cache_size = 10;
  BEGIN;
    CREATE TABLE zz(top PRIMARY KEY);
    INSERT INTO zz VALUES(a_string(222));
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
  COMMIT;
  BEGIN;
    UPDATE zz SET top = a_string(345);
} {}

proc lockout {method args} { return SQLITE_IOERR }
tv script lockout
tv filter {xWrite xTruncate xSync}
do_catchsql_test pager1-11.2 { COMMIT } {1 {disk I/O error}}

tv script {}







>






>




>




>







 







>









|







 







>







 







>







 







>









|







 







<







 







>












|







555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
...
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
...
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
...
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
...
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
....
1343
1344
1345
1346
1347
1348
1349

1350
1351
1352
1353
1354
1355
1356
....
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
  }
} {
  eval $tcl
  foreach {tn2 sql} {
    o { 
      PRAGMA main.synchronous=OFF;
      PRAGMA aux.synchronous=OFF;
      PRAGMA journal_mode = DELETE;
    }
    o512 { 
      PRAGMA main.synchronous=OFF;
      PRAGMA aux.synchronous=OFF;
      PRAGMA main.page_size = 512;
      PRAGMA aux.page_size = 512;
      PRAGMA journal_mode = DELETE;
    }
    n { 
      PRAGMA main.synchronous=NORMAL;
      PRAGMA aux.synchronous=NORMAL;
      PRAGMA journal_mode = DELETE;
    }
    f { 
      PRAGMA main.synchronous=FULL;
      PRAGMA aux.synchronous=FULL;
      PRAGMA journal_mode = DELETE;
    }
  } {

    set tn "${tn1}.${tn2}"
  
    # Set up a connection to have two databases, test.db (main) and 
    # test.db2 (aux). Then run a multi-file transaction on them. The
................................................................................
tv filter xDelete
proc copy_on_journal_delete {method filename args} {
  if {[string match *journal $filename]} faultsim_save 
  return SQLITE_OK
}
faultsim_delete_and_reopen
do_execsql_test pager1.4.5.1 {
  PRAGMA journal_mode = DELETE;
  PRAGMA page_size = 1024;
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(a, b);
  INSERT INTO t1 VALUES('I', 'II');
  INSERT INTO t2 VALUES('III', 'IV');
  BEGIN;
    INSERT INTO t1 VALUES(1, 2);
    INSERT INTO t2 VALUES(3, 4);
  COMMIT;
} {delete}
tv filter {}

# Check the transaction was committed:
#
do_execsql_test pager1.4.5.2 {
  SELECT * FROM t1;
  SELECT * FROM t2;
................................................................................
    faultsim_save 
  }
  return SQLITE_OK
}
do_test pager1.4.6.1 {
  faultsim_delete_and_reopen
  execsql {
    PRAGMA journal_mode = DELETE;
    ATTACH 'test.db2' AS two;
    CREATE TABLE t1(a, b);
    CREATE TABLE two.t2(a, b);
    INSERT INTO t1 VALUES(1, 't1.1');
    INSERT INTO t2 VALUES(1, 't2.1');
    BEGIN;
      UPDATE t1 SET b = 't1.2';
................................................................................
faultsim_restore_and_reopen
db close
do_test pager1.4.6.8 {
  set ::mj_filename1 $::mj_filename
  tv filter xDelete
  sqlite3 db test.db2
  execsql {
    PRAGMA journal_mode = DELETE;
    ATTACH 'test.db3' AS three;
    CREATE TABLE three.t3(a, b);
    INSERT INTO t3 VALUES(1, 't3.1');
    BEGIN;
      UPDATE t2 SET b = 't2.3';
      UPDATE t3 SET b = 't3.3';
    COMMIT;
................................................................................
tv filter xDelete
proc copy_on_journal_delete {method filename args} {
  if {[string match *journal $filename]} faultsim_save 
  return SQLITE_OK
}
faultsim_delete_and_reopen
do_execsql_test pager1.4.7.1 {
  PRAGMA journal_mode = DELETE;
  CREATE TABLE t1(x PRIMARY KEY, y);
  CREATE INDEX i1 ON t1(y);
  INSERT INTO t1 VALUES('I',   'one');
  INSERT INTO t1 VALUES('II',  'four');
  INSERT INTO t1 VALUES('III', 'nine');
  BEGIN;
    INSERT INTO t1 VALUES('IV', 'sixteen');
    INSERT INTO t1 VALUES('V' , 'twentyfive');
  COMMIT;
} {delete}
tv filter {}
db close
tv delete 
do_test pager1.4.7.2 {
  faultsim_restore_and_reopen
  catch {file attributes test.db-journal -permissions r--------}
  catch {file attributes test.db-journal -readonly 1}
................................................................................
    execsql {
      CREATE TABLE t6(a, b);
      CREATE TABLE t7(a, b);
      CREATE TABLE t5(a, b);
      DROP TABLE t6;
      DROP TABLE t7;
    }

    execsql {
      BEGIN;
        CREATE TABLE t6(a, b);
    }
    recursive_select 32 t3 {db eval "INSERT INTO t5 VALUES(1, 2)"}
    execsql {
      COMMIT;
................................................................................
db close
tv delete

testvfs tv -default 1
faultsim_delete_and_reopen
db func a_string a_string
do_execsql_test pager1-11.1 {
  PRAGMA journal_mode = DELETE;
  PRAGMA cache_size = 10;
  BEGIN;
    CREATE TABLE zz(top PRIMARY KEY);
    INSERT INTO zz VALUES(a_string(222));
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
    INSERT INTO zz SELECT a_string((SELECT 222+max(rowid) FROM zz)) FROM zz;
  COMMIT;
  BEGIN;
    UPDATE zz SET top = a_string(345);
} {delete}

proc lockout {method args} { return SQLITE_IOERR }
tv script lockout
tv filter {xWrite xTruncate xSync}
do_catchsql_test pager1-11.2 { COMMIT } {1 {disk I/O error}}

tv script {}

Changes to test/walmode.test.

11
12
13
14
15
16
17

18
19
20
21
22
23
24
...
263
264
265
266
267
268
269




















270
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the operation of the library in
# "PRAGMA journal_mode=WAL" mode.
#

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


# If the library was compiled without WAL support, check that the 
# "PRAGMA journal_mode=WAL" treats "WAL" as an unrecognized mode.
#
ifcapable !wal {

  do_test walmode-0.1 {
................................................................................
  execsql { 
    INSERT INTO t1 VALUES(3, 4);
    SELECT * FROM t1;
    PRAGMA temp.journal_mode;
  }
} [list 1 2 3 4 $tempJrnlMode]





















finish_test







>







 







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

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the operation of the library in
# "PRAGMA journal_mode=WAL" mode.
#

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

# If the library was compiled without WAL support, check that the 
# "PRAGMA journal_mode=WAL" treats "WAL" as an unrecognized mode.
#
ifcapable !wal {

  do_test walmode-0.1 {
................................................................................
  execsql { 
    INSERT INTO t1 VALUES(3, 4);
    SELECT * FROM t1;
    PRAGMA temp.journal_mode;
  }
} [list 1 2 3 4 $tempJrnlMode]


#-------------------------------------------------------------------------
# Test changing to WAL mode from journal_mode=off or journal_mode=memory
#
foreach {tn mode} {
  3 persist
  4 delete
  5 truncate
  2 memory
  1 off
} {
  do_test walmode-6.$tn {
    faultsim_delete_and_reopen
    execsql "
      PRAGMA journal_mode = $mode;
      PRAGMA journal_mode = wal;
    "
  } [list $mode wal]
}

finish_test