/ Check-in [04d3b909]
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:Always enable exclusive access mode for TEMP databases. This cannot be changed. The locking_mode pragma has not effect on the TEMP database. (CVS 3766)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 04d3b9098ed06d5be24253edde50ea61b4641df8
User & Date: drh 2007-03-30 16:01:55
Context
2007-03-30
17:11
Coverage tests for some pragmas. (CVS 3767) check-in: eec7ab63 user: danielk1977 tags: trunk
16:01
Always enable exclusive access mode for TEMP databases. This cannot be changed. The locking_mode pragma has not effect on the TEMP database. (CVS 3766) check-in: 04d3b909 user: drh tags: trunk
14:56
Coverage improvements for where.c. (CVS 3765) check-in: df64894b user: danielk1977 tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/pager.c.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99

100
101
102



103
104
105
106
107
108
109
....
1777
1778
1779
1780
1781
1782
1783




1784
1785
1786
1787
1788
1789
1790
....
3188
3189
3190
3191
3192
3193
3194

3195
3196
3197
3198
3199
3200

3201
3202
3203
3204
3205
3206
3207
....
4169
4170
4171
4172
4173
4174
4175





4176
4177
4178
4179
4180
4181
4182
4183
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.308 2007/03/30 14:46:01 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>
................................................................................
**                       Access is exclusive.  No other processes or
**                       threads can be reading or writing while one
**                       process is writing.
**
**   PAGER_SYNCED        The pager moves to this state from PAGER_EXCLUSIVE
**                       after all dirty pages have been written to the
**                       database file and the file has been synced to
**                       disk. All that remains to do is to remove the
**                       journal file and the transaction will be
**                       committed.
**
** The page cache comes up in PAGER_UNLOCK.  The first time a
** sqlite3PagerGet() occurs, the state transitions to PAGER_SHARED.
** After all pages have been released using sqlite_page_unref(),
** the state transitions back to PAGER_UNLOCK.  The first time
** that sqlite3PagerWrite() is called, the state transitions to
** PAGER_RESERVED.  (Note that sqlite_page_write() can only be
** called on an outstanding page which means that the pager must
** be in PAGER_SHARED before it transitions to PAGER_RESERVED.)

** The transition to PAGER_EXCLUSIVE occurs when before any changes
** are made to the database file.  After an sqlite3PagerRollback()
** or sqlite_pager_commit(), the state goes back to PAGER_SHARED.



*/
#define PAGER_UNLOCK      0
#define PAGER_SHARED      1   /* same as SHARED_LOCK */
#define PAGER_RESERVED    2   /* same as RESERVED_LOCK */
#define PAGER_EXCLUSIVE   4   /* same as EXCLUSIVE_LOCK */
#define PAGER_SYNCED      5

................................................................................
  /* pPager->nPage = 0; */
  /* pPager->nMaxPage = 0; */
  pPager->mxPage = 100;
  assert( PAGER_UNLOCK==0 );
  /* pPager->state = PAGER_UNLOCK; */
  /* pPager->errMask = 0; */
  pPager->tempFile = tempFile;




  pPager->memDb = memDb;
  pPager->readOnly = readOnly;
  /* pPager->needSync = 0; */
  pPager->noSync = pPager->tempFile || !useJournal;
  pPager->fullSync = (pPager->noSync?0:1);
  /* pPager->pFirst = 0; */
  /* pPager->pFirstSynced = 0; */
................................................................................
    /* This happens when the pager was in exclusive-access mode last
    ** time a (read or write) transaction was successfully concluded
    ** by this connection. Instead of deleting the journal file it was 
    ** kept open and truncated to 0 bytes.
    */
    assert( pPager->nRec==0 );
    assert( pPager->origDbSize==0 );

    sqlite3PagerPagecount(pPager);
    pPager->origDbSize = pPager->dbSize;
    pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
    if( !pPager->aInJournal ){
      rc = SQLITE_NOMEM;
    }else{

      rc = writeJournalHdr(pPager);
    }
  }
  assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK );
  return rc;
}

................................................................................
** the locking-mode is set to the value specified.
**
** The returned value is either PAGER_LOCKINGMODE_NORMAL or
** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated)
** locking-mode.
*/
int sqlite3PagerLockingMode(Pager *pPager, int eMode){





  if( eMode>=0 ){
    pPager->exclusiveMode = eMode;
  }
  return (int)pPager->exclusiveMode;
}

#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*







|







 







|
|
|






|


>
|
|
<
>
>
>







 







>
>
>
>







 







>

<




>







 







>
>
>
>
>
|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102

103
104
105
106
107
108
109
110
111
112
....
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
....
3195
3196
3197
3198
3199
3200
3201
3202
3203

