/ Check-in [e5d42c69]
Login

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

Overview
Comment:Fix savepoint related bugs. A rollback caused by an IO error or "OR ROLLBACK" clause while one or more savepoints were open was leaving the sqlite3 structure in an invalid state. (CVS 6128)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e5d42c69a3b325ca12f53184e33964230acbdd1f
User & Date: danielk1977 2009-01-07 08:12:16
Context
2009-01-07
10:35
Fix a problem with reverting a 'DROP TABLE' command executed inside of a savepoint on an auto-vacuum database. (CVS 6129) check-in: 3a4bb832 user: danielk1977 tags: trunk
08:12
Fix savepoint related bugs. A rollback caused by an IO error or "OR ROLLBACK" clause while one or more savepoints were open was leaving the sqlite3 structure in an invalid state. (CVS 6128) check-in: e5d42c69 user: danielk1977 tags: trunk
03:59
Add a HIGHSTRESS parameter to the sqlite3_config_alt_pcache debugging command in the test harness - to force calling pagerStress() more frequently. (CVS 6127) check-in: e426860b user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Show Whitespace Changes Patch

Changes to src/vdbeaux.c.

10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
....
1579
1580
1581
1582
1583
1584
1585

1586
1587
1588
1589
1590
1591
1592
....
1623
1624
1625
1626
1627
1628
1629

1630
1631
1632
1633
1634
1635
1636
**
*************************************************************************
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
** $Id: vdbeaux.c,v 1.429 2009/01/03 14:04:39 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"



