/ Check-in [174477bc]
Login

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

Overview
Comment:Experimental fix for [f777251dc7]. This may be changed yet.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:174477bca05d019e663fd2b7cd031189ab2e010a
User & Date: dan 2009-10-16 14:55:03
References
2009-10-16
20:55 Fixed ticket [f777251d]: Assertion fault following ROLLBACK with running queries plus 3 other changes artifact: d0214927 user: drh
Context
2009-10-16
15:05
Comment cleanup in btree.c. check-in: 32966ba4 user: drh tags: trunk
14:55
Experimental fix for [f777251dc7]. This may be changed yet. check-in: 174477bc user: dan tags: trunk
13:23
Fix comment typos in btreeInt.h. check-in: 550566a7 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979




2980
2981
2982
2983
2984
2985
2986

/*
** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback()
** at the conclusion of a transaction.
*/
static void btreeEndTransaction(Btree *p){
  BtShared *pBt = p->pBt;
  BtCursor *pCsr;
  assert( sqlite3BtreeHoldsMutex(p) );

  /* Search for a cursor held open by this b-tree connection. If one exists,
  ** then the transaction will be downgraded to a read-only transaction
  ** instead of actually concluded. A subsequent call to CommitPhaseTwo() 
  ** or Rollback() will finish the transaction and unlock the database.  */
  for(pCsr=pBt->pCursor; pCsr && pCsr->pBtree!=p; pCsr=pCsr->pNext);
  assert( pCsr==0 || p->inTrans>TRANS_NONE );

  btreeClearHasContent(pBt);
  if( pCsr ){




    downgradeAllSharedCacheTableLocks(p);
    p->inTrans = TRANS_READ;
  }else{
    /* If the handle had any kind of transaction open, decrement the 
    ** transaction count of the shared btree. If the transaction count 
    ** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused()
    ** call below will unlock the pager.  */







<


<
<
<
<
<
<
<

<
>
>
>
>







2961
2962
2963
2964
2965
2966
2967

2968
2969







2970

2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981

/*
** This function is called from both BtreeCommitPhaseTwo() and BtreeRollback()
** at the conclusion of a transaction.
*/
static void btreeEndTransaction(Btree *p){
  BtShared *pBt = p->pBt;

  assert( sqlite3BtreeHoldsMutex(p) );








  btreeClearHasContent(pBt);

  if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){
    /* If there are other active statements that belong to this database
    ** handle, downgrade to a read-only transaction. The other statements
    ** may still be reading from the database.  */
    downgradeAllSharedCacheTableLocks(p);
    p->inTrans = TRANS_READ;
  }else{
    /* If the handle had any kind of transaction open, decrement the 
    ** transaction count of the shared btree. If the transaction count 
    ** reaches 0, set the shared state to TRANS_NONE. The unlockBtreeIfUnused()
    ** call below will unlock the pager.  */

Changes to src/vacuum.c.

125
126
127
128
129
130
131






132
133
134
135
136
137
138
  */
  zSql = "ATTACH '' AS vacuum_db;";
  rc = execSql(db, zSql);
  if( rc!=SQLITE_OK ) goto end_of_vacuum;
  pDb = &db->aDb[db->nDb-1];
  assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
  pTemp = db->aDb[db->nDb-1].pBt;







  nRes = sqlite3BtreeGetReserve(pMain);

  /* A VACUUM cannot change the pagesize of an encrypted database. */
#ifdef SQLITE_HAS_CODEC
  if( db->nextPagesize ){
    extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);







>
>
>
>
>
>







125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
  */
  zSql = "ATTACH '' AS vacuum_db;";
  rc = execSql(db, zSql);
  if( rc!=SQLITE_OK ) goto end_of_vacuum;
  pDb = &db->aDb[db->nDb-1];
  assert( strcmp(db->aDb[db->nDb-1].zName,"vacuum_db")==0 );
  pTemp = db->aDb[db->nDb-1].pBt;

  /* The call to execSql() to attach the temp database has left the file
  ** locked (as there was more than one active statement when the transaction
  ** to read the schema was concluded. Unlock it here so that this doesn't
  ** cause problems for the call to BtreeSetPageSize() below.  */
  sqlite3BtreeCommit(pTemp);

  nRes = sqlite3BtreeGetReserve(pMain);

  /* A VACUUM cannot change the pagesize of an encrypted database. */
#ifdef SQLITE_HAS_CODEC
  if( db->nextPagesize ){
    extern void sqlite3CodecGetKey(sqlite3*, int, void**, int*);

Changes to src/vdbe.c.

2851
2852
2853
2854
2855
2856
2857

2858
2859
2860
2861
2862
2863
2864
....
2967
2968
2969
2970
2971
2972
2973





2974
2975
2976
2977
2978
2979
2980
    /* Record changes in the file format */
    pDb->pSchema->file_format = (u8)pIn3->u.i;
  }
  if( pOp->p1==1 ){
    /* Invalidate all prepared statements whenever the TEMP database
    ** schema is changed.  Ticket #1644 */
    sqlite3ExpirePreparedStatements(db);

  }
  break;
}

/* Opcode: VerifyCookie P1 P2 *
**
** Check the value of global database parameter number 0 (the
................................................................................
  KeyInfo *pKeyInfo;
  int p2;
  int iDb;
  int wrFlag;
  Btree *pX;
  VdbeCursor *pCur;
  Db *pDb;






  nField = 0;
  pKeyInfo = 0;
  p2 = pOp->p2;
  iDb = pOp->p3;
  assert( iDb>=0 && iDb<db->nDb );
  assert( (p->btreeMask & (1<<iDb))!=0 );







>







 







>
>
>
>
>







2851
2852
2853
2854
2855
2856
2857
2858
2859
2860
2861
2862
2863
2864
2865
....
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
    /* Record changes in the file format */
    pDb->pSchema->file_format = (u8)pIn3->u.i;
  }
  if( pOp->p1==1 ){
    /* Invalidate all prepared statements whenever the TEMP database
    ** schema is changed.  Ticket #1644 */
    sqlite3ExpirePreparedStatements(db);
    p->expired = 0;
  }
  break;
}

