Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -12,11 +12,11 @@ ** 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 $ +** $Id: vdbeaux.c,v 1.430 2009/01/07 08:12:16 danielk1977 Exp $ */ #include "sqliteInt.h" #include #include "vdbeInt.h" @@ -1581,10 +1581,11 @@ /* 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; } } } @@ -1625,10 +1626,11 @@ }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 Index: test/savepoint.test ================================================================== --- test/savepoint.test +++ test/savepoint.test @@ -7,11 +7,11 @@ # 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 $ +# $Id: savepoint.test,v 1.9 2009/01/07 08:12:16 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -742,8 +742,41 @@ 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 Index: test/savepoint3.test ================================================================== --- test/savepoint3.test +++ test/savepoint3.test @@ -7,11 +7,11 @@ # 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 $ +# $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 @@ -56,8 +56,25 @@ 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