diff options
author | danielk1977 <danielk1977@noemail.net> | 2004-05-31 08:26:49 +0000 |
---|---|---|
committer | danielk1977 <danielk1977@noemail.net> | 2004-05-31 08:26:49 +0000 |
commit | 1d850a72c265ad9368b322ca39125c9b0c3d8509 (patch) | |
tree | 3ae42a002f87796ecea58f7094dea2096fa4439a | |
parent | a19b775db9b2f12263e54cf0f64162ced526fff5 (diff) | |
download | sqlite-1d850a72c265ad9368b322ca39125c9b0c3d8509.tar.gz sqlite-1d850a72c265ad9368b322ca39125c9b0c3d8509.zip |
Replace OP_Begin, OP_Commit and OP_Rollback with OP_AutoCommit. (CVS 1500)
FossilOrigin-Name: b8ed812c92f2dbb4431d45aeb41646ceb53e0cbc
-rw-r--r-- | manifest | 56 | ||||
-rw-r--r-- | manifest.uuid | 2 | ||||
-rw-r--r-- | src/btree.c | 16 | ||||
-rw-r--r-- | src/btree.h | 4 | ||||
-rw-r--r-- | src/build.c | 94 | ||||
-rw-r--r-- | src/main.c | 3 | ||||
-rw-r--r-- | src/pager.c | 6 | ||||
-rw-r--r-- | src/pragma.c | 4 | ||||
-rw-r--r-- | src/sqliteInt.h | 5 | ||||
-rw-r--r-- | src/test3.c | 86 | ||||
-rw-r--r-- | src/trigger.c | 10 | ||||
-rw-r--r-- | src/vacuum.c | 28 | ||||
-rw-r--r-- | src/vdbe.c | 115 | ||||
-rw-r--r-- | src/vdbeInt.h | 1 | ||||
-rw-r--r-- | src/vdbeapi.c | 6 | ||||
-rw-r--r-- | src/vdbeaux.c | 111 | ||||
-rw-r--r-- | test/attach.test | 10 | ||||
-rw-r--r-- | test/attach2.test | 8 | ||||
-rw-r--r-- | test/conflict.test | 6 | ||||
-rw-r--r-- | test/hook.test | 6 | ||||
-rw-r--r-- | test/lock.test | 15 | ||||
-rw-r--r-- | test/misc1.test | 4 | ||||
-rwxr-xr-x | test/progress.test | 16 | ||||
-rw-r--r-- | test/trans.test | 4 |
24 files changed, 376 insertions, 240 deletions
@@ -1,5 +1,5 @@ -C Add\s3-byte\sand\s6-byte\sinteger\sserial\stypes.\s\sThis\smakes\sdatabases\ssmaller\nand\sfaster.\s\sShould\swe\sgo\sahead\sand\sadd\s5-\sand\s7-byte\sinteger\stypes\stoo?\s(CVS\s1499) -D 2004-05-30T21:14:59 +C Replace\sOP_Begin,\sOP_Commit\sand\sOP_Rollback\swith\sOP_AutoCommit.\s(CVS\s1500) +D 2004-05-31T08:26:49 F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -24,9 +24,9 @@ F sqlite.def fc4f5734786fe4743cfe2aa98eb2da4b089edb5f F sqlite.pc.in 30552343140c53304c2a658c080fbe810cd09ca2 F src/attach.c c315c58cb16fd6e913b3bfa6412aedecb4567fa5 F src/auth.c 5c2f0bea4729c98c2be3b69d6b466fc51448fe79 -F src/btree.c 3b7ddd0dd491c265227a045b9575786c7947cf49 -F src/btree.h 512706898e248fc5ec9237b9b535cffb9b53f9cd -F src/build.c fd36c4a603e23df35aa7f57772d965e1865e39e0 +F src/btree.c 07d0d93ba0e6f54a0f67e665d264b0bc6ab70edb +F src/btree.h 61d670f418fa6bd88b6d2731f05fcf8b19d3ec45 +F src/build.c df54499bdf0eced593e5074fae25f6d73ebb1411 F src/date.c 0eb922af5c5f5e2455f8dc2f98023ed3e04a857e F src/delete.c 72f8febf6170cda830f509c8f9dffbed3df3596c F src/encode.c a876af473d1d636faa3dca51c7571f2e007eea37 @@ -36,7 +36,7 @@ F src/hash.c 440c2f8cb373ee1b4e13a0988489c7cd95d55b6f F src/hash.h 762d95f1e567664d1eafc1687de755626be962fb F src/insert.c 0c7966dba4cd5698e393e824f162d520e96b1978 F src/legacy.c ad23746f15f67e34577621b1875f639c94839e1f -F src/main.c 79f8142ee2dbf0e3b1f60251515fcf4a1339e784 +F src/main.c 4f1dd19db1a37c8617142ef053ed4398d9069daf F src/md5.c d2c738fedfb27f73cefcf2b0ac1f9f21894b073e F src/os.h ab42f4a7c4c716f26b988e759b6e12085a3bfc67 F src/os_common.h 744286a27de55c52f1b18921e8d17abbf7fafc0f @@ -46,39 +46,39 @@ F src/os_unix.c 585665eccd31a9bb4dc090bc6b5e29d8d42899f0 F src/os_unix.h 426e1480f0847a7f8ba22aa9ac5115520875610b F src/os_win.c 92b51a38437b98d8aa3ac05b57c71e1d1092e5be F src/os_win.h 5d41af24caaef6c13a2d8e2399caa1c57d45c84d -F src/pager.c 6ff6b906427d4824099140776cb8768f922f3dc5 +F src/pager.c 048872f1ccd27e4c17d77098eb6e86990a7a9b88 F src/pager.h 78a00ac280899bcba1a89dc51585dcae6b7b3253 F src/parse.y facaa7d07885fb9d53ec8fd676705715d3942b0f -F src/pragma.c 84e778a73eb6a14c1a328d75f70355cb51c22803 +F src/pragma.c 7f432dee3c94460638df1e5fffeb59a560943d13 F src/printf.c ef750e8e2398ca7e8b58be991075f08c6a7f0e53 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3 F src/select.c 0297717eb7331604687c2e29c147d3a311359df1 F src/shell.c ed4d237b3e52a0a42512bfcc53530e46de20c28f F src/sqlite.h.in edc6408c7f53c2104f781a76b926036e17018ec9 -F src/sqliteInt.h 01f9250ee3a1ab681b7ed91ad2b3748c2f230521 +F src/sqliteInt.h 576c2d7828e538873c40da7b728c912c2b5a94d1 F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2 F src/tclsqlite.c b314f12760547e4ef090e055f1298f70627450d3 F src/test1.c 32934478366531503d634968db414df17cb38238 F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872 -F src/test3.c 32d35d15ac821f597a58353bb7b0141085259a24 +F src/test3.c 48f14101bde4be18b351a6db977cc30b349bf1c0 F src/test4.c 34848a9fd31aa65857b20a8bfc03aff77d8c3426 F src/test5.c 9a1f15133f6955f067c5246e564723b5f23ff221 F src/tokenize.c 50a87c7414de54a008427c9fed22e4e86efb6844 -F src/trigger.c 258ed8f9583c6b80e5af401cb9cce345c0c689c3 +F src/trigger.c 04b2c310d0d056b213609cab6df5fff03d5eaf88 F src/update.c 259f06e7b22c684b2d3dda54a18185892d6e9573 F src/utf.c f8604999a54483533ac20a63879074f01b0df384 F src/util.c 3b647719c0bece41491300b605cff96a7a26f03a -F src/vacuum.c 82ce1fc8ecc2e1aa284c13fe38446709f9936c63 -F src/vdbe.c 8c99c3c1e4b29b62a3e19e84b207b0fe84c45c46 +F src/vacuum.c 16d1b4ab976f19f01aa626bfdac9fee5e2cce03c +F src/vdbe.c 3cc9b3ab6c4e5b10168d56f09b6864ccb5b50f81 F src/vdbe.h e73f890e0f2a6c42b183d7d6937947930fe4fdeb -F src/vdbeInt.h c2bcd6e5a6e6a3753e4c5a368629c3a625719bfc -F src/vdbeapi.c 0c5d64c81871cb4fe5407e639604ee95738b6942 -F src/vdbeaux.c c7e66db2b52b3c816adbdec81581b5e7ad257639 +F src/vdbeInt.h 51d37798ba7bc5f2f767db0e3dbae31156ae9ff3 +F src/vdbeapi.c d43d36efeaf709bae71b743aaaee430e0b29cd1e +F src/vdbeaux.c 9cad713e47e6e684852dfc12ef6e326fb4a2ca76 F src/vdbemem.c 627d714c347f6af8092cc48ae1c06fd774a1ad9c F src/where.c 444a7c3a8b1eb7bba072e489af628555d21d92a4 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242 -F test/attach.test 0dd7cf9bf9bc915bce2da4fb616c4ea9c3da64af -F test/attach2.test 5472d442bb2ef1ee587e0ae7472bb68b52509a38 +F test/attach.test 379d5b1c6b907c682db293811fd8210715c42721 +F test/attach2.test 617583b73005638100721b4178c28d0b9df67494 F test/attach3.test d384ac2e59f305743f73aec4b3d97b36fa5c6975 F test/auth.test 95809b8f6a9bec18b94d28cafd03fe27d2f8a9e9 F test/bigfile.test ea904b853ce2d703b16c5ce90e2b54951bc1ae81 @@ -92,7 +92,7 @@ F test/btree5.test 8e5ff32c02e685d36516c6499add9375fe1377f2 F test/btree6.test a5ede6bfbbb2ec8b27e62813612c0f28e8f3e027 F test/capi2.test 8fb64e8ab7f78b8254cd4d04bb96822167f731b2 F test/capi3.test b6fe8a66d2ffe28d4faaaec154a143131e8ff631 -F test/conflict.test 0911bb2f079046914a6e9c3341b36658c4e2103e +F test/conflict.test 2cdd9a746831a18f425fabd075750dce6182951a F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2 F test/date.test aed5030482ebc02bd8d386c6c86a29f694ab068d F test/delete.test ddb1d4e172a01c0165804f82f81df556fb48a856 @@ -101,7 +101,7 @@ F test/enc2.test 8ab83839b73ce3a571b1396379f2f8ae3c895d74 F test/expr.test 8b62f3fcac64fbd5c3d43d7a7984245743dcbe65 F test/fkey1.test d65c824459916249bee501532d6154ddab0b5db7 F test/func.test b6d87075ff65babd6466b8a8dfc0d44f6a92df0c -F test/hook.test 1a67ce0cd64a6455d016962542f2822458dccc49 +F test/hook.test c4102c672d67f8fb60ea459842805abcba69a747 F test/in.test b92a2df9162e1cbd33c6449a29a05e6955b1741a F test/index.test ad3f479a3dc4a6d9105a2c88e3ee432498441c34 F test/insert.test 6ec324659656f4a86e4abfcf1a1fd2795ba6b603 @@ -114,13 +114,13 @@ F test/join2.test c97e4c5aa65dea462145529e58212a709b4722b8 F test/lastinsert.test 31382f88b9b0270333ac9e4a17f2c2f4732da718 F test/laststmtchanges.test cabd11bdfbaf73a4486c50b58297d9c2038ccc18 F test/limit.test 60d7f856ee7846f7130dee67f10f0e726cd70b5d -F test/lock.test 226ef831dad60ad4d200dc83e25479ba952aac7e +F test/lock.test 3dfd0f4f981f759ae1c07c19443e424dc9fdb133 F test/main.test 6a851b5992c4881a725a3d9647e629199df8de9d F test/malloc.test 4e19b96d9cd7d61f4826e6fce03849ad5ad526dd F test/memdb.test 6ece25c7c0e6500199d3662607a3edca081abb2a F test/memleak.test 4d5d374c8ea1fc5ac634aed58cac1047848ce65e F test/minmax.test 9dcf52f713b1b9e61d0a88a51eb8bb2e3c52d0ab -F test/misc1.test 2e1c0d592f082491984cccabfae213cb50fc574f +F test/misc1.test 508ef7287490900570054dfd853641ec4ef66cd6 F test/misc2.test 10c2ce26407d37411b96273e552d5095393732be F test/misc3.test eb488314990bfc0959221a1acc465013238bf168 F test/misuse.test 1095f26d1aed406c65e1d2eba651c4bb7c38cbff @@ -130,7 +130,7 @@ F test/pager.test 548968643d91c1c43a3a3eb1a232e9ca87b4069e F test/pager2.test 7ff175a28484fd324df9315dfe35f6fb159910ec F test/pragma.test 1b6792d4af550ca4973096d77fc278dd6c32c4dd F test/printf.test 46b3d07d59d871d0831b4a657f6dfcafe0574850 -F test/progress.test 701b6115c2613128ececdfe1398a1bd0e1a4cfb3 x +F test/progress.test 7542a6ac7894a1b7730c1f9a27f3f8b9388a4d25 x F test/quick.test 8800cd2f6b45ce2cafadb0e3d5161688c61c946a F test/quote.test 08f23385c685d3dc7914ec760d492cacea7f6e3d F test/rowid.test 863e6e75878cccf03d166fe52023f20e09508683 @@ -150,7 +150,7 @@ F test/tester.tcl fc10520db0d3ce4ef6a8b5ab91bd102fc3f4280a F test/thread1.test 53f050d5be6932d9430df7756edd379366508ff6 F test/threadtest1.c f7f896e62ed46feae1dc411114a48c15a0f82ee2 F test/threadtest2.c d94ca4114fd1504f7e0ae724bcd83d4b40931d86 -F test/trans.test 0cb8256daff1ae0da75321e00125338c6681158d +F test/trans.test 45fa0ed87ee487797ea6a30f3ec298a6618531b9 F test/trigger1.test 99b7cd9a568ac60aa04bbc3b9db9575ffa97709a F test/trigger2.test 0767ab30cb5a2c8402c8524f3d566b410b6f5263 F test/trigger3.test a95ccace88291449f5eae7139ec438a42f90654d @@ -204,7 +204,7 @@ F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P a0db15bba64af0c529d5be366659bca1165ff21b -R 915a168eb388cda740e119c94b1b9b85 -U drh -Z 7fdd86c94ca6358f07f558cb154c7ae7 +P e6685af815c4c0c7f09bb097a59a121862b865cf +R c1fe4dc87ffc77104224a068a0aafa41 +U danielk1977 +Z 668b27f088f428197bca6da249bb0086 diff --git a/manifest.uuid b/manifest.uuid index d0a9a6aae..481619f14 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -e6685af815c4c0c7f09bb097a59a121862b865cf
\ No newline at end of file +b8ed812c92f2dbb4431d45aeb41646ceb53e0cbc
\ No newline at end of file diff --git a/src/btree.c b/src/btree.c index 8057be79b..86b98d671 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.152 2004/05/30 20:46:09 drh Exp $ +** $Id: btree.c,v 1.153 2004/05/31 08:26:49 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to @@ -4183,3 +4183,17 @@ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ } return rc; } + +/* +** Return non-zero if a transaction is active. +*/ +int sqlite3BtreeIsInTrans(Btree *pBt){ + return (pBt && pBt->inTrans); +} + +/* +** Return non-zero if a statement transaction is active. +*/ +int sqlite3BtreeIsInStmt(Btree *pBt){ + return (pBt && pBt->inStmt); +} diff --git a/src/btree.h b/src/btree.h index 639e55bcd..c6c4f08bc 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.49 2004/05/30 20:46:09 drh Exp $ +** @(#) $Id: btree.h,v 1.50 2004/05/31 08:26:49 danielk1977 Exp $ */ #ifndef _BTREE_H_ #define _BTREE_H_ @@ -48,6 +48,8 @@ int sqlite3BtreeBeginStmt(Btree*); int sqlite3BtreeCommitStmt(Btree*); int sqlite3BtreeRollbackStmt(Btree*); int sqlite3BtreeCreateTable(Btree*, int*, int flags); +int sqlite3BtreeIsInTrans(Btree*); +int sqlite3BtreeIsInStmt(Btree*); const char *sqlite3BtreeGetFilename(Btree *); int sqlite3BtreeCopyFile(Btree *, Btree *); diff --git a/src/build.c b/src/build.c index 5699c5d3d..6aeb8cbd8 100644 --- a/src/build.c +++ b/src/build.c @@ -23,7 +23,7 @@ ** ROLLBACK ** PRAGMA ** -** $Id: build.c,v 1.200 2004/05/29 11:24:50 danielk1977 Exp $ +** $Id: build.c,v 1.201 2004/05/31 08:26:49 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -920,6 +920,15 @@ char sqlite3AffinityType(const char *zType, int nType){ ** 1 chance in 2^32. So we're safe enough. */ void sqlite3ChangeCookie(sqlite *db, Vdbe *v, int iDb){ + unsigned char r; + int *pSchemaCookie = &(db->aDb[iDb].schema_cookie); + + sqlite3Randomness(1, &r); + *pSchemaCookie = *pSchemaCookie + r + 1; + db->flags |= SQLITE_InternChanges; + sqlite3VdbeAddOp(v, OP_Integer, *pSchemaCookie, 0); + sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 0); +/* if( db->next_cookie==db->aDb[0].schema_cookie ){ unsigned char r; sqlite3Randomness(1, &r); @@ -928,6 +937,7 @@ void sqlite3ChangeCookie(sqlite *db, Vdbe *v, int iDb){ sqlite3VdbeAddOp(v, OP_Integer, db->next_cookie, 0); sqlite3VdbeAddOp(v, OP_SetCookie, iDb, 0); } +*/ } /* @@ -1104,7 +1114,7 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){ } sqlite3VdbeOp3(v, OP_MakeRecord, 5, 0, "tttit", P3_STATIC); sqlite3VdbeAddOp(v, OP_PutIntKey, 0, 0); - if( !p->iDb ){ + if( p->iDb!=1 ){ sqlite3ChangeCookie(db, v, p->iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); @@ -1830,7 +1840,6 @@ void sqlite3CreateIndex( int n; Vdbe *v; int lbl1, lbl2; - int i; v = sqlite3GetVdbe(pParse); if( v==0 ) goto exit_create_index; @@ -2165,19 +2174,17 @@ void sqlite3SrcListDelete(SrcList *pList){ */ void sqlite3BeginTransaction(Parse *pParse, int onError){ sqlite *db; + Vdbe *v; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite3_malloc_failed ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "BEGIN", 0, 0) ) return; - if( db->flags & SQLITE_InTrans ){ - sqlite3ErrorMsg(pParse, "cannot start a transaction within a transaction"); - return; - } - sqlite3BeginWriteOperation(pParse, 0, 0); - if( !pParse->explain ){ - db->flags |= SQLITE_InTrans; - db->onError = onError; - } + + v = sqlite3GetVdbe(pParse); + if( !v ) return; + sqlite3VdbeAddOp(v, OP_AutoCommit, 0, 0); + + /* FIX ME: Need to deal with onError */ } /* @@ -2185,20 +2192,15 @@ void sqlite3BeginTransaction(Parse *pParse, int onError){ */ void sqlite3CommitTransaction(Parse *pParse){ sqlite *db; + Vdbe *v; if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite3_malloc_failed ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "COMMIT", 0, 0) ) return; - if( (db->flags & SQLITE_InTrans)==0 ){ - sqlite3ErrorMsg(pParse, "cannot commit - no transaction is active"); - return; - } - if( !pParse->explain ){ - db->flags &= ~SQLITE_InTrans; - } - sqlite3EndWriteOperation(pParse); - if( !pParse->explain ){ - db->onError = OE_Default; + + v = sqlite3GetVdbe(pParse); + if( v ){ + sqlite3VdbeAddOp(v, OP_AutoCommit, 1, 0); } } @@ -2212,17 +2214,10 @@ void sqlite3RollbackTransaction(Parse *pParse){ if( pParse==0 || (db=pParse->db)==0 || db->aDb[0].pBt==0 ) return; if( pParse->nErr || sqlite3_malloc_failed ) return; if( sqlite3AuthCheck(pParse, SQLITE_TRANSACTION, "ROLLBACK", 0, 0) ) return; - if( (db->flags & SQLITE_InTrans)==0 ){ - sqlite3ErrorMsg(pParse, "cannot rollback - no transaction is active"); - return; - } + v = sqlite3GetVdbe(pParse); if( v ){ - sqlite3VdbeAddOp(v, OP_Rollback, 0, 0); - } - if( !pParse->explain ){ - db->flags &= ~SQLITE_InTrans; - db->onError = OE_Default; + sqlite3VdbeAddOp(v, OP_AutoCommit, 1, 1); } } @@ -2235,9 +2230,9 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ Vdbe *v = sqlite3GetVdbe(pParse); assert( iDb>=0 && iDb<db->nDb ); assert( db->aDb[iDb].pBt!=0 ); - if( iDb!=1 && !DbHasProperty(db, iDb, DB_Cookie) ){ + if( iDb!=1 && (iDb>63 || !(pParse->cookieMask & ((u64)1<<iDb))) ){ sqlite3VdbeAddOp(v, OP_VerifyCookie, iDb, db->aDb[iDb].schema_cookie); - DbSetProperty(db, iDb, DB_Cookie); + pParse->cookieMask |= ((u64)1<<iDb); } } @@ -2260,21 +2255,15 @@ void sqlite3CodeVerifySchema(Parse *pParse, int iDb){ ** specified auxiliary database and the temp database are made writable. */ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ - Vdbe *v; - sqlite *db = pParse->db; - if( DbHasProperty(db, iDb, DB_Locked) ) return; - v = sqlite3GetVdbe(pParse); + Vdbe *v = sqlite3GetVdbe(pParse); if( v==0 ) return; - if( !db->aDb[iDb].inTrans ){ - sqlite3VdbeAddOp(v, OP_Transaction, iDb, 0); - DbSetProperty(db, iDb, DB_Locked); - sqlite3CodeVerifySchema(pParse, iDb); - if( iDb!=1 ){ - sqlite3BeginWriteOperation(pParse, setStatement, 1); - } - }else if( setStatement ){ + sqlite3VdbeAddOp(v, OP_Transaction, iDb, 0); + sqlite3CodeVerifySchema(pParse, iDb); + if( setStatement ){ sqlite3VdbeAddOp(v, OP_Statement, iDb, 0); - DbSetProperty(db, iDb, DB_Locked); + } + if( iDb!=1 ){ + sqlite3BeginWriteOperation(pParse, setStatement, 1); } } @@ -2289,15 +2278,6 @@ void sqlite3BeginWriteOperation(Parse *pParse, int setStatement, int iDb){ ** call to sqlite3EndWriteOperation() at the conclusion of the statement. */ void sqlite3EndWriteOperation(Parse *pParse){ - Vdbe *v; - sqlite *db = pParse->db; - if( pParse->trigStack ) return; /* if this is in a trigger */ - v = sqlite3GetVdbe(pParse); - if( v==0 ) return; - if( db->flags & SQLITE_InTrans ){ - /* A BEGIN has executed. Do not commit until we see an explicit - ** COMMIT statement. */ - }else{ - sqlite3VdbeAddOp(v, OP_Commit, 0, 0); - } + /* Delete me! */ + return; } diff --git a/src/main.c b/src/main.c index b3fbebc70..af8e74b80 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.196 2004/05/29 10:23:19 danielk1977 Exp $ +** $Id: main.c,v 1.197 2004/05/31 08:26:49 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -1020,6 +1020,7 @@ static int openDatabase( db->nDb = 2; db->aDb = db->aDbStatic; db->enc = def_enc; + db->autoCommit = 1; /* db->flags |= SQLITE_ShortColNames; */ sqlite3HashInit(&db->aFunc, SQLITE_HASH_STRING, 0); sqlite3HashInit(&db->aCollSeq, SQLITE_HASH_STRING, 0); diff --git a/src/pager.c b/src/pager.c index b5315e8f5..d2b84b97b 100644 --- a/src/pager.c +++ b/src/pager.c @@ -18,7 +18,7 @@ ** file simultaneously, or one process from reading the database while ** another is writing. ** -** @(#) $Id: pager.c,v 1.108 2004/05/14 01:58:13 drh Exp $ +** @(#) $Id: pager.c,v 1.109 2004/05/31 08:26:49 danielk1977 Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" @@ -865,7 +865,7 @@ end_stmt_playback: void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){ if( mxPage>=0 ){ pPager->noSync = pPager->tempFile; - if( pPager->noSync==0 ) pPager->needSync = 0; + if( pPager->noSync ) pPager->needSync = 0; }else{ pPager->noSync = 1; mxPage = -mxPage; @@ -904,7 +904,7 @@ void sqlite3pager_set_cachesize(Pager *pPager, int mxPage){ void sqlite3pager_set_safety_level(Pager *pPager, int level){ pPager->noSync = level==1 || pPager->tempFile; pPager->fullSync = level==3 && !pPager->tempFile; - if( pPager->noSync==0 ) pPager->needSync = 0; + if( pPager->noSync ) pPager->needSync = 0; } /* diff --git a/src/pragma.c b/src/pragma.c index 1c50d37aa..d80005b41 100644 --- a/src/pragma.c +++ b/src/pragma.c @@ -11,7 +11,7 @@ ************************************************************************* ** This file contains code used to implement the PRAGMA command. ** -** $Id: pragma.c,v 1.34 2004/05/29 11:24:50 danielk1977 Exp $ +** $Id: pragma.c,v 1.35 2004/05/31 08:26:49 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -93,7 +93,7 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){ sqlite *db = pParse->db; if( db->temp_store==ts ) return SQLITE_OK; if( db->aDb[1].pBt!=0 ){ - if( db->flags & SQLITE_InTrans ){ + if( !db->autoCommit ){ sqlite3ErrorMsg(pParse, "temporary storage cannot be changed " "from within a transaction"); return SQLITE_ERROR; diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f1d13b52f..9abf2d301 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.261 2004/05/29 02:37:19 danielk1977 Exp $ +** @(#) $Id: sqliteInt.h,v 1.262 2004/05/31 08:26:49 danielk1977 Exp $ */ #include "config.h" #include "sqlite.h" @@ -389,6 +389,7 @@ struct sqlite { u8 busy; /* TRUE if currently initializing */ } init; struct Vdbe *pVdbe; /* List of active virtual machines */ + int activeVdbeCnt; /* Number of vdbes currently executing */ void (*xTrace)(void*,const char*); /* Trace function */ void *pTraceArg; /* Argument to the trace function */ #ifndef SQLITE_OMIT_AUTHORIZATION @@ -406,6 +407,7 @@ struct sqlite { char *zErrMsg; /* Most recent error message (UTF-8 encoded) */ void *zErrMsg16; /* Most recent error message (UTF-16 encoded) */ u8 enc; /* Text encoding for this database. */ + u8 autoCommit; /* The auto-commit flag. */ }; /* @@ -989,6 +991,7 @@ struct Parse { const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */ Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */ TriggerStack *trigStack; /* Trigger actions being coded */ + u64 cookieMask; /* Bitmask of schema verified databases */ }; /* diff --git a/src/test3.c b/src/test3.c index a402b3146..5c03c7a07 100644 --- a/src/test3.c +++ b/src/test3.c @@ -13,7 +13,7 @@ ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** -** $Id: test3.c,v 1.39 2004/05/30 20:46:09 drh Exp $ +** $Id: test3.c,v 1.40 2004/05/31 08:26:49 danielk1977 Exp $ */ #include "sqliteInt.h" #include "pager.h" @@ -192,6 +192,87 @@ static int btree_commit( } /* +** Usage: btree_begin_statement ID +** +** Start a new statement transaction +*/ +static int btree_begin_statement( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; + rc = sqlite3BtreeBeginStmt(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: btree_rollback_statement ID +** +** Rollback changes +*/ +static int btree_rollback_statement( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; + rc = sqlite3BtreeRollbackStmt(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* +** Usage: btree_commit_statement ID +** +** Commit all changes +*/ +static int btree_commit_statement( + void *NotUsed, + Tcl_Interp *interp, /* The TCL interpreter that invoked this command */ + int argc, /* Number of arguments */ + const char **argv /* Text of each argument */ +){ + Btree *pBt; + int rc; + if( argc!=2 ){ + Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], + " ID\"", 0); + return TCL_ERROR; + } + if( Tcl_GetInt(interp, argv[1], (int*)&pBt) ) return TCL_ERROR; + rc = sqlite3BtreeCommitStmt(pBt); + if( rc!=SQLITE_OK ){ + Tcl_AppendResult(interp, errorName(rc), 0); + return TCL_ERROR; + } + return TCL_OK; +} + +/* ** Usage: btree_create_table ID FLAGS ** ** Create a new table in the database @@ -1257,6 +1338,9 @@ int Sqlitetest3_Init(Tcl_Interp *interp){ { "btree_integrity_check", (Tcl_CmdProc*)btree_integrity_check }, { "btree_breakpoint", (Tcl_CmdProc*)btree_breakpoint }, { "btree_varint_test", (Tcl_CmdProc*)btree_varint_test }, + { "btree_begin_statement", (Tcl_CmdProc*)btree_begin_statement }, + { "btree_commit_statement", (Tcl_CmdProc*)btree_commit_statement }, + { "btree_rollback_statement", (Tcl_CmdProc*)btree_rollback_statement }, }; int i; diff --git a/src/trigger.c b/src/trigger.c index bb4499847..20f71b57d 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -231,8 +231,8 @@ void sqlite3FinishTrigger( sqlite3VdbeChangeP3(v, addr+2, nt->name, 0); sqlite3VdbeChangeP3(v, addr+3, nt->table, 0); sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n); - if( nt->iDb==0 ){ - sqlite3ChangeCookie(db, v, 0); + if( nt->iDb!=0 ){ + sqlite3ChangeCookie(db, v, nt->iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3EndWriteOperation(pParse); @@ -488,8 +488,8 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){ sqlite3OpenMasterTable(v, pTrigger->iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger); sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0); - if( pTrigger->iDb==0 ){ - sqlite3ChangeCookie(db, v, 0); + if( pTrigger->iDb!=1 ){ + sqlite3ChangeCookie(db, v, pTrigger->iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3EndWriteOperation(pParse); @@ -711,6 +711,7 @@ int sqlite3CodeRowTrigger( ){ Trigger * pTrigger; TriggerStack * pTriggerStack; + u64 cookieMask = pParse->cookieMask; assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE); assert(tr_tm == TK_BEFORE || tr_tm == TK_AFTER ); @@ -782,6 +783,7 @@ int sqlite3CodeRowTrigger( pTrigger = pTrigger->pNext; } + pParse->cookieMask = cookieMask; return 0; } diff --git a/src/vacuum.c b/src/vacuum.c index be47ee938..ff0a5b4fb 100644 --- a/src/vacuum.c +++ b/src/vacuum.c @@ -14,7 +14,7 @@ ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** -** $Id: vacuum.c,v 1.18 2004/05/29 10:43:07 danielk1977 Exp $ +** $Id: vacuum.c,v 1.19 2004/05/31 08:26:49 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -96,11 +96,12 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite *db){ int nFilename; /* number of characters in zFilename[] */ char *zTemp = 0; /* a temporary file in same directory as zFilename */ int i; /* Loop counter */ + Btree *pTemp; char *zSql = 0; sqlite3_stmt *pStmt = 0; - if( db->flags & SQLITE_InTrans ){ + if( !db->autoCommit ){ sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction", (char*)0); rc = SQLITE_ERROR; @@ -189,20 +190,15 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite *db){ ** opened for writing. This way, the SQL transaction used to create the ** temporary database never needs to be committed. */ - - /* FIX ME: The above will be the case shortly. But for now, a transaction - ** will have been started on the main database file by the 'BEGIN'. - */ -/* - rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt); - if( rc!=SQLITE_OK ) goto end_of_vacuum; -*/ - - if( db->aDb[db->nDb-1].inTrans ){ - Btree *pTemp = db->aDb[db->nDb-1].pBt; + pTemp = db->aDb[db->nDb-1].pBt; + if( sqlite3BtreeIsInTrans(pTemp) ){ Btree *pMain = db->aDb[0].pBt; u32 meta; + assert( 0==sqlite3BtreeIsInTrans(pMain) ); + rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt); + if( rc!=SQLITE_OK ) goto end_of_vacuum; + /* Copy Btree meta values 3 and 4. These correspond to SQL layer meta ** values 2 and 3, the default values of a couple of pragmas. */ @@ -216,13 +212,7 @@ int sqlite3RunVacuum(char **pzErrMsg, sqlite *db){ if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeCopyFile(pMain, pTemp); - - /* FIX ME: Remove the main btree from the transaction so that it is not - ** rolled back. This won't be required once the new 'auto-commit' - ** model is in place. - */ rc = sqlite3BtreeCommit(pMain); - db->aDb[0].inTrans = 0; } end_of_vacuum: diff --git a/src/vdbe.c b/src/vdbe.c index 5c20d830b..787b0eeff 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.350 2004/05/30 21:14:59 drh Exp $ +** $Id: vdbe.c,v 1.351 2004/05/31 08:26:49 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -2196,9 +2196,40 @@ case OP_MakeRecord: { */ case OP_Statement: { int i = pOp->p1; - if( i>=0 && i<db->nDb && db->aDb[i].pBt && db->aDb[i].inTrans==1 ){ - rc = sqlite3BtreeBeginStmt(db->aDb[i].pBt); - if( rc==SQLITE_OK ) db->aDb[i].inTrans = 2; + Btree *pBt; + if( i>=0 && i<db->nDb && (pBt = db->aDb[i].pBt) && !(db->autoCommit) ){ + assert( sqlite3BtreeIsInTrans(pBt) ); + if( !sqlite3BtreeIsInStmt(pBt) ){ + rc = sqlite3BtreeBeginStmt(pBt); + } + } + break; +} + +/* Opcode: AutoCommit P1 P2 * +** +** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll +** back any currently active btree transactions. +*/ +case OP_AutoCommit: { + u8 i = pOp->p1; + u8 rollback = pOp->p2; + + assert( i==1 || i==0 ); + assert( i==1 || rollback==0 ); + + if( i!=db->autoCommit ){ + db->autoCommit = i; + if( pOp->p2 ){ + sqlite3RollbackAll(db); + } + }else{ + sqlite3SetString(&p->zErrMsg, + (!i)?"cannot start a transaction within a transaction":( + (rollback)?"cannot rollback - no transaction is active": + "cannot commit - no transaction is active"), 0); + + rc = SQLITE_ERROR; } break; } @@ -2222,15 +2253,18 @@ case OP_Statement: { case OP_Transaction: { int busy = 1; int i = pOp->p1; + Btree *pBt; + assert( i>=0 && i<db->nDb ); - if( db->aDb[i].inTrans ) break; - while( db->aDb[i].pBt!=0 && busy ){ + pBt = db->aDb[i].pBt; + + if( sqlite3BtreeIsInTrans(pBt) ) break; + while( pBt && busy /* && !sqlite3BtreeIsInTrans(pBt) */ ){ rc = sqlite3BtreeBeginTrans(db->aDb[i].pBt); switch( rc ){ case SQLITE_BUSY: { if( db->xBusyCallback==0 ){ p->pc = pc; - p->undoTransOnError = 1; p->rc = SQLITE_BUSY; p->pTos = pTos; return SQLITE_BUSY; @@ -2245,7 +2279,6 @@ case OP_Transaction: { /* Fall thru into the next case */ } case SQLITE_OK: { - p->inTempTrans = 0; busy = 0; break; } @@ -2254,58 +2287,6 @@ case OP_Transaction: { } } } - db->aDb[i].inTrans = 1; - p->undoTransOnError = 1; - break; -} - -/* Opcode: Commit * * * -** -** Cause all modifications to the database that have been made since the -** last Transaction to actually take effect. No additional modifications -** are allowed until another transaction is started. The Commit instruction -** deletes the journal file and releases the write lock on the database. -** A read lock continues to be held if there are still cursors open. -*/ -case OP_Commit: { - int i; - if( db->xCommitCallback!=0 ){ - if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; - if( db->xCommitCallback(db->pCommitArg)!=0 ){ - rc = SQLITE_CONSTRAINT; - } - if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse; - } - for(i=0; rc==SQLITE_OK && i<db->nDb; i++){ - if( db->aDb[i].inTrans ){ - rc = sqlite3BtreeCommit(db->aDb[i].pBt); - db->aDb[i].inTrans = 0; - } - } - if( rc==SQLITE_OK ){ - sqlite3CommitInternalChanges(db); - }else{ - sqlite3RollbackAll(db); - } - break; -} - -/* Opcode: Rollback P1 * * -** -** Cause all modifications to the database that have been made since the -** last Transaction to be undone. The database is restored to its state -** before the Transaction opcode was executed. No additional modifications -** are allowed until another transaction is started. -** -** P1 is the index of the database file that is committed. An index of 0 -** is used for the main database and an index of 1 is used for the file used -** to hold temporary tables. -** -** This instruction automatically closes all cursors and releases both -** the read and write locks on the indicated database. -*/ -case OP_Rollback: { - sqlite3RollbackAll(db); break; } @@ -3568,12 +3549,16 @@ case OP_IdxRecno: { assert( pC->deferredMoveto==0 ); assert( pC->intKey==0 ); - rc = sqlite3VdbeIdxRowid(pCrsr, &rowid); - if( rc!=SQLITE_OK ){ - goto abort_due_to_error; + if( pC->nullRow ){ + pTos->flags = MEM_Null; + }else{ + rc = sqlite3VdbeIdxRowid(pCrsr, &rowid); + if( rc!=SQLITE_OK ){ + goto abort_due_to_error; + } + pTos->flags = MEM_Int; + pTos->i = rowid; } - pTos->flags = MEM_Int; - pTos->i = rowid; #if 0 /* Read the final 9 bytes of the key into buf[]. If the whole key is diff --git a/src/vdbeInt.h b/src/vdbeInt.h index d41dbdd3b..a7f0dbf75 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -307,7 +307,6 @@ struct Vdbe { int rc; /* Value to return */ unsigned uniqueCnt; /* Used by OP_MakeRecord when P2!=0 */ int errorAction; /* Recovery action to do in case of an error */ - int undoTransOnError; /* If error, either ROLLBACK or COMMIT */ int inTempTrans; /* True if temp database is transactioned */ int returnStack[100]; /* Return address stack for OP_Gosub & OP_Return */ int returnDepth; /* Next unused element in returnStack[] */ diff --git a/src/vdbeapi.c b/src/vdbeapi.c index 682d9a63e..56388fd71 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -168,6 +168,10 @@ int sqlite3_step(sqlite3_stmt *pStmt){ p->rc = SQLITE_MISUSE; return SQLITE_MISUSE; } + if( p->pc<0 ){ + db->activeVdbeCnt++; + p->pc = 0; + } if( p->explain ){ rc = sqlite3VdbeList(p); }else{ @@ -378,7 +382,7 @@ const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){ */ static int vdbeUnbind(Vdbe *p, int i){ Mem *pVar; - if( p->magic!=VDBE_MAGIC_RUN || p->pc!=0 ){ + if( p->magic!=VDBE_MAGIC_RUN || p->pc>=0 ){ sqlite3Error(p->db, SQLITE_MISUSE, 0); return SQLITE_MISUSE; } diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 55ced4b21..60e785361 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -659,12 +659,11 @@ void sqlite3VdbeMakeReady( } #endif p->pTos = &p->aStack[-1]; - p->pc = 0; + p->pc = -1; p->rc = SQLITE_OK; p->uniqueCnt = 0; p->returnDepth = 0; p->errorAction = OE_Abort; - p->undoTransOnError = 0; p->popStack = 0; p->explain |= isExplain; p->magic = VDBE_MAGIC_RUN; @@ -896,6 +895,32 @@ int sqlite3VdbeSetColName(Vdbe *p, int idx, const char *zName, int N){ return rc; } +/* +** This routine checks that the sqlite3.activeVdbeCnt count variable +** matches the number of vdbe's in the list sqlite3.pVdbe that are +** currently active. An assertion fails if the two counts do not match. +** +** This is a no-op if NDEBUG is defined. +*/ +#ifndef NDEBUG +static void checkActiveVdbeCnt(sqlite *db){ + Vdbe *p; + int cnt = 0; + + p = db->pVdbe; + while( p ){ + if( (p->magic==VDBE_MAGIC_RUN && p->pc>=0) || p->magic==VDBE_MAGIC_HALT ){ + cnt++; + } + p = p->pNext; + } + + assert( cnt==db->activeVdbeCnt ); +} +#else +#define checkActiveVdbeCnt(x) +#endif + /* ** Clean up a VDBE after execution but do not delete the VDBE just yet. ** Write any error messages into *pzErrMsg. Return the result code. @@ -906,10 +931,13 @@ int sqlite3VdbeSetColName(Vdbe *p, int idx, const char *zName, int N){ int sqlite3VdbeReset(Vdbe *p, char **pzErrMsg){ sqlite *db = p->db; int i; + int (*xFunc)(Btree *pBt) = 0; /* Function to call on each btree backend */ + int needXcommit = 0; if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){ sqlite3SetString(pzErrMsg, sqlite3_error_string(SQLITE_MISUSE), (char*)0); - sqlite3Error(p->db, SQLITE_MISUSE, sqlite3_error_string(SQLITE_MISUSE),0); + sqlite3Error(p->db, SQLITE_MISUSE, 0 ,0); + db->activeVdbeCnt--; return SQLITE_MISUSE; } if( p->zErrMsg ){ @@ -922,48 +950,61 @@ int sqlite3VdbeReset(Vdbe *p, char **pzErrMsg){ p->zErrMsg = 0; }else if( p->rc ){ sqlite3SetString(pzErrMsg, sqlite3_error_string(p->rc), (char*)0); - sqlite3Error(p->db, p->rc, "%s", sqlite3_error_string(p->rc) , 0); + sqlite3Error(p->db, p->rc, 0); }else{ sqlite3Error(p->db, SQLITE_OK, 0); } Cleanup(p); - if( p->rc!=SQLITE_OK ){ - switch( p->errorAction ){ - case OE_Abort: { - if( !p->undoTransOnError ){ - for(i=0; i<db->nDb; i++){ - if( db->aDb[i].pBt ){ - sqlite3BtreeRollbackStmt(db->aDb[i].pBt); - } - } - break; - } - /* Fall through to ROLLBACK */ - } - case OE_Rollback: { - sqlite3RollbackAll(db); - db->flags &= ~SQLITE_InTrans; - db->onError = OE_Default; - break; - } - default: { - if( p->undoTransOnError ){ - sqlite3RollbackAll(db); - db->flags &= ~SQLITE_InTrans; - db->onError = OE_Default; + + /* Figure out which function to call on the btree backends that + ** have active transactions. + */ + checkActiveVdbeCnt(db); + if( db->autoCommit && db->activeVdbeCnt==1 ){ + if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ + xFunc = sqlite3BtreeCommit; + needXcommit = 1; + }else{ + xFunc = sqlite3BtreeRollback; + } + }else{ + if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ + xFunc = sqlite3BtreeCommitStmt; + }else if( p->errorAction==OE_Abort ){ + xFunc = sqlite3BtreeRollbackStmt; + }else{ + xFunc = sqlite3BtreeRollback; + db->autoCommit = 1; + } + } + + for(i=0; xFunc && i<db->nDb; i++){ + Btree *pBt = db->aDb[i].pBt; + if( sqlite3BtreeIsInTrans(pBt) ){ + int rc; + if( db->xCommitCallback && needXcommit ){ + if( db->xCommitCallback(db->pCommitArg)!=0 ){ + p->rc = SQLITE_CONSTRAINT; + sqlite3Error(db, SQLITE_CONSTRAINT, 0); + xFunc = sqlite3BtreeRollback; } - break; + needXcommit = 0; } + rc = xFunc(pBt); + if( p->rc==SQLITE_OK ) p->rc = rc; } + } + + + if( p->rc!=SQLITE_OK ){ sqlite3RollbackInternalChanges(db); } - for(i=0; i<db->nDb; i++){ - if( db->aDb[i].pBt && db->aDb[i].inTrans==2 ){ - sqlite3BtreeCommitStmt(db->aDb[i].pBt); - db->aDb[i].inTrans = 1; - } + + if( (p->magic==VDBE_MAGIC_RUN && p->pc>=0) || p->magic==VDBE_MAGIC_HALT ){ + db->activeVdbeCnt--; } - assert( p->pTos<&p->aStack[p->pc] || sqlite3_malloc_failed==1 ); + + assert( p->pTos<&p->aStack[p->pc<0?0:p->pc] || sqlite3_malloc_failed==1 ); #ifdef VDBE_PROFILE { FILE *out = fopen("vdbe_profile.out", "a"); diff --git a/test/attach.test b/test/attach.test index 488f30eda..b5c84efba 100644 --- a/test/attach.test +++ b/test/attach.test @@ -12,7 +12,7 @@ # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # -# $Id: attach.test,v 1.18 2004/05/29 10:23:20 danielk1977 Exp $ +# $Id: attach.test,v 1.19 2004/05/31 08:26:49 danielk1977 Exp $ # set testdir [file dirname $argv0] @@ -347,6 +347,7 @@ do_test attach-3.7 { do_test attach-3.8 { execsql BEGIN execsql BEGIN db2 + execsql {UPDATE t2 SET x=0 WHERE 0} db2 catchsql {SELECT * FROM t2} } {1 {database is locked}} do_test attach-3.9 { @@ -364,6 +365,11 @@ do_test attach-3.12 { do_test attach-3.13 { catchsql {UPDATE t2 SET x=x+1 WHERE x=50} } {1 {database is locked}} + +# Change for version 3. Transaction is no longer rolled back +# for a locked database. +execsql {ROLLBACK} + do_test attach-3.14 { # Unable to reinitialize the schema tables because the aux database # is still locked. @@ -438,11 +444,13 @@ do_test attach-4.8 { execsql { ATTACH DATABASE 'test2.db' AS db2; INSERT INTO db2.t3 VALUES(13,14); +pragma vdbe_trace = on; SELECT * FROM db2.t4 UNION ALL SELECT * FROM main.t4; } } {db2.6 db2.13 main.11} do_test attach-4.9 { execsql { +pragma vdbe_trace = off; INSERT INTO main.t3 VALUES(15,16); SELECT * FROM db2.t4 UNION ALL SELECT * FROM main.t4; } diff --git a/test/attach2.test b/test/attach2.test index 8cc11aa2a..9c79b33a0 100644 --- a/test/attach2.test +++ b/test/attach2.test @@ -12,7 +12,7 @@ # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # -# $Id: attach2.test,v 1.9 2004/05/21 10:08:55 danielk1977 Exp $ +# $Id: attach2.test,v 1.10 2004/05/31 08:26:49 danielk1977 Exp $ # @@ -51,6 +51,7 @@ db eval {DETACH t2} do_test attach2-2.1 { # lock test2.db then try to attach it. Should get an error. db2 eval {BEGIN} + db2 eval {UPDATE t1 SET a = 0 WHERE 0} catchsql { ATTACH 'test2.db' AS t2; } @@ -77,6 +78,7 @@ do_test attach2-2.5 { do_test attach2-2.6 { # lock test2.db and try to read from it. should get an error. db2 eval BEGIN + db2 eval {UPDATE t1 SET a = 0 WHERE 0} catchsql { SELECT name FROM t2.sqlite_master; } @@ -108,6 +110,10 @@ do_test attach2-2.10 { do_test attach2-2.11 { # when the write failed in the previous test, the transaction should # have rolled back. + # + # Update for version 3: A transaction is no longer rolled back if a + # database is found to be busy. + execsql {rollback} db2 eval ROLLBACK execsql { SELECT * FROM t1 diff --git a/test/conflict.test b/test/conflict.test index 925c161fa..c2c3ec41d 100644 --- a/test/conflict.test +++ b/test/conflict.test @@ -13,7 +13,7 @@ # This file implements tests for the conflict resolution extension # to SQLite. # -# $Id: conflict.test,v 1.19 2003/08/05 13:13:39 drh Exp $ +# $Id: conflict.test,v 1.20 2004/05/31 08:26:49 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -57,6 +57,8 @@ foreach {i conf cmd t0 t1 t2} { 17 ABORT INSERT 1 {} 1 18 ROLLBACK INSERT 1 {} {} } { + if { $conf=={} } { + do_test conflict-1.$i { if {$conf!=""} {set conf "ON CONFLICT $conf"} set r0 [catch {execsql [subst { @@ -72,6 +74,8 @@ foreach {i conf cmd t0 t1 t2} { set r2 [execsql {SELECT x FROM t2}] list $r0 $r1 $r2 } [list $t0 $t1 $t2] + + } } # Create tables for the first group of tests. diff --git a/test/hook.test b/test/hook.test index d19dfaf8c..c037c04dc 100644 --- a/test/hook.test +++ b/test/hook.test @@ -15,7 +15,7 @@ # # sqlite_commit_hook # -# $Id: hook.test,v 1.3 2004/01/15 02:44:03 drh Exp $ +# $Id: hook.test,v 1.4 2004/05/31 08:26:49 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -65,7 +65,7 @@ do_test hook-3.5 { do_test hook-3.6 { set commit_cnt {} proc commit_hook {} { - set ::commit_cnt [execsql {SELECT * FROM t2}] + set ::commit_cnt [execsql {SELECT * FROM t2}] return 1 } catchsql { @@ -73,7 +73,7 @@ do_test hook-3.6 { } } {1 {constraint failed}} do_test hook-3.7 { - set commit_cnt + set ::commit_cnt } {1 2 2 3 3 4 4 5 5 6 6 7} do_test hook-3.8 { execsql {SELECT * FROM t2} diff --git a/test/lock.test b/test/lock.test index 4b30fd0bf..a68f1be24 100644 --- a/test/lock.test +++ b/test/lock.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script is database locks. # -# $Id: lock.test,v 1.20 2004/02/14 16:31:04 drh Exp $ +# $Id: lock.test,v 1.21 2004/05/31 08:26:49 danielk1977 Exp $ set testdir [file dirname $argv0] @@ -60,6 +60,7 @@ do_test lock-1.9 { } {2 1} do_test lock-1.10 { execsql {BEGIN TRANSACTION} + execsql {UPDATE t1 SET a = 0 WHERE 0} execsql {SELECT * FROM t1} } {2 1} do_test lock-1.11 { @@ -155,7 +156,10 @@ integrity_check lock-1.23 # do_test lock-2.1 { execsql {BEGIN TRANSACTION} - set r [catch {execsql {BEGIN TRANSACTION} db2} msg] + execsql {UPDATE t1 SET a = 0 WHERE 0} + execsql {BEGIN TRANSACTION} db2 + set r [catch {execsql {UPDATE t1 SET a = 0 WHERE 0} db2} msg] + execsql {ROLLBACK} db2 lappend r $msg } {1 {database is locked}} @@ -222,6 +226,7 @@ do_test lock-2.6 { } {0 {9 8} {1 2 3}} do_test lock-2.7 { execsql {BEGIN TRANSACTION} + execsql {UPDATE t1 SET a = 0 WHERE 0} proc callback {file count} { lappend ::callback_value $count if {$count>2} { @@ -230,7 +235,8 @@ do_test lock-2.7 { } set ::callback_value {} db2 busy callback - set r [catch {execsql {BEGIN TRANSACTION} db2} msg] + execsql {BEGIN TRANSACTION} db2 + set r [catch {execsql {UPDATE t1 SET a = 0 WHERE 0} db2} msg] execsql {ROLLBACK} db2 lappend r $msg lappend r $::callback_value @@ -241,7 +247,9 @@ do_test lock-2.7 { do_test lock-2.8 { db2 timeout 400 execsql BEGIN + execsql {UPDATE t1 SET a = 0 WHERE 0} catchsql BEGIN db2 + catchsql {UPDATE t1 SET a = 0 WHERE 0} db2 } {1 {database is locked}} do_test lock-2.9 { db2 timeout 0 @@ -267,6 +275,7 @@ do_test lock-4.1 { db2 close catch {db eval ROLLBACK} db eval BEGIN + db eval {UPDATE t1 SET a=0 WHERE 0} sqlite db2 ./test.db set rc [catch {db2 eval {SELECT * FROM t1}} msg] lappend rc $msg diff --git a/test/misc1.test b/test/misc1.test index 81c17d8a3..12720961c 100644 --- a/test/misc1.test +++ b/test/misc1.test @@ -13,7 +13,7 @@ # This file implements tests for miscellanous features that were # left out of other test files. # -# $Id: misc1.test,v 1.24 2004/05/19 20:41:04 drh Exp $ +# $Id: misc1.test,v 1.25 2004/05/31 08:26:49 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -312,6 +312,7 @@ do_test misc1-10.10 { # do_test misc1-11.1 { execsql {BEGIN} + execsql {UPDATE t1 SET a=0 WHERE 0} sqlite db2 test.db set rc [catch {db2 eval {SELECT count(*) FROM t1}} msg] lappend rc $msg @@ -454,6 +455,7 @@ do_test misc1-14.1 { file exists ./test.db-journal } {0} do_test misc1-14.2 { + execsql {UPDATE t1 SET a=0 WHERE 0} file exists ../test.db-journal } {1} do_test misc1-14.3 { diff --git a/test/progress.test b/test/progress.test index 15d769d49..90bb63d2f 100755 --- a/test/progress.test +++ b/test/progress.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the 'progress callback'. # -# $Id: progress.test,v 1.1 2003/10/18 09:37:27 danielk1977 Exp $ +# $Id: progress.test,v 1.2 2004/05/31 08:26:50 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -49,11 +49,11 @@ do_test progress-1.0 { do_test progress1.1 { set counter 0 db progress 1 "[namespace code {incr counter}] ; expr 1" - execsql { + set rc [catch {execsql { SELECT * FROM t1 - } - set counter -} 1 + }}] + list $counter $rc +} {1 1} # Test that the query is rolled back when the progress callback returns # non-zero. @@ -75,8 +75,8 @@ do_test progress1.2 { # some data will have been inserted into the table by the time the progress # callback abandons the query. db progress $five_rows "expr 1" - execsql { - INSERT INTO t1 SELECT a+10 FROM t1 WHERE a < 7 + catchsql { + INSERT INTO t1 SELECT a+10 FROM t1 WHERE a < 9 } execsql { SELECT count(*) FROM t1 @@ -93,7 +93,7 @@ do_test progress1.3 { INSERT INTO t1 VALUES(11) } db progress 1 "expr 1" - execsql { + catchsql { INSERT INTO t1 VALUES(12) } db progress 0 "" diff --git a/test/trans.test b/test/trans.test index a2a443c15..4e59a63cc 100644 --- a/test/trans.test +++ b/test/trans.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script is database locks. # -# $Id: trans.test,v 1.19 2004/03/08 13:26:18 drh Exp $ +# $Id: trans.test,v 1.20 2004/05/31 08:26:50 danielk1977 Exp $ set testdir [file dirname $argv0] @@ -88,6 +88,7 @@ integrity_check trans-2.11 do_test trans-3.1 { execsql { BEGIN; + UPDATE one SET a = 0 WHERE 0; SELECT a FROM one ORDER BY a; } } {1 2 3} @@ -183,6 +184,7 @@ do_test trans-4.2 { do_test trans-4.3 { set v [catch {execsql { BEGIN TRANSACTION; + UPDATE two SET a = 0 WHERE 0; SELECT a FROM two ORDER BY a; } db} msg] lappend v $msg |