diff options
author | danielk1977 <danielk1977@noemail.net> | 2005-12-16 15:24:28 +0000 |
---|---|---|
committer | danielk1977 <danielk1977@noemail.net> | 2005-12-16 15:24:28 +0000 |
commit | f3f06bb30cb2d140c5ed6b79aee43bc497be4eb4 (patch) | |
tree | 191c519c11a7f311c94e977569d21efa677dd12f /src | |
parent | 71fd80bf5ca3027464eb233c36bd928f2249edc4 (diff) | |
download | sqlite-f3f06bb30cb2d140c5ed6b79aee43bc497be4eb4.tar.gz sqlite-f3f06bb30cb2d140c5ed6b79aee43bc497be4eb4.zip |
Verify that the rollback-hook is invoked correctly when a malloc() failure occurs. (CVS 2824)
FossilOrigin-Name: 83c8ae5bee3b6bdb556d2e85fa260ba855742601
Diffstat (limited to 'src')
-rw-r--r-- | src/btree.c | 14 | ||||
-rw-r--r-- | src/btree.h | 3 | ||||
-rw-r--r-- | src/main.c | 8 | ||||
-rw-r--r-- | src/sqlite.h.in | 17 | ||||
-rw-r--r-- | src/vdbe.c | 19 | ||||
-rw-r--r-- | src/vdbeaux.c | 32 |
6 files changed, 47 insertions, 46 deletions
diff --git a/src/btree.c b/src/btree.c index 65b5594dd..052f917b7 100644 --- a/src/btree.c +++ b/src/btree.c @@ -9,7 +9,7 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* -** $Id: btree.c,v 1.274 2005/12/16 06:54:02 danielk1977 Exp $ +** $Id: btree.c,v 1.275 2005/12/16 15:24:29 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -5818,15 +5818,3 @@ int sqlite3BtreeSync(Btree *pBt, const char *zMaster){ return SQLITE_OK; } -#ifndef SQLITE_OMIT_GLOBALRECOVER -/* -** Reset the btree and underlying pager after a malloc() failure. Any -** transaction that was active when malloc() failed is rolled back. -*/ -int sqlite3BtreeReset(Btree *pBt){ - if( pBt->pCursor ) return SQLITE_BUSY; - pBt->inTrans = TRANS_NONE; - unlockBtreeIfUnused(pBt); - return sqlite3pager_reset(pBt->pPager); -} -#endif diff --git a/src/btree.h b/src/btree.h index acc29710f..61c1cc3d5 100644 --- a/src/btree.h +++ b/src/btree.h @@ -13,7 +13,7 @@ ** subsystem. See comments in the source code for a detailed description ** of what each interface routine does. ** -** @(#) $Id: btree.h,v 1.64 2005/08/27 16:36:49 drh Exp $ +** @(#) $Id: btree.h,v 1.65 2005/12/16 15:24:29 danielk1977 Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -74,7 +74,6 @@ int sqlite3BtreeCreateTable(Btree*, int*, int flags); int sqlite3BtreeIsInTrans(Btree*); int sqlite3BtreeIsInStmt(Btree*); int sqlite3BtreeSync(Btree*, const char *zMaster); -int sqlite3BtreeReset(Btree *); const char *sqlite3BtreeGetFilename(Btree *); const char *sqlite3BtreeGetDirname(Btree *); diff --git a/src/main.c b/src/main.c index ba0bb5feb..2315a6df0 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.311 2005/12/16 06:54:02 danielk1977 Exp $ +** $Id: main.c,v 1.312 2005/12/16 15:24:29 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -204,8 +204,12 @@ int sqlite3_close(sqlite3 *db){ */ void sqlite3RollbackAll(sqlite3 *db){ int i; + int inTrans = 0; for(i=0; i<db->nDb; i++){ if( db->aDb[i].pBt ){ + if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){ + inTrans = 1; + } sqlite3BtreeRollback(db->aDb[i].pBt); db->aDb[i].inTrans = 0; } @@ -215,7 +219,7 @@ void sqlite3RollbackAll(sqlite3 *db){ } /* If one has been configured, invoke the rollback-hook callback */ - if( db->xRollbackCallback ){ + if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){ db->xRollbackCallback(db->pRollbackArg); } } diff --git a/src/sqlite.h.in b/src/sqlite.h.in index 966b38a20..551fddc23 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.147 2005/12/16 06:54:02 danielk1977 Exp $ +** @(#) $Id: sqlite.h.in,v 1.148 2005/12/16 15:24:29 danielk1977 Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -1319,6 +1319,21 @@ void *sqlite3_update_hook( void* ); +/* +** Register a callback to be invoked whenever a transaction is rolled +** back. +** +** The new callback function overrides any existing rollback-hook +** callback. If there was an existing callback, then it's pArg value +** (the third argument to sqlite3_rollback_hook() when it was registered) +** is returned. Otherwise, NULL is returned. +** +** For the purposes of this API, a transaction is said to have been +** rolled back if an explicit "ROLLBACK" statement is executed, or +** an error or constraint causes an implicit rollback to occur. The +** callback is not invoked if a transaction is automatically rolled +** back because the database connection is closed. +*/ void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*); /* diff --git a/src/vdbe.c b/src/vdbe.c index 95e024d20..4cedcd5c2 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -43,7 +43,7 @@ ** in this file for details. If in doubt, do not deviate from existing ** commenting and indentation practices when changing or adding code. ** -** $Id: vdbe.c,v 1.505 2005/12/15 15:22:10 danielk1977 Exp $ +** $Id: vdbe.c,v 1.506 2005/12/16 15:24:29 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -2299,16 +2299,19 @@ case OP_AutoCommit: { /* no-push */ " transaction - SQL statements in progress", 0); rc = SQLITE_ERROR; }else if( i!=db->autoCommit ){ - db->autoCommit = i; if( pOp->p2 ){ assert( i==1 ); sqlite3RollbackAll(db); - }else if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ - p->pTos = pTos; - p->pc = pc; - db->autoCommit = 1-i; - p->rc = SQLITE_BUSY; - return SQLITE_BUSY; + db->autoCommit = 1; + }else{ + db->autoCommit = i; + if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){ + p->pTos = pTos; + p->pc = pc; + db->autoCommit = 1-i; + p->rc = SQLITE_BUSY; + return SQLITE_BUSY; + } } return SQLITE_DONE; }else{ diff --git a/src/vdbeaux.c b/src/vdbeaux.c index a99dc4643..82977e881 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1177,12 +1177,12 @@ int sqlite3VdbeHalt(Vdbe *p){ return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ p->rc = rc; - xFunc = sqlite3BtreeRollback; + sqlite3RollbackAll(db); }else{ sqlite3CommitInternalChanges(db); } }else{ - xFunc = sqlite3BtreeRollback; + sqlite3RollbackAll(db); } }else{ @@ -1227,9 +1227,9 @@ int sqlite3VdbeHalt(Vdbe *p){ }else if( p->errorAction==OE_Abort ){ xFunc = sqlite3BtreeRollbackStmt; }else{ - xFunc = sqlite3BtreeRollback; - db->autoCommit = 1; abortOtherActiveVdbes(p); + sqlite3RollbackAll(db); + db->autoCommit = 1; } } @@ -1240,20 +1240,14 @@ int sqlite3VdbeHalt(Vdbe *p){ */ assert(!xFunc || xFunc==sqlite3BtreeCommitStmt || - xFunc==sqlite3BtreeRollbackStmt || - xFunc==sqlite3BtreeRollback + xFunc==sqlite3BtreeRollbackStmt ); - if( xFunc==sqlite3BtreeRollback ){ - assert( p->rc!=SQLITE_OK ); - sqlite3RollbackAll(db); - }else{ - for(i=0; xFunc && i<db->nDb; i++){ - int rc; - Btree *pBt = db->aDb[i].pBt; - if( pBt ){ - rc = xFunc(pBt); - if( p->rc==SQLITE_OK ) p->rc = rc; - } + for(i=0; xFunc && i<db->nDb; i++){ + int rc; + Btree *pBt = db->aDb[i].pBt; + if( pBt ){ + rc = xFunc(pBt); + if( p->rc==SQLITE_OK ) p->rc = rc; } } @@ -1270,9 +1264,7 @@ int sqlite3VdbeHalt(Vdbe *p){ /* Rollback or commit any schema changes that occurred. */ if( p->rc!=SQLITE_OK && db->flags&SQLITE_InternChanges ){ sqlite3ResetInternalSchema(db, 0); - if( xFunc!=sqlite3BtreeRollback ){ - db->flags = (db->flags | SQLITE_InternChanges); - } + db->flags = (db->flags | SQLITE_InternChanges); } /* We have successfully halted and closed the VM. Record this fact. */ |