SQLite

Check-in [04d3b9098e]
Login

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
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 04d3b9098ed06d5be24253edde50ea61b4641df8
User & Date: drh 2007-03-30 16:01:55.000
Context
2007-03-30
17:11
Coverage tests for some pragmas. (CVS 3767) (check-in: eec7ab63be 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: 04d3b9098e user: drh tags: trunk)
14:56
Coverage improvements for where.c. (CVS 3765) (check-in: df64894bac user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/pager.c.
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** 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>







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
** 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>
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
**                       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








|
|
|






|


>
|
|
>
|
>







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
**                       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

1777
1778
1779
1780
1781
1782
1783




1784
1785
1786
1787
1788
1789
1790
  /* 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; */







>
>
>
>







1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
  /* 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; */
3188
3189
3190
3191
3192
3193
3194

3195
3196
3197
3198
3199
3200

3201
3202
3203
3204
3205
3206
3207
    /* 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;
}








>

<




>







3195
3196
3197
3198
3199
3200
3201
3202
3203

3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
    /* 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;
}

4169
4170
4171
4172
4173
4174
4175





4176
4177
4178
4179
4180
4181
4182
4183
** 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)
/*







>
>
>
>
>
|







4177
4178
4179
4180
4181
4182
4183
4184
4185
4186
4187
4188
4189
4190
4191
4192
4193
4194
4195
4196
** 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
#    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







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#    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
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
85
86
87
88
89

90
91
92
93
94
95
96
97
98
99
#----------------------------------------------------------------------
# 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;
    pragma aux.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 {







>

|









>

|









>

|









>

|
















>


|







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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#----------------------------------------------------------------------
# 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;
    pragma aux.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 {
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
} {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;
  }







>



|






>




|







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
} {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;
  }
363
364
365
366
367
368
369
370







371
372
373
374
375
376
377
  }
} {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;
  }







|
>
>
>
>
>
>
>







370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
  }
} {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;
  }
418
419
420
421
422
423
424
425
} {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








<
432
433
434
435
436
437
438

} {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
# 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
|










|
|

|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 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
53
54
55
56
57
58
59
60
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








<
53
54
55
56
57
58
59

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