/* Opcode: VerifyCookie P1 P2 *
**
** Check the value of global database parameter number 0 (the
................................................................................
  KeyInfo *pKeyInfo;
  int p2;
  int iDb;
  int wrFlag;
  Btree *pX;
  VdbeCursor *pCur;
  Db *pDb;

  if( p->expired ){
    rc = SQLITE_ABORT;
    break;
  }

  nField = 0;
  pKeyInfo = 0;
  p2 = pOp->p2;
  iDb = pOp->p3;
  assert( iDb>=0 && iDb<db->nDb );
  assert( (p->btreeMask & (1<<iDb))!=0 );

Added test/tkt-f777251dc7a.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
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
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
# 2009 October 16
#
# 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.
#
# This file implements tests to verify that ticket [f777251dc7a] has been
# fixed.  
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

do_test tkt-f7772-1.1 {
  execsql {
     CREATE TEMP TABLE t1(x UNIQUE);
     INSERT INTO t1 VALUES(1);
     CREATE TABLE t2(x, y);
     INSERT INTO t2 VALUES(1, 2);
     CREATE TEMP TABLE t3(w, z);
  }
} {}

proc force_rollback {} {
  catch {db eval {INSERT OR ROLLBACK INTO t1 VALUES(1)}}
}
db function force_rollback force_rollback

do_test tkt-f7772-1.2 {
  catchsql {
    BEGIN IMMEDIATE;
    SELECT x, force_rollback(), EXISTS(SELECT 1 FROM t3 WHERE w=x) FROM t2;
  }
} {1 {callback requested query abort}}
do_test tkt-f7772-1.3 {
  sqlite3_get_autocommit db
} {1}

do_test tkt-f7772-2.1 {
  execsql {
     DROP TABLE IF EXISTS t1;
     DROP TABLE IF EXISTS t2;
     DROP TABLE IF EXISTS t3;

     CREATE TEMP TABLE t1(x UNIQUE);
     INSERT INTO t1 VALUES(1);
     CREATE TABLE t2(x, y);
     INSERT INTO t2 VALUES(1, 2);
  }
} {}
do_test tkt-f7772-2.2 {
  execsql {
    BEGIN IMMEDIATE;
    CREATE TEMP TABLE t3(w, z);
  }
  catchsql {
    SELECT x, force_rollback(), EXISTS(SELECT 1 FROM t3 WHERE w=x) FROM t2
  }
} {1 {callback requested query abort}}
do_test tkt-f7772-2.3 {
  sqlite3_get_autocommit db
} {1}

do_test tkt-f7772-3.1 {
  execsql {
    DROP TABLE IF EXISTS t1;
    DROP TABLE IF EXISTS t2;
    DROP TABLE IF EXISTS t3;

    CREATE TEMP TABLE t1(x);
    CREATE TABLE t2(x);
    CREATE TABLE t3(x);
  
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t2 VALUES(1);
    INSERT INTO t2 VALUES(2);
  }
} {}

proc ins {} { db eval {INSERT INTO t3 VALUES('hello')} }
db function ins ins

do_test tkt-f7772-3.2 {
  execsql {
    SELECT ins() AS x FROM t2 UNION ALL SELECT ins() AS x FROM t1
  }
} {{} {} {} {}}
do_test tkt-f7772-3.3 {
  execsql { SELECT * FROM t3 }
} {hello hello hello hello}

finish_test