SQLite

Check-in [a4a3bbe646]
Login

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

Overview
Comment:Fix a problem with deferred page allocation in transactions that revert page allocations by savepoint rollbacks.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | begin-concurrent
Files: files | file ages | folders
SHA3-256: a4a3bbe64690856403642352f36e664a5a7fba686463a63446c6ada99df4e89f
User & Date: dan 2017-05-26 16:15:05.191
Context
2017-05-26
16:51
Add extra test cases for deferred page allocation. (check-in: 9df0195780 user: dan tags: begin-concurrent)
16:15
Fix a problem with deferred page allocation in transactions that revert page allocations by savepoint rollbacks. (check-in: a4a3bbe646 user: dan tags: begin-concurrent)
2017-05-25
21:02
Fix a problem with the deferred page allocation on this branch that could occur when the database file is just slightly smaller than the PENDING_BYTE page offset. (check-in: 47a7dd9235 user: dan tags: begin-concurrent)
Changes
Unified Diff Show Whitespace Changes Patch
Changes to src/btree.c.
518
519
520
521
522
523
524

525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
          pMap->nRollbackAlloc = nNew;
        }
      }

      pMap->aRollback[pMap->nRollback].pgno = pgno;
      pMap->aRollback[pMap->nRollback].parent = pMap->aPtr[iEntry].parent;
      pMap->aRollback[pMap->nRollback].eType = pMap->aPtr[iEntry].eType;

    }

    /* Update the aPtr[] array */
    pMap->aPtr[iEntry].parent = parent;
    pMap->aPtr[iEntry].eType = eType;
  }

  return SQLITE_OK;
}

/* !defined(SQLITE_OMIT_CONCURRENT)
**
** Open savepoint iSavepoint, if it is not already open.
*/
static int btreePtrmapBegin(BtShared *pBt, int nSvpt){
  BtreePtrmap *pMap = pBt->pMap;
  if( pMap && nSvpt<pMap->nSvpt ){
    int i;
    if( nSvpt>=pMap->nSvptAlloc ){
      int nNew = pMap->nSvptAlloc ? pMap->nSvptAlloc*2 : 16;
      int *aNew = sqlite3_realloc(pMap->aSvpt, sizeof(int) * nNew);
      if( aNew==0 ){
        return SQLITE_NOMEM;
      }else{







>
















|







518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
          pMap->nRollbackAlloc = nNew;
        }
      }

      pMap->aRollback[pMap->nRollback].pgno = pgno;
      pMap->aRollback[pMap->nRollback].parent = pMap->aPtr[iEntry].parent;
      pMap->aRollback[pMap->nRollback].eType = pMap->aPtr[iEntry].eType;
      pMap->nRollback++;
    }

    /* Update the aPtr[] array */
    pMap->aPtr[iEntry].parent = parent;
    pMap->aPtr[iEntry].eType = eType;
  }

  return SQLITE_OK;
}

/* !defined(SQLITE_OMIT_CONCURRENT)
**
** Open savepoint iSavepoint, if it is not already open.
*/
static int btreePtrmapBegin(BtShared *pBt, int nSvpt){
  BtreePtrmap *pMap = pBt->pMap;
  if( pMap && nSvpt>pMap->nSvpt ){
    int i;
    if( nSvpt>=pMap->nSvptAlloc ){
      int nNew = pMap->nSvptAlloc ? pMap->nSvptAlloc*2 : 16;
      int *aNew = sqlite3_realloc(pMap->aSvpt, sizeof(int) * nNew);
      if( aNew==0 ){
        return SQLITE_NOMEM;
      }else{
Added test/concurrent4.test.
































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 2017 May 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.
#
#***********************************************************************
#
# Miscellaneous tests for transactions started with BEGIN CONCURRENT. 
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
source $testdir/lock_common.tcl
source $testdir/wal_common.tcl
set ::testprefix concurrent4

ifcapable !concurrent {
  finish_test
  return
}

do_execsql_test 1.0 {
  PRAGMA journal_mode = wal;
  CREATE TABLE t1(x PRIMARY KEY, y UNIQUE);
  WITH s(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<100)
  INSERT INTO t1 SELECT randomblob(400), randomblob(400) FROM s;
  DELETE FROM t1 WHERE rowid<2;
} {wal}

do_execsql_test 1.1 {
  BEGIN CONCURRENT;
    INSERT INTO t1(rowid, x, y) VALUES(1000, randomblob(3000), randomblob(3000));
    SAVEPOINT abc;
    DELETE FROM t1 WHERE rowid = 1000;
}

do_execsql_test 1.2 { ROLLBACK TO abc }
do_execsql_test 1.3 { COMMIT }
do_execsql_test 1.4 { PRAGMA integrity_check } {ok}



finish_test