/ Check-in [b3f2f465]
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:Add the SQLITE_FCNTL_SYNC file-control.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b3f2f465c310a2cfef8731a0dae3453593b68de9
User & Date: dan 2011-01-11 17:39:38
Context
2011-01-11
17:40
Merge accidentally created fork. check-in: b7d080b8 user: dan tags: trunk
17:39
Add the SQLITE_FCNTL_SYNC file-control. check-in: b3f2f465 user: dan tags: trunk
16:09
If a rollback is attempted in journal_mode=off mode, force SQLite to discard the contents of the pager cache before processing any subsequent queries. check-in: ece7efce user: dan tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
....
5592
5593
5594
5595
5596
5597
5598



5599
5600
5601
5602
5603
5604
5605
....
5809
5810
5811
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
  pPager->changeCountDone = pPager->tempFile;

  if( rc==SQLITE_OK ){
    zMaster = pPager->pTmpSpace;
    rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
    testcase( rc!=SQLITE_OK );
  }
  if( rc==SQLITE_OK && !pPager->noSync 
   && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
  ){
    rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
  }
  if( rc==SQLITE_OK ){
    rc = pager_end_transaction(pPager, zMaster[0]!='\0');
    testcase( rc!=SQLITE_OK );
  }
  if( rc==SQLITE_OK && zMaster[0] && res ){
    /* If there was a master journal and this routine will return success,
................................................................................
  int rc;                              /* Return code */
  assert( !MEMDB );
  if( pPager->noSync ){
    rc = SQLITE_OK;
  }else{
    rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
  }



  return rc;
}

/*
** This function may only be called while a write-transaction is active in
** rollback. If the connection is in WAL mode, this call is a no-op. 
** Otherwise, if the connection does not already have an EXCLUSIVE lock on 
................................................................................
        Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
        assert( pPager->eState==PAGER_WRITER_DBMOD );
        rc = pager_truncate(pPager, nNew);
        if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
      }
  
      /* Finally, sync the database file. */
      if( !pPager->noSync && !noSync ){
        rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
      }
      IOTRACE(("DBSYNC %p\n", pPager))
    }
  }

commit_phase_one_exit:
  if( rc==SQLITE_OK && !pagerUseWal(pPager) ){







|


|







 







>
>
>







 







|
|







2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
....
5592
5593
5594
5595
5596
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
....
5812
5813
5814
5815
5816
5817
5818
5819
5820
5821
5822
5823
5824
5825
5826
5827
  pPager->changeCountDone = pPager->tempFile;

  if( rc==SQLITE_OK ){
    zMaster = pPager->pTmpSpace;
    rc = readMasterJournal(pPager->jfd, zMaster, pPager->pVfs->mxPathname+1);
    testcase( rc!=SQLITE_OK );
  }
  if( rc==SQLITE_OK
   && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
  ){
    rc = sqlite3PagerSync(pPager);
  }
  if( rc==SQLITE_OK ){
    rc = pager_end_transaction(pPager, zMaster[0]!='\0');
    testcase( rc!=SQLITE_OK );
  }
  if( rc==SQLITE_OK && zMaster[0] && res ){
    /* If there was a master journal and this routine will return success,
................................................................................
  int rc;                              /* Return code */
  assert( !MEMDB );
  if( pPager->noSync ){
    rc = SQLITE_OK;
  }else{
    rc = sqlite3OsSync(pPager->fd, pPager->syncFlags);
  }
  if( isOpen(pPager->fd) ){
    sqlite3OsFileControl(pPager->fd, SQLITE_FCNTL_SYNC, (void *)&rc);
  }
  return rc;
}

/*
** This function may only be called while a write-transaction is active in
** rollback. If the connection is in WAL mode, this call is a no-op. 
** Otherwise, if the connection does not already have an EXCLUSIVE lock on 
................................................................................
        Pgno nNew = pPager->dbSize - (pPager->dbSize==PAGER_MJ_PGNO(pPager));
        assert( pPager->eState==PAGER_WRITER_DBMOD );
        rc = pager_truncate(pPager, nNew);
        if( rc!=SQLITE_OK ) goto commit_phase_one_exit;
      }
  
      /* Finally, sync the database file. */
      if( !noSync ){
        rc = sqlite3PagerSync(pPager);
      }
      IOTRACE(("DBSYNC %p\n", pPager))
    }
  }