................................................................................
          xFunc = sqlite3BtreeRollbackStmt;
        }else{
          /* We are forced to roll back the active transaction. Before doing
          ** so, abort any other statements this handle currently has active.
          */
          invalidateCursorsOnModifiedBtrees(db);
          sqlite3RollbackAll(db);

          db->autoCommit = 1;
        }
      }
    }
  
    /* If the auto-commit flag is set and this is the only active vdbe, then
    ** we do either a commit or rollback of the current transaction. 
................................................................................
          xFunc = sqlite3BtreeCommitStmt;
        } 
      }else if( p->errorAction==OE_Abort ){
        xFunc = sqlite3BtreeRollbackStmt;
      }else{
        invalidateCursorsOnModifiedBtrees(db);
        sqlite3RollbackAll(db);

        db->autoCommit = 1;
      }
    }
  
    /* If xFunc is not NULL, then it is one of sqlite3BtreeRollbackStmt or
    ** sqlite3BtreeCommitStmt. Call it once on each backend. If an error occurs
    ** and the return code is still SQLITE_OK, set the return code to the new







|







 







>







 







>







10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
....
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
....
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
**
*************************************************************************
** This file contains code used for creating, destroying, and populating
** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
** to version 2.8.7, all this code was combined into the vdbe.c source file.
** But that file was getting too big so this subroutines were split out.
**
** $Id: vdbeaux.c,v 1.430 2009/01/07 08:12:16 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"



................................................................................
          xFunc = sqlite3BtreeRollbackStmt;
        }else{
          /* We are forced to roll back the active transaction. Before doing
          ** so, abort any other statements this handle currently has active.
          */
          invalidateCursorsOnModifiedBtrees(db);
          sqlite3RollbackAll(db);
          sqlite3CloseSavepoints(db);
          db->autoCommit = 1;
        }
      }
    }
  
    /* If the auto-commit flag is set and this is the only active vdbe, then
    ** we do either a commit or rollback of the current transaction. 
................................................................................
          xFunc = sqlite3BtreeCommitStmt;
        } 
      }else if( p->errorAction==OE_Abort ){
        xFunc = sqlite3BtreeRollbackStmt;
      }else{
        invalidateCursorsOnModifiedBtrees(db);
        sqlite3RollbackAll(db);
        sqlite3CloseSavepoints(db);
        db->autoCommit = 1;
      }
    }
  
    /* If xFunc is not NULL, then it is one of sqlite3BtreeRollbackStmt or
    ** sqlite3BtreeCommitStmt. Call it once on each backend. If an error occurs
    ** and the return code is still SQLITE_OK, set the return code to the new

Changes to test/savepoint.test.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
740
741
742
743
744
745
746
747

































748
749
#
#    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.
#
#***********************************************************************
#
# $Id: savepoint.test,v 1.8 2009/01/06 13:40:08 danielk1977 Exp $

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


#----------------------------------------------------------------------
# The following tests - savepoint-1.* - test that the SAVEPOINT, RELEASE
................................................................................
  }
} {}
integrity_check savepoint-11.7
do_test savepoint-11.6 {
  execsql { ROLLBACK }
  file size test.db
} {8192}


































finish_test








|







 








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
...
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
#
#    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.
#
#***********************************************************************
#
# $Id: savepoint.test,v 1.9 2009/01/07 08:12:16 danielk1977 Exp $

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


#----------------------------------------------------------------------
# The following tests - savepoint-1.* - test that the SAVEPOINT, RELEASE
................................................................................
  }
} {}
integrity_check savepoint-11.7
do_test savepoint-11.6 {
  execsql { ROLLBACK }
  file size test.db
} {8192}

#-------------------------------------------------------------------------
# The following tests - savepoint-12.* - test the interaction of 
# savepoints and "ON CONFLICT ROLLBACK" clauses.
# 
do_test savepoint-12.1 {
  execsql {
    CREATE TABLE t4(a PRIMARY KEY, b);
    INSERT INTO t4 VALUES(1, 'one');
  }
} {}
do_test savepoint-12.2 {
  # The final statement of the following SQL hits a constraint when the
  # conflict handling mode is "OR ROLLBACK" and there are a couple of
  # open savepoints. At one point this would fail to clear the internal
  # record of the open savepoints, resulting in an assert() failure 
  # later on.
  # 
  catchsql {
    BEGIN;
      INSERT INTO t4 VALUES(2, 'two');
      SAVEPOINT sp1;
        INSERT INTO t4 VALUES(3, 'three');
        SAVEPOINT sp2;
          INSERT OR ROLLBACK INTO t4 VALUES(1, 'one');
  }
} {1 {column a is not unique}}
do_test savepoint-12.3 {
  sqlite3_get_autocommit db
} {1}
do_test savepoint-12.4 {
  execsql { SAVEPOINT one }
} {}

finish_test

Changes to test/savepoint3.test.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
..
54
55
56
57
58
59
60

















61
62
63
#
#    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.
#
#***********************************************************************
#
# $Id: savepoint3.test,v 1.2 2009/01/01 15:20:37 danielk1977 Exp $

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

source $testdir/malloc_common.tcl

do_malloc_test savepoint3-1 -sqlprep {
................................................................................
    DELETE FROM t1 WHERE rowid < 5;
    SAVEPOINT two;
      DELETE FROM t1 WHERE rowid > 10;
    ROLLBACK TO two;
  ROLLBACK TO one;
  RELEASE one;
}


















finish_test








|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>



5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
..
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
#
#    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.
#
#***********************************************************************
#
# $Id: savepoint3.test,v 1.3 2009/01/07 08:12:16 danielk1977 Exp $

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

source $testdir/malloc_common.tcl

do_malloc_test savepoint3-1 -sqlprep {
................................................................................
    DELETE FROM t1 WHERE rowid < 5;
    SAVEPOINT two;
      DELETE FROM t1 WHERE rowid > 10;
    ROLLBACK TO two;
  ROLLBACK TO one;
  RELEASE one;
}

do_ioerr_test savepoint3.3 -sqlprep {
  CREATE TABLE t1(a, b, c);
  INSERT INTO t1 VALUES(1, randstr(1000,1000), randstr(1000,1000));
  INSERT INTO t1 VALUES(2, randstr(1000,1000), randstr(1000,1000));
} -sqlbody {
  BEGIN;
    UPDATE t1 SET a = 3 WHERE a = 1;
    SAVEPOINT one;
      UPDATE t1 SET a = 4 WHERE a = 2;
  COMMIT;
} -cleanup {
  db eval {
    SAVEPOINT one;
    RELEASE one;
  }
}

finish_test