SQLite

Check-in [e6108047]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:In wal mode, if a "BEGIN EXCLUSIVE" command (or any other command that upgrades from no transaction directly to a write transaction) hits an SQLITE_BUSY_SNAPSHOT error, change the error code to SQLITE_BUSY to indicate to the caller that the condition may be transient.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: e6108047cb136119d8ed19af010a669ed9750b4e7f991ccabc9e3d15774eda31
User & Date: dan 2018-07-05 17:16:55
Context
2018-07-05
17:35
Fix the .dump command in the command-line shell so that it does not show extraneous SELECT statements when ".echo on" is enabled. (check-in: 11763cac user: drh tags: trunk)
17:16
In wal mode, if a "BEGIN EXCLUSIVE" command (or any other command that upgrades from no transaction directly to a write transaction) hits an SQLITE_BUSY_SNAPSHOT error, change the error code to SQLITE_BUSY to indicate to the caller that the condition may be transient. (check-in: e6108047 user: dan tags: trunk)
17:03
Fix a typo inside an assert() statement introduced by the previous commit. (Closed-Leaf check-in: e3357728 user: dan tags: exp-busy-snapshot-fix)
2018-07-03
20:17
Test that a race condition can cause a "BEGIN EXCLUSIVE" to return SQLITE_BUSY_SNAPSHOT in wal mode. (check-in: 5a12db75 user: dan tags: trunk)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

3371
3372
3373
3374
3375
3376
3377





3378
3379
3380
3381
3382
3383
3384
    if( rc==SQLITE_OK && wrflag ){
      if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
        rc = SQLITE_READONLY;
      }else{
        rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
        if( rc==SQLITE_OK ){
          rc = newDatabase(pBt);





        }
      }
    }
  
    if( rc!=SQLITE_OK ){
      unlockBtreeIfUnused(pBt);
    }







>
>
>
>
>







3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
3383
3384
3385
3386
3387
3388
3389
    if( rc==SQLITE_OK && wrflag ){
      if( (pBt->btsFlags & BTS_READ_ONLY)!=0 ){
        rc = SQLITE_READONLY;
      }else{
        rc = sqlite3PagerBegin(pBt->pPager,wrflag>1,sqlite3TempInMemory(p->db));
        if( rc==SQLITE_OK ){
          rc = newDatabase(pBt);
        }else if( rc==SQLITE_BUSY_SNAPSHOT && pBt->inTransaction==TRANS_NONE ){
          /* if there was no transaction opened when this function was
          ** called and SQLITE_BUSY_SNAPSHOT is returned, change the error
          ** code to SQLITE_BUSY. */
          rc = SQLITE_BUSY;
        }
      }
    }
  
    if( rc!=SQLITE_OK ){
      unlockBtreeIfUnused(pBt);
    }
3421
3422
3423
3424
3425
3426
3427
3428
3429
3430
3431
3432
3433
3434
3435
        rc = sqlite3PagerWrite(pPage1->pDbPage);
        if( rc==SQLITE_OK ){
          put4byte(&pPage1->aData[28], pBt->nPage);
        }
      }
    }
  }


trans_begun:
  if( rc==SQLITE_OK ){
    if( pSchemaVersion ){
      *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]);
    }
    if( wrflag ){







<







3426
3427
3428
3429
3430
3431
3432

3433
3434
3435
3436
3437
3438
3439
        rc = sqlite3PagerWrite(pPage1->pDbPage);
        if( rc==SQLITE_OK ){
          put4byte(&pPage1->aData[28], pBt->nPage);
        }
      }
    }
  }


trans_begun:
  if( rc==SQLITE_OK ){
    if( pSchemaVersion ){
      *pSchemaVersion = get4byte(&pBt->pPage1->aData[40]);
    }
    if( wrflag ){

Changes to test/walprotocol2.test.

68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  }
}
do_catchsql_test 2.2 {
  BEGIN EXCLUSIVE;
} {1 {database is locked}}
do_test 2.3 {
  sqlite3_extended_errcode db
} {SQLITE_BUSY_SNAPSHOT}

#---------------------------------------------------------------
# Same again, but with a busy-handler. This time, following the
# SQLITE_BUSY_SNAPSHOT error the busy-handler is invoked and then the 
# whole thing retried from the beginning. This time it succeeds.
#
proc lock_callback {method filename handle lock} {







|







68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  }
}
do_catchsql_test 2.2 {
  BEGIN EXCLUSIVE;
} {1 {database is locked}}
do_test 2.3 {
  sqlite3_extended_errcode db
} {SQLITE_BUSY}

#---------------------------------------------------------------
# Same again, but with a busy-handler. This time, following the
# SQLITE_BUSY_SNAPSHOT error the busy-handler is invoked and then the 
# whole thing retried from the beginning. This time it succeeds.
#
proc lock_callback {method filename handle lock} {