3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
....
4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
** The pager is used to access a database disk file.  It implements
** atomic commit and rollback through the use of a journal file that
** is separate from the database file.  The pager also implements file
** locking to prevent two processes from writing the same database
** file simultaneously, or one process from reading the database while
** another is writing.
**
** @(#) $Id: pager.c,v 1.309 2007/03/30 16:01:55 drh Exp $
*/
#ifndef SQLITE_OMIT_DISKIO
#include "sqliteInt.h"
#include "os.h"
#include "pager.h"
#include <assert.h>
#include <string.h>
................................................................................
**                       Access is exclusive.  No other processes or
**                       threads can be reading or writing while one
**                       process is writing.
**
**   PAGER_SYNCED        The pager moves to this state from PAGER_EXCLUSIVE
**                       after all dirty pages have been written to the
**                       database file and the file has been synced to
**                       disk. All that remains to do is to remove or
**                       truncate the journal file and the transaction 
**                       will be committed.
**
** The page cache comes up in PAGER_UNLOCK.  The first time a
** sqlite3PagerGet() occurs, the state transitions to PAGER_SHARED.
** After all pages have been released using sqlite_page_unref(),
** the state transitions back to PAGER_UNLOCK.  The first time
** that sqlite3PagerWrite() is called, the state transitions to
** PAGER_RESERVED.  (Note that sqlite3PagerWrite() can only be
** called on an outstanding page which means that the pager must
** be in PAGER_SHARED before it transitions to PAGER_RESERVED.)
** PAGER_RESERVED means that there is an open rollback journal.
** The transition to PAGER_EXCLUSIVE occurs before any changes
** are made to the database file, though writes to the rollback

** journal occurs with just PAGER_RESERVED.  After an sqlite3PagerRollback()
** or sqlite3PagerCommitPhaseTwo(), the state can go back to PAGER_SHARED,
** or it can stay at PAGER_EXCLUSIVE if we are in exclusive access mode.
*/
#define PAGER_UNLOCK      0
#define PAGER_SHARED      1   /* same as SHARED_LOCK */
#define PAGER_RESERVED    2   /* same as RESERVED_LOCK */
#define PAGER_EXCLUSIVE   4   /* same as EXCLUSIVE_LOCK */
#define PAGER_SYNCED      5

................................................................................
  /* pPager->nPage = 0; */
  /* pPager->nMaxPage = 0; */
  pPager->mxPage = 100;
  assert( PAGER_UNLOCK==0 );
  /* pPager->state = PAGER_UNLOCK; */
  /* pPager->errMask = 0; */
  pPager->tempFile = tempFile;
  assert( tempFile==PAGER_LOCKINGMODE_NORMAL 
          || tempFile==PAGER_LOCKINGMODE_EXCLUSIVE );
  assert( PAGER_LOCKINGMODE_EXCLUSIVE==1 );
  pPager->exclusiveMode = tempFile; 
  pPager->memDb = memDb;
  pPager->readOnly = readOnly;
  /* pPager->needSync = 0; */
  pPager->noSync = pPager->tempFile || !useJournal;
  pPager->fullSync = (pPager->noSync?0:1);
  /* pPager->pFirst = 0; */
  /* pPager->pFirstSynced = 0; */
................................................................................
    /* This happens when the pager was in exclusive-access mode last
    ** time a (read or write) transaction was successfully concluded
    ** by this connection. Instead of deleting the journal file it was 
    ** kept open and truncated to 0 bytes.
    */
    assert( pPager->nRec==0 );
    assert( pPager->origDbSize==0 );
    assert( pPager->aInJournal==0 );
    sqlite3PagerPagecount(pPager);

    pPager->aInJournal = sqliteMalloc( pPager->dbSize/8 + 1 );
    if( !pPager->aInJournal ){
      rc = SQLITE_NOMEM;
    }else{
      pPager->origDbSize = pPager->dbSize;
      rc = writeJournalHdr(pPager);
    }
  }
  assert( !pPager->journalOpen || pPager->journalOff>0 || rc!=SQLITE_OK );
  return rc;
}

................................................................................
** the locking-mode is set to the value specified.
**
** The returned value is either PAGER_LOCKINGMODE_NORMAL or
** PAGER_LOCKINGMODE_EXCLUSIVE, indicating the current (possibly updated)
** locking-mode.
*/
int sqlite3PagerLockingMode(Pager *pPager, int eMode){
  assert( eMode==PAGER_LOCKINGMODE_QUERY
            || eMode==PAGER_LOCKINGMODE_NORMAL
            || eMode==PAGER_LOCKINGMODE_EXCLUSIVE );
  assert( PAGER_LOCKINGMODE_QUERY<0 );
  assert( PAGER_LOCKINGMODE_NORMAL>=0 && PAGER_LOCKINGMODE_EXCLUSIVE>=0 );
  if( eMode>=0 && !pPager->tempFile ){
    pPager->exclusiveMode = eMode;
  }
  return (int)pPager->exclusiveMode;
}

