-C Save\sthe\sposition\sof\sany\sopen\scursors\sbefore\sa\srollback.\s(CVS\s3026)
-D 2006-01-24T14:21:24
+C Handle\serrors\sin\ssaving\scursor\spositions\sduring\sa\srollback\sby\saborting\sall\sactive\sstatements.\s(CVS\s3027)
+D 2006-01-24T16:37:58
F Makefile.in 53841eb72e9eeb6030a8ce28c2595a92f440fd10
F Makefile.linux-gcc 74ba0eadf88748a9ce3fd03d2a3ede2e6715baec
F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
F src/analyze.c 7d2b7ab9a9c2fd6e55700f69064dfdd3e36d7a8a
F src/attach.c d73a3505de3fb9e373d0a158978116c4212031d0
F src/auth.c 9ae84d2d94eb96195e04515715e08e85963e96c2
-F src/btree.c 5b71740985d4845f3a6ac7e0bb809e41d25830d4
+F src/btree.c f45f57e6cbd3b3db947cdd699db64e5215d20b2a
F src/btree.h 5663c4f43e8521546ccebc8fc95acb013b8f3184
F src/build.c feaa61e769d7887ffeaa060d746638c7b3e994ef
F src/callback.c 1bf497306c32229114f826707054df7ebe10abf2
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
F src/insert.c 7e931b7f06afbcefcbbaab175c02eff8268db33f
F src/legacy.c 86b669707b3cefd570e34154e2f6457547d1df4f
-F src/main.c dc3fc9b02b1a022574d6e12d25abe58b93b85b1f
+F src/main.c 2693776249865dc69b97904205638e84a34a059c
F src/md5.c c5fdfa5c2593eaee2e32a5ce6c6927c986eaf217
F src/os.c 59f05de8c5777c34876607114a2fbe55ae578235
F src/os.h 93035a0e3b9dd05cdd0aaef32ea28ca28e02fe78
F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
F src/shell.c 66b073375efbdee19045e7e0cd38b85f9aff71da
F src/sqlite.h.in 492580f7e3ff71eb43193eb7bb98e2d549889ce3
-F src/sqliteInt.h 35a3c3556abfca796cf44fea83c9f04385efcfb6
+F src/sqliteInt.h 0121298397ac14eb468ab1ba9d488ac7ed7d88a1
F src/table.c 486dcfce532685b53b5a2b5da8bba0ded6fb2316
F src/tclsqlite.c 7764ab34df617b3d3cfd5f0fdf3444ed219c11d6
F src/test1.c ce715e15c8045c598fe83a17f862ddeedf60c057
F src/vdbe.h 8729a4ee16ff9aeab2af9667df3cf300ff978e13
F src/vdbeInt.h eb3f86ab08ef11635bc78eb88c3ff13f923c233b
F src/vdbeapi.c dcb2636f49b4807e34960d52a2fc257b3a751140
-F src/vdbeaux.c 0c27d3b3bd8dda7ed73eb8fcfa74350ca6633895
+F src/vdbeaux.c bc90137791c9442ddd9e81453f10a23688d19dbf
F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5
F src/vdbemem.c 2034e93b32c14bda6e306bb54e3a8e930b963027
F src/where.c 8409e00fa2cb5fce873b4c911165cfed097e9c49
F test/server1.test e328b8e641ba8fe9273132cfef497383185dc1f5
F test/shared.test 0ed247941236788c255b3b29b5a82d5ca71b6432
F test/shared2.test 3466dc54ca69a3c50ac259e106fb5cd067b8cd53
-F test/shared_err.test 162ad76d510370e4d3878cb6c376e1292db06005
+F test/shared_err.test 299a9180a6376b2089e8e0d469f383fe91bfa4ff
F test/sort.test 0e4456e729e5a92a625907c63dcdedfbe72c5dc5
F test/subquery.test ae324ee928c5fb463a3ce08a8860d6e7f1ca5797
F test/subselect.test 2d13fb7f450db3595adcdd24079a0dd1d2d6abc2
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
F www/version3.tcl a99cf5f6d8bd4d5537584a2b342f0fb9fa601d8b
F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P c30705a00d7d9d61fb9cb47a1019b1a186d690a7
-R 6675c7ec185eda4043b15c5e61211396
+P 32d45bcf746e7e926b8cc8bd038d66e7c2ec6562
+R bfc84cb6ae1c5988a33aa090aaeb35d5
U danielk1977
-Z 32002e918852056122387d8fed3cdfe2
+Z b319ec5ca674b878a1973ce33be953dd
-32d45bcf746e7e926b8cc8bd038d66e7c2ec6562
\ No newline at end of file
+5df9f022bfb22976f22b996bda169635354b825c
\ No newline at end of file
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.310 2006/01/24 14:21:24 danielk1977 Exp $
+** $Id: btree.c,v 1.311 2006/01/24 16:37:58 danielk1977 Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
ThreadData *pTsd;
#endif
- /* Drop any table-locks */
- unlockAllTables(p);
-
/* Close all cursors opened via this handle. */
pCur = pBt->pCursor;
while( pCur ){
}
}
- /* Rollback any active transaction and free the handle structure */
+ /* Rollback any active transaction and free the handle structure.
+ ** The call to sqlite3BtreeRollback() drops any table-locks held by
+ ** this handle.
+ */
sqlite3BtreeRollback(p);
sqliteFree(p);
** are no active cursors, it also releases the read lock.
*/
int sqlite3BtreeRollback(Btree *p){
- int rc = SQLITE_OK;
+ int rc;
BtShared *pBt = p->pBt;
MemPage *pPage1;
rc = saveAllCursors(pBt, 0, 0);
+#ifndef SQLITE_OMIT_SHARED_CACHE
if( rc!=SQLITE_OK ){
- return rc;
+ /* This is a horrible situation. An IO or malloc() error occured whilst
+ ** trying to save cursor positions. If this is an automatic rollback (as
+ ** the result of a constraint, malloc() failure or IO error) then
+ ** the cache may be internally inconsistent (not contain valid trees) so
+ ** we cannot simply return the error to the caller. Instead, abort
+ ** all queries that may be using any of the cursors that failed to save.
+ */
+ while( pBt->pCursor ){
+ sqlite3 *db = pBt->pCursor->pBtree->pSqlite;
+ if( db ){
+ sqlite3AbortOtherActiveVdbes(db, 0);
+ }
+ }
}
+#endif
btreeIntegrity(p);
unlockAllTables(p);
if( p->inTrans==TRANS_WRITE ){
+ int rc2;
+
assert( TRANS_WRITE==pBt->inTransaction );
+ rc2 = sqlite3pager_rollback(pBt->pPager);
+ if( rc2!=SQLITE_OK ){
+ rc = rc2;
+ }
- rc = sqlite3pager_rollback(pBt->pPager);
/* The rollback may have destroyed the pPage1->aData value. So
** call getPage() on page 1 again to make sure pPage1->aData is
** set correctly. */
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.330 2006/01/24 13:09:33 danielk1977 Exp $
+** $Id: main.c,v 1.331 2006/01/24 16:37:58 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
return SQLITE_ERROR;
}
- /* sqlite3_close() may not invoke sqliteMalloc(). */
- sqlite3MallocDisallow();
-
for(j=0; j<db->nDb; j++){
struct Db *pDb = &db->aDb[j];
if( pDb->pBt ){
*/
sqliteFree(db->aDb[1].pSchema);
sqliteFree(db);
- sqlite3MallocAllow();
sqlite3ReleaseThreadData();
return SQLITE_OK;
}
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.478 2006/01/23 13:28:54 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.479 2006/01/24 16:37:58 danielk1977 Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
int sqlite3ApiExit(sqlite3 *db, int);
int sqlite3MallocFailed(void);
void sqlite3FailedMalloc(void);
+void sqlite3AbortOtherActiveVdbes(sqlite3 *, Vdbe *);
#ifndef SQLITE_OMIT_SHARED_CACHE
void sqlite3TableLock(Parse *, int, int, u8, const char *);
** aborted so that they do not have data rolled out from underneath
** them leading to a segfault.
*/
-static void abortOtherActiveVdbes(Vdbe *pVdbe){
+void sqlite3AbortOtherActiveVdbes(sqlite3 *db, Vdbe *pExcept){
Vdbe *pOther;
- for(pOther=pVdbe->db->pVdbe; pOther; pOther=pOther->pNext){
- if( pOther==pVdbe ) continue;
+ for(pOther=db->pVdbe; pOther; pOther=pOther->pNext){
+ if( pOther==pExcept ) continue;
if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue;
closeAllCursors(pOther);
pOther->aborted = 1;
/* We are forced to roll back the active transaction. Before doing
** so, abort any other statements this handle currently has active.
*/
- abortOtherActiveVdbes(p);
+ sqlite3AbortOtherActiveVdbes(db, p);
sqlite3RollbackAll(db);
db->autoCommit = 1;
}
}else if( p->errorAction==OE_Abort ){
xFunc = sqlite3BtreeRollbackStmt;
}else{
- abortOtherActiveVdbes(p);
+ sqlite3AbortOtherActiveVdbes(db, p);
sqlite3RollbackAll(db);
db->autoCommit = 1;
}
# cache context. What happens to connection B if one connection A encounters
# an IO-error whilst reading or writing the file-system?
#
-# $Id: shared_err.test,v 1.8 2006/01/24 11:30:27 danielk1977 Exp $
+# $Id: shared_err.test,v 1.9 2006/01/24 16:37:59 danielk1977 Exp $
proc skip {args} {}
}
} -cleanup {
do_test shared_malloc-4.$::n.cleanup.1 {
- sqlite3_step $::STMT
- } {SQLITE_ROW}
- do_test shared_malloc-4.$::n.cleanup.2 {
- sqlite3_column_text $::STMT 0
- } {2222222222}
+ set ::rc [sqlite3_step $::STMT]
+ expr {$::rc=="SQLITE_ROW" || $::rc=="SQLITE_ABORT"}
+ } {1}
+ if {$::rc=="SQLITE_ROW"} {
+ do_test shared_malloc-4.$::n.cleanup.2 {
+ sqlite3_column_text $::STMT 0
+ } {2222222222}
+ }
do_test shared_malloc-4.$::n.cleanup.3 {
sqlite3_finalize $::STMT
} {SQLITE_OK}
set msg
} {library routine called out of sequence}
+# Again provoke a malloc() failure when a cursor position is being saved,
+# this time during a ROLLBACK operation by some other handle.
+#
+# The library should return an SQLITE_NOMEM to the caller. The query that
+# owns the cursor (the one for which the position is not saved) should
+# be aborted.
+#
+set ::aborted 0
+do_malloc_test 8 -tclprep {
+ sqlite3 db2 test.db
+ execsql {
+ PRAGMA read_uncommitted = 1;
+ BEGIN;
+ CREATE TABLE t1(a, b, UNIQUE(a, b));
+ } db2
+ for {set i 0} {$i < 2} {incr i} {
+ set a [string repeat $i 10]
+ set b [string repeat $i 2000]
+ execsql {INSERT INTO t1 VALUES($a, $b)} db2
+ }
+ execsql {COMMIT} db2
+ set ::DB2 [sqlite3_connection_pointer db2]
+ set ::STMT [sqlite3_prepare $::DB2 "SELECT a FROM t1 ORDER BY a" -1 DUMMY]
+ sqlite3_step $::STMT ;# Cursor points at 0000000000
+ sqlite3_step $::STMT ;# Cursor points at 1111111111
+} -tclbody {
+ execsql {
+ BEGIN;
+ INSERT INTO t1 VALUES(6, NULL);
+ ROLLBACK;
+ }
+} -cleanup {
+ do_test shared_malloc-8.$::n.cleanup.1 {
+ lrange [execsql {
+ SELECT a FROM t1;
+ } db2] 0 1
+ } {0000000000 1111111111}
+ do_test shared_malloc-8.$::n.cleanup.2 {
+ set rc1 [sqlite3_step $::STMT]
+ set rc2 [sqlite3_finalize $::STMT]
+ if {$rc1=="SQLITE_ABORT"} {
+ incr ::aborted
+ }
+ expr {
+ ($rc1=="SQLITE_DONE" && $rc2=="SQLITE_OK") ||
+ ($rc1=="SQLITE_ABORT" && $rc2=="SQLITE_OK")
+ }
+ } {1}
+ db2 close
+}
+do_test shared_malloc-8.X {
+ # Test that one or more queries were aborted due to the malloc() failure.
+ expr $::aborted>=1
+} {1}
+
catch {db close}
sqlite3_enable_shared_cache $::enable_shared_cache
finish_test