commit_phase_one_exit:
  if( rc==SQLITE_OK && !pagerUseWal(pPager) ){

Changes to src/sqlite.h.in.

711
712
713
714
715
716
717






718
719
720
721
722
723
724
725

726
727
728
729
730
731
732
** chunks (say 1MB at a time), may reduce file-system fragmentation and
** improve performance on some systems.
**
** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
** to the [sqlite3_file] object associated with a particular database
** connection.  See the [sqlite3_file_control()] documentation for
** additional information.






*/
#define SQLITE_FCNTL_LOCKSTATE        1
#define SQLITE_GET_LOCKPROXYFILE      2
#define SQLITE_SET_LOCKPROXYFILE      3
#define SQLITE_LAST_ERRNO             4
#define SQLITE_FCNTL_SIZE_HINT        5
#define SQLITE_FCNTL_CHUNK_SIZE       6
#define SQLITE_FCNTL_FILE_POINTER     7



/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks







>
>
>
>
>
>








>







711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
** chunks (say 1MB at a time), may reduce file-system fragmentation and
** improve performance on some systems.
**
** The [SQLITE_FCNTL_FILE_POINTER] opcode is used to obtain a pointer
** to the [sqlite3_file] object associated with a particular database
** connection.  See the [sqlite3_file_control()] documentation for
** additional information.
**
** The [SQLITE_FCNTL_SYNC] opcode is used internally. SQLite calls
** the file-control method with this opcode immediately after the database
** file is synced, or if the database is running in synchronous=off mode
** immediately after it would have been synced otherwise. This makes it
** easier to write special VFS modules that depend on the xSync call.
*/
#define SQLITE_FCNTL_LOCKSTATE        1
#define SQLITE_GET_LOCKPROXYFILE      2
#define SQLITE_SET_LOCKPROXYFILE      3
#define SQLITE_LAST_ERRNO             4
#define SQLITE_FCNTL_SIZE_HINT        5
#define SQLITE_FCNTL_CHUNK_SIZE       6
#define SQLITE_FCNTL_FILE_POINTER     7
#define SQLITE_FCNTL_SYNC             8


/*
** CAPI3REF: Mutex Handle
**
** The mutex module within SQLite defines [sqlite3_mutex] to be an
** abstract type for a mutex object.  The SQLite core never looks

Changes to test/jrnlmode3.test.

41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
..
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
...
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
139
140
141
142
143
144
145
146
147
148
149
150
do_test jrnlmode3-1.2 {
  db eval {
    BEGIN;
    INSERT INTO t1 VALUES(2);
    ROLLBACK;
    SELECT * FROM t1;
  }
} {1 2}

db close
file delete -force test.db test.db-journal
sqlite3 db test.db

do_test jrnlmode3-2.1 {
  db eval {
................................................................................
do_test jrnlmode3-2.2 {
  db eval {
    BEGIN;
    INSERT INTO t1 VALUES(2);
    ROLLBACK;
    SELECT * FROM t1;
  }
} {1 2}

# Test cases to verify that we can move from any journal_mode
# to any other, as long as we are not in a transaction.  Verify
# that we cannot change journal_mode while a transaction is active.
#
set all_journal_modes {delete persist truncate memory off}
set cnt 0
................................................................................
        CREATE TABLE t1(x);
        BEGIN;
        INSERT INTO t1 VALUES($cnt);
      }
      db eval "PRAGMA journal_mode=$tojmode"
    } $fromjmode

    # Rollback the transaction.  Verify that the rollback occurred
    # if journal_mode!=OFF.
    #
    do_test jrnlmode3-3.$cnt.4 {
      db eval {
        ROLLBACK;
        SELECT * FROM t1;
      }
    } [expr {$fromjmode=="off"?$cnt:""}]

    # Now change the journal mode again.  This time the new mode
    # should take.
    #
    do_test jrnlmode3-3.$cnt.5 {
      db eval "PRAGMA journal_mode=$tojmode"
    } $tojmode
................................................................................
        BEGIN;
        INSERT INTO t1 VALUES(1);
      }
      db eval ROLLBACK
      db eval {
        SELECT * FROM t1;
      }
    } [expr {$tojmode=="off"?"1":""}]
  }
}

finish_test







|







 







|







 







|
<






|







 







|




41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
..
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
...
108
109
110
111
112
113
114
115

116
117
118
119
120
121
122
123
124
125
126
127
128
129
...
138
139
140
141
142
143
144
145
146
147
148
149
do_test jrnlmode3-1.2 {
  db eval {
    BEGIN;
    INSERT INTO t1 VALUES(2);
    ROLLBACK;
    SELECT * FROM t1;
  }
} {1}

db close
file delete -force test.db test.db-journal
sqlite3 db test.db

do_test jrnlmode3-2.1 {
  db eval {
................................................................................
do_test jrnlmode3-2.2 {
  db eval {
    BEGIN;
    INSERT INTO t1 VALUES(2);
    ROLLBACK;
    SELECT * FROM t1;
  }
} {1}

# Test cases to verify that we can move from any journal_mode
# to any other, as long as we are not in a transaction.  Verify
# that we cannot change journal_mode while a transaction is active.
#
set all_journal_modes {delete persist truncate memory off}
set cnt 0
................................................................................
        CREATE TABLE t1(x);
        BEGIN;
        INSERT INTO t1 VALUES($cnt);
      }
      db eval "PRAGMA journal_mode=$tojmode"
    } $fromjmode

    # Rollback the transaction.  

    #
    do_test jrnlmode3-3.$cnt.4 {
      db eval {
        ROLLBACK;
        SELECT * FROM t1;
      }
    } {}

    # Now change the journal mode again.  This time the new mode
    # should take.
    #
    do_test jrnlmode3-3.$cnt.5 {
      db eval "PRAGMA journal_mode=$tojmode"
    } $tojmode
................................................................................
        BEGIN;
        INSERT INTO t1 VALUES(1);
      }
      db eval ROLLBACK
      db eval {
        SELECT * FROM t1;
      }
    } {}
  }
}

finish_test

Changes to test/pager1.test.

1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
do_catchsql_test pager1-14.1.2 {
  BEGIN;
    INSERT INTO t1 VALUES(3, 4);
  ROLLBACK;
} {0 {}}
do_execsql_test pager1-14.1.3 {
  SELECT * FROM t1;
} {1 2 3 4}
do_catchsql_test pager1-14.1.4 {
  BEGIN;
    INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1;
    INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1;
} {1 {PRIMARY KEY must be unique}}
do_execsql_test pager1-14.1.5 {
  COMMIT;
  SELECT * FROM t1;
} {1 2 3 4 2 2 4 4}

#-------------------------------------------------------------------------
# Test opening and closing the pager sub-system with different values
# for the sqlite3_vfs.szOsFile variable.
#
faultsim_delete_and_reopen
do_execsql_test pager1-15.0 {







|








|







1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
do_catchsql_test pager1-14.1.2 {
  BEGIN;
    INSERT INTO t1 VALUES(3, 4);
  ROLLBACK;
} {0 {}}
do_execsql_test pager1-14.1.3 {
  SELECT * FROM t1;
} {1 2}
do_catchsql_test pager1-14.1.4 {
  BEGIN;
    INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1;
    INSERT INTO t1(rowid, a, b) SELECT a+3, b, b FROM t1;
} {1 {PRIMARY KEY must be unique}}
do_execsql_test pager1-14.1.5 {
  COMMIT;
  SELECT * FROM t1;
} {1 2 2 2}

#-------------------------------------------------------------------------
# Test opening and closing the pager sub-system with different values
# for the sqlite3_vfs.szOsFile variable.
#
faultsim_delete_and_reopen
do_execsql_test pager1-15.0 {

Changes to test/pager2.test.

129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    CREATE TABLE t1(a, b);
    PRAGMA journal_mode = off;
    BEGIN;
      INSERT INTO t1 VALUES(1, 2);
    ROLLBACK;
    SELECT * FROM t1;
  }
} {off 1 2}
do_test pager2-2.2 {
  faultsim_delete_and_reopen
  execsql {
    PRAGMA auto_vacuum = incremental;
    PRAGMA page_size = 1024;
    PRAGMA journal_mode = off;
    CREATE TABLE t1(a, b);







|







129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    CREATE TABLE t1(a, b);
    PRAGMA journal_mode = off;
    BEGIN;
      INSERT INTO t1 VALUES(1, 2);
    ROLLBACK;
    SELECT * FROM t1;
  }
} {off}
do_test pager2-2.2 {
  faultsim_delete_and_reopen
  execsql {
    PRAGMA auto_vacuum = incremental;
    PRAGMA page_size = 1024;
    PRAGMA journal_mode = off;
    CREATE TABLE t1(a, b);

Changes to test/savepoint.test.

901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
        INSERT INTO t1 VALUES(13, 14);
        SAVEPOINT s1;
          INSERT INTO t1 VALUES(15, 16);
        ROLLBACK TO s1;
      ROLLBACK;
      SELECT * FROM t1;
    }
  } {1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16}
}

db close
file delete test.db
do_multiclient_test tn {
  do_test savepoint-14.$tn.1 {
    sql1 {







|







901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
        INSERT INTO t1 VALUES(13, 14);
        SAVEPOINT s1;
          INSERT INTO t1 VALUES(15, 16);
        ROLLBACK TO s1;
      ROLLBACK;
      SELECT * FROM t1;
    }
  } {1 2 3 4 5 6 7 8 9 10 11 12}
}

db close
file delete test.db
do_multiclient_test tn {
  do_test savepoint-14.$tn.1 {
    sql1 {