/ Check-in [50c8952c]
Login

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

Overview
Comment:Fix a spurious SQLITE_CORRUPT error that could occur within a COMMIT of a concurrent transaction.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | begin-concurrent-pnu
Files: files | file ages | folders
SHA3-256: 50c8952c92b9f0c61935fb0df04ed1426d9e266a812071b7bf5b0215c5552757
User & Date: dan 2018-01-02 19:57:26
Context
2018-12-03
19:29
Cherrypick a couple of fixes from begin-concurrent-pnu into this branch. The differences between the two branches are now that this one does not have "PRAGMA noop_update" or the mutex-free PRNG. check-in: a56506b9 user: dan tags: begin-concurrent
2018-01-04
18:36
Fix problem causing free-list corruption when merging free-lists for two concurrent transactions that have both used page X as an in-memory free-list trunk page, where X lies past the end of the initial database images. check-in: dc0fc2aa user: dan tags: begin-concurrent-pnu
2018-01-02
19:57
Fix a spurious SQLITE_CORRUPT error that could occur within a COMMIT of a concurrent transaction. check-in: 50c8952c user: dan tags: begin-concurrent-pnu
2017-12-12
18:17
Merge latest begin-concurrent changes into this branch. check-in: 3fde0b4d user: dan tags: begin-concurrent-pnu
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  4175   4175           ** not have shrunk since the transaction was opened. Therefore nHPage
  4176   4176           ** should be set to (pMap->iFirst-1) or greater. */
  4177   4177           rc = SQLITE_CORRUPT_BKPT;
  4178   4178         }else{
  4179   4179           /* The current transaction allocated pages pMap->iFirst through
  4180   4180           ** nPage (inclusive) at the end of the database file. Meanwhile,
  4181   4181           ** other transactions have allocated (iFirst..nHPage). So move
  4182         -        ** pages (iFirst..MIN(nPage,nHPage)) to (MAX(nPage,nHPage)+1).  */
         4182  +        ** pages (iFirst..MIN(nPage,nHPage)) to (MAX(nPage,nHPage)+1). */
  4183   4183           Pgno iLast = MIN(nPage, nHPage);    /* Last page to move */
  4184   4184           Pgno nCurrent;                      /* Current size of db */
         4185  +
  4185   4186           nCurrent = MAX(nPage, nHPage);
         4187  +        pBt->nPage = nCurrent;
  4186   4188           rc = btreeRelocateRange(pBt, pMap->iFirst, iLast, &nCurrent);
  4187   4189   
  4188   4190           /* There are now no collisions with the snapshot at the head of the
  4189   4191           ** database file. So at this point it would be possible to write
  4190   4192           ** the transaction out to disk. Before doing so though, attempt to
  4191   4193           ** relocate some of the new pages to free locations within the body
  4192   4194           ** of the database file (i.e. free-list entries). */
................................................................................
  6123   6125     assert( eMode==BTALLOC_ANY || (nearby>0 && REQUIRE_PTRMAP ) );
  6124   6126     pPage1 = pBt->pPage1;
  6125   6127     mxPage = btreePagecount(pBt);
  6126   6128     /* EVIDENCE-OF: R-05119-02637 The 4-byte big-endian integer at offset 36
  6127   6129     ** stores stores the total number of pages on the freelist. */
  6128   6130     n = get4byte(&pPage1->aData[36]);
  6129   6131     testcase( n==mxPage-1 );
  6130         -  if( ISCONCURRENT==0 && n>=mxPage ){
         6132  +  if( n>=mxPage ){
  6131   6133       return SQLITE_CORRUPT_BKPT;
  6132   6134     }
  6133   6135   
  6134   6136     /* Ensure page 1 is writable. This function will either change the number
  6135   6137     ** of pages in the free-list or the size of the database file. Since both
  6136   6138     ** of these operations involve modifying page 1 header fields, page 1
  6137   6139     ** will definitely be written by this transaction. If this is an CONCURRENT

Added test/concurrent6.test.

            1  +# 2017 May 26
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +#
           13  +
           14  +set testdir [file dirname $argv0]
           15  +source $testdir/tester.tcl
           16  +source $testdir/lock_common.tcl
           17  +source $testdir/wal_common.tcl
           18  +set ::testprefix concurrent6
           19  +
           20  +ifcapable !concurrent {
           21  +  finish_test
           22  +  return
           23  +}
           24  +
           25  +sqlite3 db2 test.db
           26  +
           27  +do_execsql_test 1.0 {
           28  +  PRAGMA page_size = 1024;
           29  +  PRAGMA journal_mode = wal;
           30  +  CREATE TABLE t1(x);
           31  +  CREATE TABLE t2(x);
           32  +  CREATE TABLE t3(x);
           33  +  CREATE TABLE t4(x);
           34  +
           35  +  INSERT INTO t1 VALUES(zeroblob(1500));
           36  +} {wal}
           37  +
           38  +do_execsql_test -db db2 1.1 {
           39  +  BEGIN CONCURRENT;
           40  +    INSERT INTO t3 VALUES(zeroblob(4000));
           41  +    DELETE FROM t1;
           42  +}
           43  +
           44  +do_execsql_test 1.2 {
           45  +  WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100) 
           46  +  INSERT INTO t2 SELECT zeroblob(1000) FROM s;
           47  +
           48  +  WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100) 
           49  +  INSERT INTO t4  SELECT zeroblob(1000) FROM s;
           50  +
           51  +  DELETE FROM t4;
           52  +}
           53  +
           54  +do_execsql_test -db db2 1.3 {
           55  +  COMMIT;
           56  +}
           57  +
           58  +
           59  +finish_test
           60  +