Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Merge latest begin-concurrent changes with this branch. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | begin-concurrent-wal2 |
Files: | files | file ages | folders |
SHA3-256: |
1625887c0240eb1cb37e41d79e789c4f |
User & Date: | dan 2018-12-29 20:47:45.530 |
Context
2019-01-02
| ||
16:30 | Merge latest wal2 changes into this branch. (check-in: c31eeb3c87 user: dan tags: begin-concurrent-wal2) | |
2018-12-29
| ||
20:47 | Merge latest begin-concurrent changes with this branch. (check-in: 1625887c02 user: dan tags: begin-concurrent-wal2) | |
20:42 | Fix a problem causing a corrupt pager-cache if an OOM or IO error was encountered while committing a concurrent transacation. (check-in: 48ca30f9d7 user: dan tags: begin-concurrent) | |
16:34 | Increase coverage provided by permutation "coverage-wal" on this branch. (check-in: f664f940a7 user: dan tags: begin-concurrent-wal2) | |
Changes
Changes to ext/session/sqlite3session.h.
︙ | ︙ | |||
314 315 316 317 318 319 320 321 322 323 324 325 326 327 | ** the same session object is disabled, no INSERT record will appear in the ** changeset, even though the delete took place while the session was disabled. ** Or, if one field of a row is updated while a session is disabled, and ** another field of the same row is updated while the session is enabled, the ** resulting changeset will contain an UPDATE change that updates both fields. */ int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); /* ** CAPI3REF: Generate A Full Changeset From A Session Object | > > > > > > > > > > > > > | 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 | ** the same session object is disabled, no INSERT record will appear in the ** changeset, even though the delete took place while the session was disabled. ** Or, if one field of a row is updated while a session is disabled, and ** another field of the same row is updated while the session is enabled, the ** resulting changeset will contain an UPDATE change that updates both fields. */ int sqlite3session_changeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); /* ** CAPI3REF: Generate A Full Changeset From A Session Object ** ** This function is similar to sqlite3session_changeset(), except that for ** each row affected by an UPDATE statement, all old.* values are recorded ** as part of the changeset, not just those modified. */ int sqlite3session_fullchangeset( sqlite3_session *pSession, /* Session object */ int *pnChangeset, /* OUT: Size of buffer at *ppChangeset */ void **ppChangeset /* OUT: Buffer containing changeset */ ); /* ** CAPI3REF: Generate A Full Changeset From A Session Object |
︙ | ︙ |
Changes to src/pager.c.
︙ | ︙ | |||
3199 3200 3201 3202 3203 3204 3205 | ** been written (but not committed) to the log file, do one of the ** following: ** ** + Discard the cached page (if refcount==0), or ** + Reload page content from the database (if refcount>0). */ pPager->dbSize = pPager->dbOrigSize; | | > > > > > > | 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 | ** been written (but not committed) to the log file, do one of the ** following: ** ** + Discard the cached page (if refcount==0), or ** + Reload page content from the database (if refcount>0). */ pPager->dbSize = pPager->dbOrigSize; rc = sqlite3WalUndo(pPager->pWal, pagerUndoCallback, (void *)pPager, #ifdef SQLITE_OMIT_CONCURRENT 0 #else pPager->pAllRead!=0 #endif ); pList = sqlite3PcacheDirtyList(pPager->pPCache); #ifndef SQLITE_OMIT_CONCURRENT /* If this is an CONCURRENT transaction, then page 1 must be reread from ** the db file, even if it is not dirty. This is because the b-tree layer ** may have already zeroed the nFree and iTrunk header fields. */ if( rc==SQLITE_OK && (pList==0 || pList->pgno!=1) && pPager->pAllRead ){ |
︙ | ︙ |
Changes to src/wal.c.
︙ | ︙ | |||
4028 4029 4030 4031 4032 4033 4034 | ** to the WAL since the start of the transaction. If the callback returns ** other than SQLITE_OK, it is not invoked again and the error code is ** returned to the caller. ** ** Otherwise, if the callback function does not return an error, this ** function returns SQLITE_OK. */ | | > > > > > | 4028 4029 4030 4031 4032 4033 4034 4035 4036 4037 4038 4039 4040 4041 4042 4043 4044 4045 4046 4047 | ** to the WAL since the start of the transaction. If the callback returns ** other than SQLITE_OK, it is not invoked again and the error code is ** returned to the caller. ** ** Otherwise, if the callback function does not return an error, this ** function returns SQLITE_OK. */ int sqlite3WalUndo( Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx, int bConcurrent /* True if this is a CONCURRENT transaction */ ){ int rc = SQLITE_OK; if( pWal->writeLock ){ int iWal = walidxGetFile(&pWal->hdr); Pgno iMax = walidxGetMxFrame(&pWal->hdr, iWal); Pgno iNew; Pgno iFrame; |
︙ | ︙ | |||
4059 4060 4061 4062 4063 4064 4065 4066 | ** The code below is still valid. All frames between (iNew+1) and iMax ** must have been written by this transaction before the error occurred. ** The exception is in wal2 mode - if the current wal file at the time ** of the last COMMIT is not wal file iWal, then the error must have ** occurred in WalLockForCommit(), before any pages were written ** to the database file. In this case return early. */ #ifndef SQLITE_OMIT_CONCURRENT if( walidxGetFile(&pWal->hdr)!=iWal ){ | > > > | | 4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 4078 4079 4080 4081 4082 | ** The code below is still valid. All frames between (iNew+1) and iMax ** must have been written by this transaction before the error occurred. ** The exception is in wal2 mode - if the current wal file at the time ** of the last COMMIT is not wal file iWal, then the error must have ** occurred in WalLockForCommit(), before any pages were written ** to the database file. In this case return early. */ #ifndef SQLITE_OMIT_CONCURRENT if( bConcurrent ){ pWal->hdr.aCksum[0]++; } if( walidxGetFile(&pWal->hdr)!=iWal ){ assert( bConcurrent && isWalMode2(pWal) ); return SQLITE_OK; } #endif assert( walidxGetFile(&pWal->hdr)==iWal ); for(iFrame=iNew+1; ALWAYS(rc==SQLITE_OK) && iFrame<=iMax; iFrame++){ /* This call cannot fail. Unless the page for which the page number |
︙ | ︙ |
Changes to src/wal.h.
︙ | ︙ | |||
30 31 32 33 34 35 36 | # define sqlite3WalLimit(x,y) # define sqlite3WalClose(v,w,x,y,z) 0 # define sqlite3WalBeginReadTransaction(y,z) 0 # define sqlite3WalEndReadTransaction(z) # define sqlite3WalDbsize(y) 0 # define sqlite3WalBeginWriteTransaction(y) 0 # define sqlite3WalEndWriteTransaction(x) 0 | | | 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | # define sqlite3WalLimit(x,y) # define sqlite3WalClose(v,w,x,y,z) 0 # define sqlite3WalBeginReadTransaction(y,z) 0 # define sqlite3WalEndReadTransaction(z) # define sqlite3WalDbsize(y) 0 # define sqlite3WalBeginWriteTransaction(y) 0 # define sqlite3WalEndWriteTransaction(x) 0 # define sqlite3WalUndo(w,x,y,z) 0 # define sqlite3WalSavepoint(y,z) # define sqlite3WalSavepointUndo(y,z) 0 # define sqlite3WalFrames(u,v,w,x,y,z) 0 # define sqlite3WalCheckpoint(q,r,s,t,u,v,w,x,y,z) 0 # define sqlite3WalCallback(z) 0 # define sqlite3WalExclusiveMode(y,z) 0 # define sqlite3WalHeapMemory(z) 0 |
︙ | ︙ | |||
80 81 82 83 84 85 86 | Pgno sqlite3WalDbsize(Wal *pWal); /* Obtain or release the WRITER lock. */ int sqlite3WalBeginWriteTransaction(Wal *pWal); int sqlite3WalEndWriteTransaction(Wal *pWal); /* Undo any frames written (but not committed) to the log */ | | | 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 | Pgno sqlite3WalDbsize(Wal *pWal); /* Obtain or release the WRITER lock. */ int sqlite3WalBeginWriteTransaction(Wal *pWal); int sqlite3WalEndWriteTransaction(Wal *pWal); /* Undo any frames written (but not committed) to the log */ int sqlite3WalUndo(Wal *pWal, int (*xUndo)(void *, Pgno), void *pUndoCtx, int); /* Return an integer that records the current (uncommitted) write ** position in the WAL */ void sqlite3WalSavepoint(Wal *pWal, u32 *aWalData); /* Move the write position of the WAL back to iFrame. Called in ** response to a ROLLBACK TO command. */ |
︙ | ︙ |
Changes to test/concfault2.test.
︙ | ︙ | |||
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 | } {1 32768} faultsim_save_and_close do_faultsim_test 1 -prep { faultsim_restore_and_reopen execsql { BEGIN CONCURRENT; INSERT INTO t2 VALUES(1, 2); } sqlite3 db2 test.db execsql { PRAGMA journal_size_limit = 10000; INSERT INTO t1 VALUES(randomblob(1000), randomblob(1000)); } db2 db2 close } -body { execsql { COMMIT } } -test { faultsim_test_result {0 {}} catchsql { ROLLBACK } faultsim_integrity_check } finish_test | > > > > | 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 | } {1 32768} faultsim_save_and_close do_faultsim_test 1 -prep { faultsim_restore_and_reopen execsql { SELECT * FROM t1; BEGIN CONCURRENT; INSERT INTO t2 VALUES(1, 2); } sqlite3 db2 test.db execsql { PRAGMA journal_size_limit = 10000; INSERT INTO t1 VALUES(randomblob(1000), randomblob(1000)); } db2 db2 close } -body { execsql { COMMIT } } -test { faultsim_test_result {0 {}} catchsql { ROLLBACK } set res [catchsql { SELECT count(*) FROM t1 }] if {$res!="0 9"} { error "expected {0 9} got {$res}" } faultsim_integrity_check } finish_test |