#if defined(SQLITE_DEBUG) || defined(SQLITE_TEST)
/*

Changes to test/exclusive.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49

50
51
52
53
54
55
56
57
58
59
60

61
62
63
64
65
66
67
68
69
70
71

72
73
74
75
76
77
78
79
80
..
83
84
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99
...
117
118
119
120
121
122
123

124
125
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145
...
363
364
365
366
367
368
369
370








371
372
373
374
375
376
377
...
418
419
420
421
422
423
424
425
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The focus
# of these tests is exclusive access mode (i.e. the thing activated by 
# "PRAGMA locking_mode = EXCLUSIVE").
#
# $Id: exclusive.test,v 1.3 2007/03/26 10:27:19 danielk1977 Exp $

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

ifcapable {!pager_pragmas} {
  finish_test
  return
................................................................................
#----------------------------------------------------------------------
# Test cases exclusive-1.X test the PRAGMA logic.
#
do_test exclusive-1.0 {
  execsql {
    pragma locking_mode;
    pragma main.locking_mode;

  } 
} {normal normal}
do_test exclusive-1.1 {
  execsql {
    pragma locking_mode = exclusive;
  } 
} {exclusive}
do_test exclusive-1.2 {
  execsql {
    pragma locking_mode;
    pragma main.locking_mode;

  } 
} {exclusive exclusive}
do_test exclusive-1.3 {
  execsql {
    pragma locking_mode = normal;
  } 
} {normal}
do_test exclusive-1.4 {
  execsql {
    pragma locking_mode;
    pragma main.locking_mode;

  } 
} {normal normal}
do_test exclusive-1.5 {
  execsql {
    pragma locking_mode = invalid;
  } 
} {normal}
do_test exclusive-1.6 {
  execsql {
    pragma locking_mode;
    pragma main.locking_mode;

  } 
} {normal normal}
do_test exclusive-1.7 {
  execsql {
    pragma locking_mode = exclusive;
    ATTACH 'test2.db' as aux;
  }
  execsql {
    pragma main.locking_mode;
................................................................................
} {exclusive exclusive}
do_test exclusive-1.8 {
  execsql {
    pragma main.locking_mode = normal;
  }
  execsql {
    pragma main.locking_mode;

    pragma aux.locking_mode;
  }
} {normal exclusive}
do_test exclusive-1.9 {
  execsql {
    pragma locking_mode;
  }
} {exclusive}
do_test exclusive-1.10 {
  execsql {
................................................................................
} {normal normal exclusive}
do_test exclusive-1.12 {
  execsql {
    pragma locking_mode = normal;
  }
  execsql {
    pragma main.locking_mode;

    pragma aux.locking_mode;
    pragma aux2.locking_mode;
  }
} {normal normal normal}
do_test exclusive-1.13 {
  execsql {
    ATTACH 'test4.db' as aux3;
  }
  execsql {
    pragma main.locking_mode;

    pragma aux.locking_mode;
    pragma aux2.locking_mode;
    pragma aux3.locking_mode;
  }
} {normal normal normal normal}

do_test exclusive-1.99 {
  execsql {
    DETACH aux;
    DETACH aux2;
    DETACH aux3;
  }
................................................................................
  }
} {normal}

#----------------------------------------------------------------------
# Tests exclusive-5.X - test that statement journals are truncated
# instead of deleted when in exclusive access mode.
#
#set sqlite_os_trace 1








do_test exclusive-5.0 {
  execsql {
    CREATE TABLE abc(a UNIQUE, b UNIQUE, c UNIQUE);
    BEGIN;
    INSERT INTO abc VALUES(1, 2, 3);
    INSERT INTO abc SELECT a+1, b+1, c+1 FROM abc;
  }
................................................................................
} {normal 1 2 3 2 3 4 5 6 7 11 12 13 12 13 14 15 16 17}
do_test exclusive-5.7 {
  # Just the db open.
  set sqlite_open_file_count
} {1}

finish_test








|







 







>

|









>

|









>

|









>

|







 







>


|







 







>



|






>




|







 







<
>
>
>
>
>
>
>
>







 







<
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
..
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
...
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
370
371
372
373
374
375
376

377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
...
432
433
434
435
436
437
438

#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library. The focus
# of these tests is exclusive access mode (i.e. the thing activated by 
# "PRAGMA locking_mode = EXCLUSIVE").
#
# $Id: exclusive.test,v 1.4 2007/03/30 16:01:55 drh Exp $

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

ifcapable {!pager_pragmas} {
  finish_test
  return
................................................................................
#----------------------------------------------------------------------
# Test cases exclusive-1.X test the PRAGMA logic.
#
do_test exclusive-1.0 {
  execsql {
    pragma locking_mode;
    pragma main.locking_mode;
    pragma temp.locking_mode;
  } 
} {normal normal exclusive}
do_test exclusive-1.1 {
  execsql {
    pragma locking_mode = exclusive;
  } 
} {exclusive}
do_test exclusive-1.2 {
  execsql {
    pragma locking_mode;
    pragma main.locking_mode;
    pragma temp.locking_mode;
  } 
} {exclusive exclusive exclusive}
do_test exclusive-1.3 {
  execsql {
    pragma locking_mode = normal;
  } 
} {normal}
do_test exclusive-1.4 {
  execsql {
    pragma locking_mode;
    pragma main.locking_mode;
    pragma temp.locking_mode;
  } 
} {normal normal exclusive}
do_test exclusive-1.5 {
  execsql {
    pragma locking_mode = invalid;
  } 
} {normal}
do_test exclusive-1.6 {
  execsql {
    pragma locking_mode;
    pragma main.locking_mode;
    pragma temp.locking_mode;
  } 
} {normal normal exclusive}
do_test exclusive-1.7 {
  execsql {
    pragma locking_mode = exclusive;
    ATTACH 'test2.db' as aux;
  }
  execsql {
    pragma main.locking_mode;
................................................................................
} {exclusive exclusive}
do_test exclusive-1.8 {
  execsql {
    pragma main.locking_mode = normal;
  }
  execsql {
    pragma main.locking_mode;
    pragma temp.locking_mode;
    pragma aux.locking_mode;
  }
} {normal exclusive exclusive}
do_test exclusive-1.9 {
  execsql {
    pragma locking_mode;
  }
} {exclusive}
do_test exclusive-1.10 {
  execsql {
................................................................................
} {normal normal exclusive}
do_test exclusive-1.12 {
  execsql {
    pragma locking_mode = normal;
  }
  execsql {
    pragma main.locking_mode;
    pragma temp.locking_mode;
    pragma aux.locking_mode;
    pragma aux2.locking_mode;
  }
} {normal exclusive normal normal}
do_test exclusive-1.13 {
  execsql {
    ATTACH 'test4.db' as aux3;
  }
  execsql {
    pragma main.locking_mode;
    pragma temp.locking_mode;
    pragma aux.locking_mode;
    pragma aux2.locking_mode;
    pragma aux3.locking_mode;
  }
} {normal exclusive normal normal normal}

do_test exclusive-1.99 {
  execsql {
    DETACH aux;
    DETACH aux2;
    DETACH aux3;
  }
................................................................................
  }
} {normal}

#----------------------------------------------------------------------
# Tests exclusive-5.X - test that statement journals are truncated
# instead of deleted when in exclusive access mode.
#


# Close and reopen the database so that the temp database is no
# longer active.
#
db close
sqlite db test.db


do_test exclusive-5.0 {
  execsql {
    CREATE TABLE abc(a UNIQUE, b UNIQUE, c UNIQUE);
    BEGIN;
    INSERT INTO abc VALUES(1, 2, 3);
    INSERT INTO abc SELECT a+1, b+1, c+1 FROM abc;
  }
................................................................................
} {normal 1 2 3 2 3 4 5 6 7 11 12 13 12 13 14 15 16 17}
do_test exclusive-5.7 {
  # Just the db open.
  set sqlite_open_file_count
} {1}

finish_test

Changes to test/exclusive3.test.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
53
54
55
56
57
58
59
60
# 2001 September 15
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file runs the tests in the file ioerr.test with auto-vacuum enabled
# databases.
#
# $Id: exclusive3.test,v 1.2 2007/03/27 16:19:52 danielk1977 Exp $

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

ifcapable {!pager_pragmas} {
  finish_test
  return
................................................................................
rename sqlite3 ""
rename real_sqlite3 sqlite3
rename finish_test ""
rename really_finish_test2 finish_test
rename do_test ""
rename really_do_test do_test
finish_test

|










|
|

|







 







<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
53
54
55
56
57
58
59

# 2007 March 26
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# This file runs the tests in the file ioerr.test with 
# exclusive access mode enabled.
#
# $Id: exclusive3.test,v 1.3 2007/03/30 16:01:55 drh Exp $

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

ifcapable {!pager_pragmas} {
  finish_test
  return
................................................................................
rename sqlite3 ""
rename real_sqlite3 sqlite3
rename finish_test ""
rename really_finish_test2 finish_test
rename do_test ""
rename really_do_test do_test
finish_test