Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Change the journal_mode pragma so that it always returns the current journal mode, even on a failed attempt to change the journal mode. Allow the journal mode to be changed as long as there is not a pending transaction. Ticket #3811. (CVS 6526) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
419e320ae51639794335d19699f8e118 |
User & Date: | drh 2009-04-20 17:43:03.000 |
Context
2009-04-21
| ||
09:02 | Attempt to optimize virtual table queries with 'OR' expressions in the WHERE clause. (CVS 6527) (check-in: f61e4cd936 user: danielk1977 tags: trunk) | |
2009-04-20
| ||
17:43 | Change the journal_mode pragma so that it always returns the current journal mode, even on a failed attempt to change the journal mode. Allow the journal mode to be changed as long as there is not a pending transaction. Ticket #3811. (CVS 6526) (check-in: 419e320ae5 user: drh tags: trunk) | |
13:32 | Add new tests to show that journal_mode=OFF works with locking_mode=EXCLUSIVE as long as the journal_mode is set prior to the first transaction. Ticket #3811. (CVS 6525) (check-in: e62ac26f72 user: drh tags: trunk) | |
Changes
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.529 2009/04/20 17:43:03 drh Exp $ */ #include "sqliteInt.h" /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. */ |
︙ | ︙ | |||
154 155 156 157 158 159 160 | u32 mask; int iDb; sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0); | > | > | 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 | u32 mask; int iDb; sqlite3VdbeJumpHere(v, pParse->cookieGoto-1); for(iDb=0, mask=1; iDb<db->nDb; mask<<=1, iDb++){ if( (mask & pParse->cookieMask)==0 ) continue; sqlite3VdbeUsesBtree(v, iDb); sqlite3VdbeAddOp2(v,OP_Transaction, iDb, (mask & pParse->writeMask)!=0); if( db->init.busy==0 ){ sqlite3VdbeAddOp2(v,OP_VerifyCookie, iDb, pParse->cookieValue[iDb]); } } #ifndef SQLITE_OMIT_VIRTUALTABLE { int i; for(i=0; i<pParse->nVtabLock; i++){ char *vtab = (char *)pParse->apVtabLock[i]->pVtab; sqlite3VdbeAddOp4(v, OP_VBegin, 0, 0, 0, vtab, P4_VTAB); |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 | ** 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. ** | | | 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.582 2009/04/20 17:43:03 drh Exp $ */ #ifndef SQLITE_OMIT_DISKIO #include "sqliteInt.h" /* ** Macros for troubleshooting. Normally turned off */ |
︙ | ︙ | |||
5191 5192 5193 5194 5195 5196 5197 | ** PAGER_JOURNALMODE_QUERY ** PAGER_JOURNALMODE_DELETE ** PAGER_JOURNALMODE_TRUNCATE ** PAGER_JOURNALMODE_PERSIST ** PAGER_JOURNALMODE_OFF ** PAGER_JOURNALMODE_MEMORY ** | | > > > | | < | > > | | > > > > > | 5191 5192 5193 5194 5195 5196 5197 5198 5199 5200 5201 5202 5203 5204 5205 5206 5207 5208 5209 5210 5211 5212 5213 5214 5215 5216 5217 5218 5219 5220 5221 5222 5223 5224 5225 5226 5227 5228 5229 5230 5231 | ** PAGER_JOURNALMODE_QUERY ** PAGER_JOURNALMODE_DELETE ** PAGER_JOURNALMODE_TRUNCATE ** PAGER_JOURNALMODE_PERSIST ** PAGER_JOURNALMODE_OFF ** PAGER_JOURNALMODE_MEMORY ** ** If the parameter is not _QUERY, then the journal_mode is set to the ** value specified if the change is allowed. The change is disallowed ** for the following reasons: ** ** * An in-memory database can only have its journal_mode set to _OFF ** or _MEMORY. ** ** * The journal mode may not be changed while a transaction is active. ** ** The returned indicate the current (possibly updated) journal-mode. */ int sqlite3PagerJournalMode(Pager *pPager, int eMode){ assert( eMode==PAGER_JOURNALMODE_QUERY || eMode==PAGER_JOURNALMODE_DELETE || eMode==PAGER_JOURNALMODE_TRUNCATE || eMode==PAGER_JOURNALMODE_PERSIST || eMode==PAGER_JOURNALMODE_OFF || eMode==PAGER_JOURNALMODE_MEMORY ); assert( PAGER_JOURNALMODE_QUERY<0 ); if( eMode>=0 && (!MEMDB || eMode==PAGER_JOURNALMODE_MEMORY || eMode==PAGER_JOURNALMODE_OFF) && !pPager->dbModified ){ if( isOpen(pPager->jfd) ){ sqlite3OsClose(pPager->jfd); } pPager->journalMode = (u8)eMode; } return (int)pPager->journalMode; } /* ** Get/set the size-limit used for persistent journal files. |
︙ | ︙ |
Changes to src/prepare.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains the implementation of the sqlite3_prepare() ** interface, and routines that contribute to loading the database schema ** from disk. ** ** $Id: prepare.c,v 1.117 2009/04/20 17:43:03 drh Exp $ */ #include "sqliteInt.h" /* ** Fill the InitData structure with an error message that indicates ** that the database is corrupt. */ |
︙ | ︙ | |||
123 124 125 126 127 128 129 130 131 132 133 134 135 136 | ** database file is given by iDb. iDb==0 is used for the main ** database. iDb==1 should never be used. iDb>=2 is used for ** auxiliary databases. Return one of the SQLITE_ error codes to ** indicate success or failure. */ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ int rc; BtCursor *curMain; int size; Table *pTab; Db *pDb; char const *azArg[4]; int meta[10]; InitData initData; | > | 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | ** database file is given by iDb. iDb==0 is used for the main ** database. iDb==1 should never be used. iDb>=2 is used for ** auxiliary databases. Return one of the SQLITE_ error codes to ** indicate success or failure. */ static int sqlite3InitOne(sqlite3 *db, int iDb, char **pzErrMsg){ int rc; int i; BtCursor *curMain; int size; Table *pTab; Db *pDb; char const *azArg[4]; int meta[10]; InitData initData; |
︙ | ︙ | |||
212 213 214 215 216 217 218 | curMain = sqlite3MallocZero(sqlite3BtreeCursorSize()); if( !curMain ){ rc = SQLITE_NOMEM; goto error_out; } sqlite3BtreeEnter(pDb->pBt); rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain); | > | | 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 | curMain = sqlite3MallocZero(sqlite3BtreeCursorSize()); if( !curMain ){ rc = SQLITE_NOMEM; goto error_out; } sqlite3BtreeEnter(pDb->pBt); rc = sqlite3BtreeCursor(pDb->pBt, MASTER_ROOT, 0, 0, curMain); if( rc==SQLITE_EMPTY ) rc = SQLITE_OK; if( rc!=SQLITE_OK ){ sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); goto initone_error_out; } /* Get the database meta information. ** ** Meta values are as follows: |
︙ | ︙ | |||
234 235 236 237 238 239 240 | ** meta[7] ** meta[8] ** meta[9] ** ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to ** the possible values of meta[4]. */ | < < | | | | | | < < < | 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 | ** meta[7] ** meta[8] ** meta[9] ** ** Note: The #defined SQLITE_UTF* symbols in sqliteInt.h correspond to ** the possible values of meta[4]. */ for(i=0; i<ArraySize(meta); i++){ rc = sqlite3BtreeGetMeta(pDb->pBt, i+1, (u32 *)&meta[i]); if( rc ){ sqlite3SetString(pzErrMsg, db, "%s", sqlite3ErrStr(rc)); goto initone_error_out; } } pDb->pSchema->schema_cookie = meta[0]; /* If opening a non-empty database, check the text encoding. For the ** main database, set sqlite3.enc to the encoding of the main database. ** For an attached db, it is an error if the encoding is not the same ** as sqlite3.enc. |
︙ | ︙ |
Changes to test/jrnlmode.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2008 April 17 # # 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 implements regression tests for SQLite library. The focus # of these tests is the journal mode pragma. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2008 April 17 # # 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 implements regression tests for SQLite library. The focus # of these tests is the journal mode pragma. # # $Id: jrnlmode.test,v 1.15 2009/04/20 17:43:03 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable {!pager_pragmas} { finish_test return |
︙ | ︙ | |||
278 279 280 281 282 283 284 285 286 287 288 289 290 291 | PRAGMA auto_vacuum = 1; CREATE TABLE abc(a, b, c); } execsql { PRAGMA page_count } } {3} do_test jrnlmode-4.2 { execsql { PRAGMA journal_mode = off } } {off} do_test jrnlmode-4.3 { execsql { INSERT INTO abc VALUES(1, 2, randomblob(2000)) } } {} | > | 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 | PRAGMA auto_vacuum = 1; CREATE TABLE abc(a, b, c); } execsql { PRAGMA page_count } } {3} do_test jrnlmode-4.2 { breakpoint execsql { PRAGMA journal_mode = off } } {off} do_test jrnlmode-4.3 { execsql { INSERT INTO abc VALUES(1, 2, randomblob(2000)) } } {} |
︙ | ︙ | |||
460 461 462 463 464 465 466 | execsql { PRAGMA journal_mode = truncate; CREATE TABLE t4(a, b); BEGIN; INSERT INTO t4 VALUES(1, 2); PRAGMA journal_mode = memory; } | | | > | > > > > > > > | 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 | execsql { PRAGMA journal_mode = truncate; CREATE TABLE t4(a, b); BEGIN; INSERT INTO t4 VALUES(1, 2); PRAGMA journal_mode = memory; } } {truncate truncate} do_test jrnlmode-6.2 { file exists test.db-journal } {1} do_test jrnlmode-6.3 { execsql { COMMIT; SELECT * FROM t4; } } {1 2} do_test jrnlmode-6.4 { file exists test.db-journal } {1} do_test jrnlmode-6.5 { execsql { PRAGMA journal_mode = MEMORY; BEGIN; INSERT INTO t4 VALUES(3, 4); } file exists test.db-journal } {1} do_test jrnlmode-6.7 { execsql { COMMIT; SELECT * FROM t4; } } {1 2 3 4} do_test jrnlmode-6.8 { file exists test.db-journal } {1} do_test jrnlmode-6.9 { execsql { PRAGMA journal_mode = DELETE; BEGIN IMMEDIATE; COMMIT; } file exists test.db-journal } {0} } } finish_test |
Changes to test/jrnlmode3.test.
1 2 3 4 5 6 7 8 9 10 11 | # 2009 April 20 # # 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. # #*********************************************************************** # | > > > > | < | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | # 2009 April 20 # # 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. # #*********************************************************************** # # Test cases inspired by ticket #3811. Tests to make sure that # the journal_mode can only be changed at appropriate times and that # all reported changes are effective. # # $Id: jrnlmode3.test,v 1.5 2009/04/20 17:43:03 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl ifcapable {!pager_pragmas} { finish_test return } # # Verify that journal_mode=OFF works as long as it occurs before the first # transaction, even if locking_mode=EXCLUSIVE is enabled. The behavior if # journal_mode is changed after the first transaction is undefined and hence # untested. # do_test jrnlmode3-1.1 { |
︙ | ︙ | |||
62 63 64 65 66 67 68 | BEGIN; INSERT INTO t1 VALUES(2); ROLLBACK; SELECT * FROM t1; } } {1 2} | > > > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 105 106 107 108 109 110 111 112 113 114 115 116 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 146 147 148 149 150 | 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 foreach fromjmode $all_journal_modes { foreach tojmode $all_journal_modes { # Skip the no-change cases if {$fromjmode==$tojmode} continue incr cnt # Start with a fresh database connection an empty database file. # db close file delete -force test.db test.db-journal sqlite3 db test.db # Initialize the journal mode. # do_test jrnlmode3-3.$cnt.1-($fromjmode-to-$tojmode) { db eval "PRAGMA journal_mode = $fromjmode;" } $fromjmode # Verify that the initial journal mode takes. # do_test jrnlmode3-3.$cnt.2 { db eval {PRAGMA main.journal_mode} } $fromjmode # Start a transaction and try to change the journal mode within # the transaction. This should fail. # do_test jrnlmode3-3.$cnt.3 { db eval { 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 # Do a the transaction. Verify that the rollback occurred # if journal_mode!=OFF. # do_test jrnlmode3-3.$cnt.6 { db eval { DROP TABLE IF EXISTS t1; CREATE TABLE t1(x); BEGIN; INSERT INTO t1 VALUES(1); } db eval ROLLBACK db eval { SELECT * FROM t1; } } [expr {$tojmode=="off"?"1":""}] } } finish_test |