-C Changes\sto\svarious\stest\sscripts\sso\sthat\sveryquick.test\sruns\swith\sOMIT_COMPOUND_SELECT\sdefined.
-D 2012-02-13T10:00:35.138
+C Change\sthe\sROLLBACK\scommand\sso\sthat\spending\sstatements\sto\snot\sblock\sit.\s\sThe\npending\sstatements\sinstead\sreturn\sSQLITE_ABORT\supon\snext\saccess.\s\sNote:\sThis\ncauses\sseparate\sshared-cache\sconnections\sin\sread_uncommitted\smode\sto\sabort\sas\nwell.
+D 2012-02-13T16:43:16.086
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 3f79a373e57c3b92dabf76f40b065e719d31ac34
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F src/analyze.c f32ff304da413851eefa562b04e61ff6cb88248b
F src/attach.c 12c6957996908edc31c96d7c68d4942c2474405f
F src/auth.c 523da7fb4979469955d822ff9298352d6b31de34
-F src/backup.c e9538bad2d4a4fcd4308f1aed7cb18a0fbc968f9
+F src/backup.c 6be23a344d3301ae38e92fddb3a33b91c309fce4
F src/bitvec.c af50f1c8c0ff54d6bdb7a80e2fceca5a93670bef
F src/btmutex.c 976f45a12e37293e32cae0281b15a21d48a8aaa7
-F src/btree.c bb0132a725b4d5ed077924399c4f6d4b9390a721
-F src/btree.h 46e9f04672f1390255bc56865a3238b384d0f2d5
+F src/btree.c 253c3147a4ebbaee42cd329dbdc0856200bbbda7
+F src/btree.h 48a013f8964f12d944d90e4700df47b72dd6d923
F src/btreeInt.h 26d8ca625b141927fe6620c1d2cf58eaf494ca0c
F src/build.c c4d36e527f457f9992a6663365871dfa7c5094b8
F src/callback.c 0425c6320730e6d3981acfb9202c1bed9016ad1a
F src/legacy.c a199d7683d60cef73089e892409113e69c23a99f
F src/lempar.c 0ee69fca0be54cd93939df98d2aca4ca46f44416
F src/loadext.c f20382fbaeec832438a1ba7797bee3d3c8a6d51d
-F src/main.c cb099cc4864b542f97938049fc74ea8ae6845ce4
+F src/main.c 4aa7f1994a7cf810d7d754cb30202543b40bb726
F src/malloc.c 15afac5e59b6584efe072e9933aefb4230e74f97
F src/mem0.c 6a55ebe57c46ca1a7d98da93aaa07f99f1059645
F src/mem1.c b3677415e69603d6a0e7c5410a1b3731d55beda1
F src/shell.c aa28f117033ba3e44b5eaaf2ad572222bcdfd66e
F src/sqlite.h.in 371c30e4be94b9b0ea6400ed66663fcf8e891eb4
F src/sqlite3ext.h 6904f4aadf976f95241311fbffb00823075d9477
-F src/sqliteInt.h 736f3a7748434200db7a9e0a352b67d1b8759e0a
+F src/sqliteInt.h ea24b5f2d2e3ae7e0c1126a78c0e025ed4e98f4b
F src/sqliteLimit.h 164b0e6749d31e0daa1a4589a169d31c0dec7b3d
F src/status.c 4568e72dfd36b6a5911f93457364deb072e0b03a
F src/table.c 2cd62736f845d82200acfa1287e33feb3c15d62e
F src/utf.c 890c67dcfcc7a74623c95baac7535aadfe265e84
F src/util.c 9e07bd67dfafe9c75b1da78c87ba030cebbb5388
F src/vacuum.c 0c0ba2242355c6048d65e2b333abe0f7c06348fa
-F src/vdbe.c 40b14dff04692b1ee421db40c67d4921ecf17a9d
+F src/vdbe.c 2afc9b0260dfe47786211e1eb815a52f27c661b7
F src/vdbe.h 18f581cac1f4339ec3299f3e0cc6e11aec654cdb
F src/vdbeInt.h 6ff4180a05683566a8835d12f7ec504b22932c82
F src/vdbeapi.c 3662b6a468a2a4605a15dfab313baa6dff81ad91
-F src/vdbeaux.c 7683d772ad638faa4567142438c4594e47f173c4
+F src/vdbeaux.c dce061e42f89cd6d0af15c03a854bcc89bd5deb0
F src/vdbeblob.c 32f2a4899d67f69634ea4dd93e3f651936d732cb
F src/vdbemem.c fb0ac964ccbcd94f595eb993c05bfd9c52468a4a
F src/vdbesort.c b25814d385895544ebc8118245c8311ded7f81c9
F test/busy.test 76b4887f8b9160ba903c1ac22e8ff406ad6ae2f0
F test/cache.test f64136b0893c293d0b910ed057b3b711249099a7
F test/capi2.test 835d4cee9f542ea50fa8d01f3fe6de80b0627360
-F test/capi3.test 7200dff6acb17b9a4b6f9918f554eaae04968ddd
+F test/capi3.test 9c8b58b6a6aeb14e69bd8c8c7721b47d640464d1
F test/capi3b.test efb2b9cfd127efa84433cd7a2d72ce0454ae0dc4
-F test/capi3c.test ccf0acf045dbacd09f6229aa4efed670aaba76a9
+F test/capi3c.test 1b5424d2ac57b7b443b5de5b9a287642c02279b6
F test/capi3d.test 17b57ca28be3e37e14c2ba8f787d292d84b724a1
F test/capi3e.test f7408dda65c92b9056199fdc180f893015f83dde
F test/cast.test 4c275cbdc8202d6f9c54a3596701719868ac7dc3
F test/in2.test 5d4c61d17493c832f7d2d32bef785119e87bde75
F test/in3.test 3cbf58c87f4052cee3a58b37b6389777505aa0c0
F test/in4.test 64f3cc1acde1b9161ccdd8e5bde3daefdb5b2617
-F test/incrblob.test 3307c04876fe025e10256e3cc8050ab5a84aa27f
+F test/incrblob.test 26fde912a1e0aff158b3a84ef3b265f046aad3be
F test/incrblob2.test edc3a96e557bd61fb39acc8d2edd43371fbbaa19
F test/incrblob3.test aedbb35ea1b6450c33b98f2b6ed98e5020be8dc7
F test/incrblob_err.test d2562d2771ebffd4b3af89ef64c140dd44371597
F test/rowhash.test 0bc1d31415e4575d10cacf31e1a66b5cc0f8be81
F test/rowid.test e58e0acef38b527ed1b0b70d3ada588f804af287
F test/rtree.test 0c8d9dd458d6824e59683c19ab2ffa9ef946f798
-F test/savepoint.test 42ba63b632df4ce1bef8acdba62e4182d6505125
+F test/savepoint.test f5acd87d0c7a5f4ad6c547b47fd18c0e1aeaf048
F test/savepoint2.test 9b8543940572a2f01a18298c3135ad0c9f4f67d7
F test/savepoint3.test e328085853b14898d78ceea00dfe7db18bb6a9ec
F test/savepoint4.test c8f8159ade6d2acd9128be61e1230f1c1edc6cc0
F test/selectC.test 871fb55d884d3de5943c4057ebd22c2459e71977
F test/server1.test 46803bd3fe8b99b30dbc5ff38ffc756f5c13a118
F test/shared.test 34945a516532b11182c3eb26e31247eee3c9ae48
-F test/shared2.test 8f71d4eb4d5261280de92284df74172545c852cc
+F test/shared2.test 03eb4a8d372e290107d34b6ce1809919a698e879
F test/shared3.test ebf77f023f4bdaa8f74f65822b559e86ce5c6257
F test/shared4.test 72d90821e8d2fc918a08f16d32880868d8ee8e9d
F test/shared6.test 866bb4982c45ce216c61ded5e8fde4e7e2f3ffa9
F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
F tool/warnings-clang.sh 9f406d66e750e8ac031c63a9ef3248aaa347ef2a
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
-P bfbfe05b81919ecc3d6e7be4c24994f795f16582
-R 6250e4472fb78736176921352e48e2f9
-U dan
-Z f0319cf74449ae83da7435ab8330767c
+P 76bb649ee2633226324130f5898622c348f93769
+R 99d7e91688392c96521a36db0be702a8
+T *branch * nonblocking-rollback
+T *sym-nonblocking-rollback *
+T -sym-trunk *
+U drh
+Z 742e7385f2147385b0b62b5bc1ba4557
-76bb649ee2633226324130f5898622c348f93769
\ No newline at end of file
+9b66c79e054c8a109d1ee8d35fed1c42814c330d
\ No newline at end of file
}
/* If a transaction is still open on the Btree, roll it back. */
- sqlite3BtreeRollback(p->pDest);
+ sqlite3BtreeRollback(p->pDest, SQLITE_OK);
/* Set the error code of the destination database handle. */
rc = (p->rc==SQLITE_DONE) ? SQLITE_OK : p->rc;
** The call to sqlite3BtreeRollback() drops any table-locks held by
** this handle.
*/
- sqlite3BtreeRollback(p);
+ sqlite3BtreeRollback(p, SQLITE_OK);
sqlite3BtreeLeave(p);
/* If there are still other outstanding references to the shared-btree
*/
void sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode){
BtCursor *p;
+ if( pBtree==0 ) return;
sqlite3BtreeEnter(pBtree);
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
int i;
** This will release the write lock on the database file. If there
** are no active cursors, it also releases the read lock.
*/
-int sqlite3BtreeRollback(Btree *p){
+int sqlite3BtreeRollback(Btree *p, int tripCode){
int rc;
BtShared *pBt = p->pBt;
MemPage *pPage1;
sqlite3BtreeEnter(p);
- rc = saveAllCursors(pBt, 0, 0);
-#ifndef SQLITE_OMIT_SHARED_CACHE
- if( rc!=SQLITE_OK ){
- /* This is a horrible situation. An IO or malloc() error occurred 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.
- */
- sqlite3BtreeTripAllCursors(p, rc);
+ if( tripCode==SQLITE_OK ){
+ rc = tripCode = saveAllCursors(pBt, 0, 0);
+ }else{
+ rc = SQLITE_OK;
+ }
+ if( tripCode ){
+ sqlite3BtreeTripAllCursors(p, tripCode);
}
-#endif
btreeIntegrity(p);
if( p->inTrans==TRANS_WRITE ){
int sqlite3BtreeCommitPhaseOne(Btree*, const char *zMaster);
int sqlite3BtreeCommitPhaseTwo(Btree*, int);
int sqlite3BtreeCommit(Btree*);
-int sqlite3BtreeRollback(Btree*);
+int sqlite3BtreeRollback(Btree*,int);
int sqlite3BtreeBeginStmt(Btree*,int);
int sqlite3BtreeCreateTable(Btree*, int*, int flags);
int sqlite3BtreeIsInTrans(Btree*);
}
/*
-** Rollback all database files.
+** Rollback all database files. If tripCode is not SQLITE_OK, then
+** any open cursors are invalidated ("tripped" - as in "tripping a circuit
+** breaker") and made to return tripCode if there are any further
+** attempts to use that cursor.
*/
-void sqlite3RollbackAll(sqlite3 *db){
+void sqlite3RollbackAll(sqlite3 *db, int tripCode){
int i;
int inTrans = 0;
assert( sqlite3_mutex_held(db->mutex) );
sqlite3BeginBenignMalloc();
for(i=0; i<db->nDb; i++){
- if( db->aDb[i].pBt ){
- if( sqlite3BtreeIsInTrans(db->aDb[i].pBt) ){
+ Btree *p = db->aDb[i].pBt;
+ if( p ){
+ if( sqlite3BtreeIsInTrans(p) ){
inTrans = 1;
}
- sqlite3BtreeRollback(db->aDb[i].pBt);
+ sqlite3BtreeRollback(p, tripCode);
db->aDb[i].inTrans = 0;
}
}
void sqlite3PrngSaveState(void);
void sqlite3PrngRestoreState(void);
void sqlite3PrngResetState(void);
-void sqlite3RollbackAll(sqlite3*);
+void sqlite3RollbackAll(sqlite3*,int);
void sqlite3CodeVerifySchema(Parse*, int);
void sqlite3CodeVerifyNamedSchema(Parse*, const char *zDb);
void sqlite3BeginTransaction(Parse*, int);
if( !pSavepoint ){
sqlite3SetString(&p->zErrMsg, db, "no such savepoint: %s", zName);
rc = SQLITE_ERROR;
- }else if(
- db->writeVdbeCnt>0 || (p1==SAVEPOINT_ROLLBACK && db->activeVdbeCnt>1)
- ){
+ }else if( db->writeVdbeCnt>0 && p1==SAVEPOINT_RELEASE ){
/* It is not possible to release (commit) a savepoint if there are
- ** active write statements. It is not possible to rollback a savepoint
- ** if there are any active statements at all.
+ ** active write statements.
*/
sqlite3SetString(&p->zErrMsg, db,
- "cannot %s savepoint - SQL statements in progress",
- (p1==SAVEPOINT_ROLLBACK ? "rollback": "release")
+ "cannot release savepoint - SQL statements in progress"
);
rc = SQLITE_BUSY;
}else{
rc = p->rc;
}else{
iSavepoint = db->nSavepoint - iSavepoint - 1;
+ for(ii=0; ii<db->nDb; ii++){
+ sqlite3BtreeTripAllCursors(db->aDb[ii].pBt, SQLITE_ABORT);
+ }
for(ii=0; ii<db->nDb; ii++){
rc = sqlite3BtreeSavepoint(db->aDb[ii].pBt, p1, iSavepoint);
if( rc!=SQLITE_OK ){
assert( desiredAutoCommit==1 || iRollback==0 );
assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */
+#if 0
if( turnOnAC && iRollback && db->activeVdbeCnt>1 ){
/* If this instruction implements a ROLLBACK and other VMs are
** still running, and a transaction is active, return an error indicating
sqlite3SetString(&p->zErrMsg, db, "cannot rollback transaction - "
"SQL statements in progress");
rc = SQLITE_BUSY;
- }else if( turnOnAC && !iRollback && db->writeVdbeCnt>0 ){
+ }else
+#endif
+ if( turnOnAC && !iRollback && db->writeVdbeCnt>0 ){
/* If this instruction implements a COMMIT and other VMs are writing
** return an error indicating that the other VMs must complete first.
*/
}else if( desiredAutoCommit!=db->autoCommit ){
if( iRollback ){
assert( desiredAutoCommit==1 );
- sqlite3RollbackAll(db);
+ sqlite3RollbackAll(db, SQLITE_ABORT);
db->autoCommit = 1;
}else if( (rc = sqlite3VdbeCheckFk(p, 1))!=SQLITE_OK ){
goto vdbe_return;
#define checkActiveVdbeCnt(x)
#endif
-/*
-** For every Btree that in database connection db which
-** has been modified, "trip" or invalidate each cursor in
-** that Btree might have been modified so that the cursor
-** can never be used again. This happens when a rollback
-*** occurs. We have to trip all the other cursors, even
-** cursor from other VMs in different database connections,
-** so that none of them try to use the data at which they
-** were pointing and which now may have been changed due
-** to the rollback.
-**
-** Remember that a rollback can delete tables complete and
-** reorder rootpages. So it is not sufficient just to save
-** the state of the cursor. We have to invalidate the cursor
-** so that it is never used again.
-*/
-static void invalidateCursorsOnModifiedBtrees(sqlite3 *db){
- int i;
- for(i=0; i<db->nDb; i++){
- Btree *p = db->aDb[i].pBt;
- if( p && sqlite3BtreeIsInTrans(p) ){
- sqlite3BtreeTripAllCursors(p, SQLITE_ABORT);
- }
- }
-}
-
/*
** If the Vdbe passed as the first argument opened a statement-transaction,
** close it now. Argument eOp must be either SAVEPOINT_ROLLBACK or
/* 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);
+ sqlite3RollbackAll(db, SQLITE_ABORT);
sqlite3CloseSavepoints(db);
db->autoCommit = 1;
}
return SQLITE_BUSY;
}else if( rc!=SQLITE_OK ){
p->rc = rc;
- sqlite3RollbackAll(db);
+ sqlite3RollbackAll(db, SQLITE_OK);
}else{
db->nDeferredCons = 0;
sqlite3CommitInternalChanges(db);
}
}else{
- sqlite3RollbackAll(db);
+ sqlite3RollbackAll(db, SQLITE_OK);
}
db->nStatement = 0;
}else if( eStatementOp==0 ){
}else if( p->errorAction==OE_Abort ){
eStatementOp = SAVEPOINT_ROLLBACK;
}else{
- invalidateCursorsOnModifiedBtrees(db);
- sqlite3RollbackAll(db);
+ sqlite3RollbackAll(db, SQLITE_ABORT);
sqlite3CloseSavepoints(db);
db->autoCommit = 1;
}
sqlite3DbFree(db, p->zErrMsg);
p->zErrMsg = 0;
}
- invalidateCursorsOnModifiedBtrees(db);
- sqlite3RollbackAll(db);
+ sqlite3RollbackAll(db, SQLITE_ABORT);
sqlite3CloseSavepoints(db);
db->autoCommit = 1;
}
catchsql {
ROLLBACK;
}
-} {1 {cannot rollback transaction - SQL statements in progress}}
+} {0 {}}
do_test capi3-11.9.3 {
sqlite3_get_autocommit $DB
-} 0
+} 1
do_test capi3-11.10 {
sqlite3_step $STMT
-} {SQLITE_ROW}
+} {SQLITE_ERROR}
do_test capi3-11.11 {
sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3-11.12 {
sqlite3_step $STMT
+ sqlite3_step $STMT
} {SQLITE_DONE}
do_test capi3-11.13 {
sqlite3_finalize $STMT
execsql {
SELECT a FROM t2;
}
-} {1 2 3}
+} {1 2}
do_test capi3-11.14.1 {
sqlite3_get_autocommit $DB
-} 0
+} 1
do_test capi3-11.15 {
catchsql {
ROLLBACK;
}
-} {0 {}}
+} {1 {cannot rollback - no transaction is active}}
do_test capi3-11.15.1 {
sqlite3_get_autocommit $DB
} 1
catchsql {
ROLLBACK;
}
-} {1 {cannot rollback transaction - SQL statements in progress}}
+} {0 {}}
do_test capi3c-11.9.3 {
sqlite3_get_autocommit $DB
-} 0
+} 1
do_test capi3c-11.10 {
sqlite3_step $STMT
-} {SQLITE_ROW}
+} {SQLITE_ABORT}
do_test capi3c-11.11 {
sqlite3_step $STMT
} {SQLITE_ROW}
do_test capi3c-11.12 {
sqlite3_step $STMT
+ sqlite3_step $STMT
} {SQLITE_DONE}
do_test capi3c-11.13 {
sqlite3_finalize $STMT
execsql {
SELECT a FROM t2;
}
-} {1 2 3}
+} {1 2}
do_test capi3c-11.14.1 {
sqlite3_get_autocommit $DB
-} 0
+} 1
do_test capi3c-11.15 {
catchsql {
ROLLBACK;
}
-} {0 {}}
+} {1 {cannot rollback - no transaction is active}}
do_test capi3c-11.15.1 {
sqlite3_get_autocommit $DB
} 1
flush $::blob
} {}
- # At this point rollback should be illegal (because
- # there is an open blob channel). But commit is also illegal because
- # the open blob is read-write.
+ # At this point commit should be illegal (because
+ # there is an open blob channel).
#
- do_test incrblob-6.10 {
- catchsql {
- ROLLBACK;
- } db2
- } {1 {cannot rollback transaction - SQL statements in progress}}
do_test incrblob-6.11 {
catchsql {
COMMIT;
execsql {SAVEPOINT abc}
catchsql {ROLLBACK TO def}
} {1 {no such savepoint: def}}
- do_test savepoint-5.3.2 {
+ do_test savepoint-5.3.2.1 {
execsql {SAVEPOINT def}
set fd [db incrblob -readonly blobs x 1]
+ set rc [catch {seek $fd 0;read $fd} res]
+ lappend rc $res
+ } {0 {hellontyeight character blob}}
+ do_test savepoint-5.3.2.2 {
catchsql {ROLLBACK TO def}
- } {1 {cannot rollback savepoint - SQL statements in progress}}
+ } {0 {}}
+ do_test savepoint-5.3.2.3 {
+ set rc [catch {seek $fd 0; read $fd} res]
+ set rc
+ } {1}
do_test savepoint-5.3.3 {
catchsql {RELEASE def}
} {0 {}}
list $a $count
} {32 64}
-#---------------------------------------------------------------------------
-# These tests, shared2.2.*, test the outcome when data is added to or
-# removed from a table due to a rollback while a read-uncommitted
-# cursor is scanning it.
-#
-do_test shared2-2.1 {
- execsql {
- INSERT INTO numbers VALUES(1, 'Medium length text field');
- INSERT INTO numbers VALUES(2, 'Medium length text field');
- INSERT INTO numbers VALUES(3, 'Medium length text field');
- INSERT INTO numbers VALUES(4, 'Medium length text field');
- BEGIN;
- DELETE FROM numbers WHERE (a%2)=0;
- } db1
- set res [list]
- db2 eval {
- SELECT a FROM numbers ORDER BY a;
- } {
- lappend res $a
- if {$a==3} {
- execsql {ROLLBACK} db1
- }
- }
- set res
-} {1 3 4}
-do_test shared2-2.2 {
- execsql {
- BEGIN;
- INSERT INTO numbers VALUES(5, 'Medium length text field');
- INSERT INTO numbers VALUES(6, 'Medium length text field');
- } db1
- set res [list]
- db2 eval {
- SELECT a FROM numbers ORDER BY a;
- } {
- lappend res $a
- if {$a==5} {
- execsql {ROLLBACK} db1
- }
- }
- set res
-} {1 2 3 4 5}
db1 close
db2 close