diff --git a/manifest b/manifest index e87b6d1389..d46ad5d84c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Make\ssure\svacuum.test\scloses\sall\sfiles.\s(CVS\s1777) -D 2004-06-30T10:54:30 +C When\sa\sstatement\scauses\sa\sROLLBACK\sdue\sto\san\sON\sCONFLICT\sclause,\sother\sactive\nVMs\sabort.\s(CVS\s1778) +D 2004-06-30T11:14:19 F Makefile.in cb7a9889c38723f72b2506c4236ff30a05ff172b F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -75,9 +75,9 @@ F src/util.c b267d0fe10cffa3301fe9fab6592a6808a38bce6 F src/vacuum.c b8546f4921719458cc537b9e736df52a8256399c F src/vdbe.c 4629151c9995b8b6a895c42de8808df1969bdcc7 F src/vdbe.h 75b241c02431b9c0f16eaa9cdbb34146c6287f52 -F src/vdbeInt.h d83fd7389838453d8392915c21f432014afc99cf -F src/vdbeapi.c ba3722f45db3d3c3509bf5d24f4f868f4c64449d -F src/vdbeaux.c f9b1b3d4d2f1c31f6db1ae1536e17e4eb5454205 +F src/vdbeInt.h 7160653a006b6d2c4a00d204112a095bdf842ab6 +F src/vdbeapi.c 7c3c3d818fad427881b65c51999d06bf393ebeaf +F src/vdbeaux.c f97b4b5e922fe74152e084bcea7b4468156bde50 F src/vdbemem.c 053f8adcb644bca1c1e4ad08f4016cb7ee6bf1b8 F src/where.c 6507074d8ce3f78e7a4cd33f667f11e62020553e F test/all.test 3b692eb43583b52c99c344b2fa8934512d179016 @@ -147,6 +147,7 @@ F test/printf.test 5ed2e033a0b47f901764096bf1907915d6e39406 F test/progress.test 76c722f090b1ccb575e7e4e203a71608c5763beb x F test/quick.test bbe4abf7f434d71c0de26626c8cbb4858e1bcb18 F test/quote.test 08f23385c685d3dc7914ec760d492cacea7f6e3d +F test/rollback.test 4097328d44510277244ef4fa51b22b2f11d7ef4c F test/rowid.test b3d059f5c8d8874fa1c31030e0636f67405d20ea F test/select1.test 813a270ac7996b31ff228e8109cd2d1e8c3fa255 F test/select2.test 91a2225926039b0d1687840735c284dbbf89f0bc @@ -232,7 +233,7 @@ F www/tclsqlite.tcl 19191cf2a1010eaeff74c51d83fd5f5a4d899075 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 563ba3ac02f64da27ab17f3edbe8e56bfd0293fb F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 152e9940b919a53fcd0da4091dbf75ab8ef15b38 -R 7c0d14b9c00314801ef156d50cb14232 -U danielk1977 -Z 744e63435b1a53bb66bf937c6227be06 +P 4077f9a30b0c30a8749a596031aa4f7adc3a4891 +R c74b8042375ac1ecced768631e1e7c90 +U drh +Z bbd3e84a33ffc460275952232aa91883 diff --git a/manifest.uuid b/manifest.uuid index 8c80df17ce..3ab60f3642 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -4077f9a30b0c30a8749a596031aa4f7adc3a4891 \ No newline at end of file +0fedf74e30026afe2c8caacff3d62cf5c1b1f528 \ No newline at end of file diff --git a/src/vdbeInt.h b/src/vdbeInt.h index 9ccb4d4272..5a5a5d34af 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -342,8 +342,9 @@ struct Vdbe { u8 resOnStack; /* True if there are result values on the stack */ u8 explain; /* True if EXPLAIN present on SQL command */ u8 autoCommitOn; /* True if autocommit got turned on by this program */ - int nChange; /* Number of db changes made since last reset */ u8 changeCntOn; /* True to update the change-counter */ + u8 aborted; /* True if ROLLBACK in another VM causes an abort */ + int nChange; /* Number of db changes made since last reset */ }; /* diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 6935ca7d1a..6f0fbb20a9 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -149,6 +149,9 @@ int sqlite3_step(sqlite3_stmt *pStmt){ if( p->magic!=VDBE_MAGIC_RUN ){ return SQLITE_MISUSE; } + if( p->aborted ){ + return SQLITE_ABORT; + } db = p->db; if( sqlite3SafetyOn(db) ){ p->rc = SQLITE_MISUSE; diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 8bed685871..8e0522ff37 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1090,6 +1090,20 @@ static int vdbeCommit(sqlite *db){ return rc; } +/* +** Find every active VM other than pVdbe and change its status to +** aborted. This happens when on VM causes a rollback. +*/ +static void abortOtherActiveVdbes(Vdbe *pVdbe){ + Vdbe *pOther; + for(pOther=pVdbe->db->pVdbe; pOther; pOther=pOther->pNext){ + if( pOther==pVdbe ) continue; + if( pOther->magic!=VDBE_MAGIC_RUN || pOther->pc<0 ) continue; + closeAllCursors(pOther); + pOther->aborted = 1; + } +} + /* ** This routine checks that the sqlite3.activeVdbeCnt count variable ** matches the number of vdbe's in the list sqlite3.pVdbe that are @@ -1183,6 +1197,7 @@ int sqlite3VdbeReset(Vdbe *p){ }else{ xFunc = sqlite3BtreeRollback; db->autoCommit = 1; + abortOtherActiveVdbes(p); } } p->autoCommitOn = 0; @@ -1245,6 +1260,7 @@ int sqlite3VdbeReset(Vdbe *p){ } #endif p->magic = VDBE_MAGIC_INIT; + p->aborted = 0; return p->rc; } diff --git a/test/rollback.test b/test/rollback.test new file mode 100644 index 0000000000..af1aedadbd --- /dev/null +++ b/test/rollback.test @@ -0,0 +1,78 @@ +# 2004 June 30 +# +# The author disclaims copyright to this source code. In place of +# a legal notice, here is a blessing: +# +# 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. +# +#*********************************************************************** +# This file implements regression tests for SQLite library. The +# focus of this file is verifying that a rollback in one statement +# caused by an ON CONFLICT ROLLBACK clause aborts any other pending +# statements. +# +# $Id: rollback.test,v 1.1 2004/06/30 11:14:19 drh Exp $ + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + +db close +set DB [sqlite3 db test.db] + +do_test rollback-1.1 { + execsql { + CREATE TABLE t1(a); + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + INSERT INTO t1 VALUES(3); + INSERT INTO t1 VALUES(4); + SELECT * FROM t1; + } +} {1 2 3 4} + +do_test rollback-1.2 { + execsql { + CREATE TABLE t3(a unique on conflict rollback); + INSERT INTO t3 SELECT a FROM t1; + BEGIN; + INSERT INTO t1 SELECT * FROM t1; + } +} {} +do_test rollback-1.3 { + set STMT [sqlite3_prepare $DB "SELECT a FROM t1" -1 TAIL] + sqlite3_step $STMT +} {SQLITE_ROW} + +# This causes a ROLLBACK, which deletes the table out from underneath the +# SELECT statement. +# +do_test rollback-1.4 { + catchsql { + INSERT INTO t3 SELECT a FROM t1; + } +} {1 {column a is not unique}} + +# Try to continue with the SELECT statement +# +do_test rollback-1.5 { + sqlite3_step $STMT +} {SQLITE_ABORT} + +# Restart the SELECT statement +# +do_test rollback-1.6 { + sqlite3_reset $STMT +} {} +do_test rollback-1.7 { + sqlite3_step $STMT +} {SQLITE_ROW} +do_test rollback-1.8 { + sqlite3_step $STMT +} {SQLITE_ROW} +do_test rollback-1.9 { + sqlite3_finalize $STMT +} {SQLITE_OK} + +finish_test