diff --git a/manifest b/manifest index ae4458bea3..38ccf08d70 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Work\saround\sa\sbug\sin\sthe\sBorland\sC++\scompiler.\s\sTicket\s#881.\s(CVS\s1927) -D 2004-09-01T16:12:25 +C Transactions\scommit\son\sthe\slast\ssqlite3_step(),\snot\son\ssqlite3_finalize().\nThis\sallows\sthe\ssqlite3_step()\sto\sreturn\sSQLITE_BUSY\sif\sthe\scommit\sis\nblocked\sby\sa\slock.\s\sTicket\s#885.\s(CVS\s1928) +D 2004-09-02T14:57:08 F Makefile.in 65a7c43fcaf9a710d62f120b11b6e435eeb4a450 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd @@ -40,7 +40,7 @@ F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5 F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84 F src/insert.c fc1ce65a0fe68f226143de9b43c3582164a92aff F src/legacy.c 2f3617c61bcdcd1d776154a9cfebf99facda8ad8 -F src/main.c b92d44c72298d31e08700b1483ef8827468dac9f +F src/main.c c42b3c1c9e0e401a490ed8f8ce789eb7302a9b69 F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070 F src/os.h d1780e0db95cad01f213d48da22ab490eb4fd345 F src/os_common.h cd7eb025fdab7dc91e0e97bf6310f1648205857f @@ -52,7 +52,7 @@ F src/os_unix.c a5625eed7ab071d1715df783f4684945ae538a22 F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13 F src/os_win.c 9e2887825b1a32f0ceb1b73b93ffe29a112cd86f F src/os_win.h babd4e912967c6b09088cfe38a45e8005a07ba44 -F src/pager.c 616563dc510993ab67baa54fc6a2ddacc05175ca +F src/pager.c ae06c85de0db43f61a7a3e5eacad3fd5615daf59 F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71 F src/parse.y 581a2ce014b843506805b2470c02b7865ad034d5 F src/pragma.c b39177b96bb5f7354511468c933357ce65a0dd4c @@ -75,16 +75,16 @@ F src/update.c bbe126c67529bd699016af2d72bc4ceb8fd41527 F src/utf.c 328890099db492dda5620ee5f924e244c6e57ff7 F src/util.c d5aaf211543fb6e285654fada50252c857ac78aa F src/vacuum.c 9978a5760c2c430bc5b5e66505a02dad76f25813 -F src/vdbe.c 28b0ea2a8c534fc39e15e41db0437fcc3b5f2e9b +F src/vdbe.c 45f659497b479f001c2f4e8251474aba3975b9f8 F src/vdbe.h e081c72cd0f7c19d49b1927460aeefcf0fbc85ac -F src/vdbeInt.h aadadddc8cfad6aa5a5445c849f70d881276fe34 +F src/vdbeInt.h f8df57a9dc272967991f806e612628e0aa57e705 F src/vdbeapi.c 854732720c2cfc6ff76b28eef6253ac84a5408bc -F src/vdbeaux.c 022c484dba235d2dcbb1faca0f1943702f4232ed +F src/vdbeaux.c 77eaaf62b8b3acad4a2ef351e3c44ecffc67faf6 F src/vdbemem.c ef9ac7d32acfe4bce5c5b408b1294c8d9e0cdb56 F src/where.c a84eee276cd072158224da6b5f30733df2d56027 F test/all.test 929bfa932b55e75c96fe2203f7650ba451c1862c F test/attach.test feb2ce54e78688df4c84553416d5aec3b2a0112e -F test/attach2.test 9be9656bc1e929b224861960299920c76d45b14d +F test/attach2.test 32ca2c1a5a347a7404219a11f9f84739a63d2582 F test/attach3.test 6d060986ff004ebb89e1876a331d96c6bb62269e F test/auth.test e74b015545f608c06d5b84d17acdf7146eb818af F test/bigfile.test 62722ac4b420dfbcdceb137b8634e2cf2865fe27 @@ -97,8 +97,9 @@ F test/btree4.test 3797b4305694c7af6828675b0f4b1424b8ca30e4 F test/btree5.test 8e5ff32c02e685d36516c6499add9375fe1377f2 F test/btree6.test a5ede6bfbbb2ec8b27e62813612c0f28e8f3e027 F test/btree7.test 429b96cfef5b51a7d512cfb4b5b3e453384af293 -F test/capi2.test 78f2c486689fcc80394a24c2cc32725330ab6299 -F test/capi3.test e2d47b59c1ca5be2e5986fb77f716a7fdd228e25 +F test/capi2.test 53e3f399074d5654f26d55b32ccaca7b5b619933 +F test/capi3.test 9258ca75fc98d89477015dcd70aa3d2757b142b8 +F test/capi3b.test 458044d8c250c129ddfd77c6265a6923bc008b5e F test/collate1.test f79736d2ebf5492167ee4d1f4ab4c09dda776b03 F test/collate2.test c1a3b41f761b28853c5696037f92de928f93233b F test/collate3.test e60b428e07ec945492ba90ff1c895902ee3a8a50 @@ -153,7 +154,7 @@ F test/pager3.test 16f546293bb751b8151dc17df613fca938bbec8b F test/pragma.test 66a66b7f3b273b93325c9a5794acb418f52fdcbf F test/printf.test 5a30fb0d736148fca64cb1b7ed0390be7414e024 F test/progress.test 76c722f090b1ccb575e7e4e203a71608c5763beb x -F test/quick.test 2e9af7203555ea894af654adf0794157434928fb +F test/quick.test 212a9cd4c40c72c7c4780fef1c2fbe5d1cb34ce6 F test/quote.test 6d75cf635d93ba2484dc9cb378d88cbae9dc2c62 F test/rollback.test 4097328d44510277244ef4fa51b22b2f11d7ef4c F test/rowid.test b3d059f5c8d8874fa1c31030e0636f67405d20ea @@ -246,7 +247,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4 -P 9c411c3c8dde2061c98513a413ef58c5c2de45af -R 54ca511e52d24afac36ea482ae4bc8ec +P 18af6ba580a5ad50a20955bfe2ebce8e30b1d39e +R 8124409cd5ad134f1cc0a6f820ab9a66 U drh -Z 888aa66dde2c6dec44c62c3082b0fba4 +Z 68ff020543a01eac2435ebdc5d559c02 diff --git a/manifest.uuid b/manifest.uuid index b0ae7163c5..c22d4c09c4 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -18af6ba580a5ad50a20955bfe2ebce8e30b1d39e \ No newline at end of file +d1b29156558f1c576002cdb2544dffaa693da39b \ No newline at end of file diff --git a/src/main.c b/src/main.c index af07d90458..91dd1b23b5 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.256 2004/08/29 20:08:59 drh Exp $ +** $Id: main.c,v 1.257 2004/09/02 14:57:08 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -521,7 +521,6 @@ void sqlite3RollbackAll(sqlite *db){ } } sqlite3ResetInternalSchema(db, 0); - /* sqlite3RollbackInternalChanges(db); */ } /* @@ -987,7 +986,7 @@ int sqlite3_prepare( ** Make a copy of that part of the SQL string since zSQL is const ** and we must pass a zero terminated string to the trace function ** The copy is unnecessary if the tail pointer is pointing at the - ** beginnig or end of the SQL string. + ** beginning or end of the SQL string. */ if( sParse.zTail && sParse.zTail!=zSql && *sParse.zTail ){ char *tmpSql = sqliteStrNDup(zSql, sParse.zTail - zSql); diff --git a/src/pager.c b/src/pager.c index b53962ad66..d94847be58 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.161 2004/08/30 16:52:18 drh Exp $ +** @(#) $Id: pager.c,v 1.162 2004/09/02 14:57:08 drh Exp $ */ #include "os.h" /* Must be first to enable large file support */ #include "sqliteInt.h" @@ -2798,10 +2798,7 @@ int sqlite3pager_commit(Pager *pPager){ /* Jump here if anything goes wrong during the commit process. */ commit_abort: - rc = sqlite3pager_rollback(pPager); - if( rc==SQLITE_OK ){ - rc = SQLITE_FULL; - } + sqlite3pager_rollback(pPager); return rc; } diff --git a/src/vdbe.c b/src/vdbe.c index 4151e43b10..a3d3dd6511 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.412 2004/08/31 13:45:12 drh Exp $ +** $Id: vdbe.c,v 1.413 2004/09/02 14:57:09 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -621,12 +621,12 @@ case OP_Return: { ** Exit immediately. All open cursors, Lists, Sorts, etc are closed ** automatically. ** -** P1 is the result code returned by sqlite3_exec(). For a normal -** halt, this should be SQLITE_OK (0). For errors, it can be some -** other value. If P1!=0 then P2 will determine whether or not to -** rollback the current transaction. Do not rollback if P2==OE_Fail. -** Do the rollback if P2==OE_Rollback. If P2==OE_Abort, then back -** out all changes that have occurred during this execution of the +** P1 is the result code returned by sqlite3_exec(), sqlite3_reset(), +** or sqlite3_finalize(). For a normal halt, this should be SQLITE_OK (0). +** For errors, it can be some other value. If P1!=0 then P2 will determine +** whether or not to rollback the current transaction. Do not rollback +** if P2==OE_Fail. Do the rollback if P2==OE_Rollback. If P2==OE_Abort, +** then back out all changes that have occurred during this execution of the ** VDBE, but do not rollback the transaction. ** ** There is an implied "Halt 0 0 0" instruction inserted at the very end of @@ -634,17 +634,21 @@ case OP_Return: { ** is the same as executing Halt. */ case OP_Halt: { - p->magic = VDBE_MAGIC_HALT; p->pTos = pTos; - if( pOp->p1!=SQLITE_OK ){ - p->rc = pOp->p1; - p->errorAction = pOp->p2; + p->rc = pOp->p1; + p->pc = pc; + p->errorAction = pOp->p2; + if( pOp->p3 ){ sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0); - return SQLITE_ERROR; - }else{ - p->rc = SQLITE_OK; - return SQLITE_DONE; } + rc = sqlite3VdbeHalt(p); + if( rc==SQLITE_BUSY ){ + p->rc = SQLITE_BUSY; + return SQLITE_BUSY; + }else if( rc!=SQLITE_OK ){ + p->rc = rc; + } + return p->rc ? SQLITE_ERROR : SQLITE_DONE; } /* Opcode: Integer P1 * P3 @@ -2118,6 +2122,8 @@ case OP_Statement: { ** Set the database auto-commit flag to P1 (1 or 0). If P2 is true, roll ** back any currently active btree transactions. If there are any active ** VMs (apart from this one), then the COMMIT or ROLLBACK statement fails. +** +** This instruction causes the VM to halt. */ case OP_AutoCommit: { u8 i = pOp->p1; @@ -2126,7 +2132,7 @@ case OP_AutoCommit: { assert( i==1 || i==0 ); assert( i==1 || rollback==0 ); - assert( db->activeVdbeCnt>0 ); + assert( db->activeVdbeCnt>0 ); /* At least this one VM is active */ if( db->activeVdbeCnt>1 && i && !db->autoCommit ){ /* If this instruction implements a COMMIT or ROLLBACK, other VMs are @@ -2138,10 +2144,17 @@ case OP_AutoCommit: { rc = SQLITE_ERROR; }else if( i!=db->autoCommit ){ db->autoCommit = i; - p->autoCommitOn |= 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; } + return SQLITE_DONE; }else{ sqlite3SetString(&p->zErrMsg, (!i)?"cannot start a transaction within a transaction":( @@ -4451,7 +4464,7 @@ vdbe_halt: }else{ rc = SQLITE_DONE; } - p->magic = VDBE_MAGIC_HALT; + sqlite3VdbeHalt(p); p->pTos = pTos; return rc; diff --git a/src/vdbeInt.h b/src/vdbeInt.h index c16c261367..ef92acc9cf 100644 --- a/src/vdbeInt.h +++ b/src/vdbeInt.h @@ -338,7 +338,6 @@ struct Vdbe { char *zErrMsg; /* Error message written here */ 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 */ 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 */ @@ -379,6 +378,7 @@ int sqlite3VdbeRecordCompare(void*,int,const void*,int, const void*); int sqlite3VdbeIdxRowidLen(int,const u8*); int sqlite3VdbeExec(Vdbe*); int sqlite3VdbeList(Vdbe*); +int sqlite3VdbeHalt(Vdbe*); int sqlite3VdbeChangeEncoding(Mem *, int); int sqlite3VdbeMemCopy(Mem*, const Mem*); void sqlite3VdbeMemShallowCopy(Mem*, const Mem*, int); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index 1734677c31..ba81e1be37 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -543,6 +543,9 @@ void sqlite3VdbePrintSql(Vdbe *p){ ** as allocating stack space and initializing the program counter. ** After the VDBE has be prepped, it can be executed by one or more ** calls to sqlite3VdbeExec(). +** +** This is the only way to move a VDBE from VDBE_MAGIC_INIT to +** VDBE_MAGIC_RUN. */ void sqlite3VdbeMakeReady( Vdbe *p, /* The VDBE */ @@ -938,7 +941,11 @@ static int vdbeCommit(sqlite *db){ /* If there are any write-transactions at all, invoke the commit hook */ if( needXcommit && db->xCommitCallback ){ - if( db->xCommitCallback(db->pCommitArg) ){ + int rc; + sqlite3SafetyOff(db); + rc = db->xCommitCallback(db->pCommitArg); + sqlite3SafetyOn(db); + if( rc ){ return SQLITE_CONSTRAINT; } } @@ -1124,6 +1131,8 @@ static void abortOtherActiveVdbes(Vdbe *pVdbe){ ** 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 an internal self-check only - it is not an essential processing +** step. ** ** This is a no-op if NDEBUG is defined. */ @@ -1131,15 +1140,13 @@ static void abortOtherActiveVdbes(Vdbe *pVdbe){ 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 ){ + if( p->magic==VDBE_MAGIC_RUN && p->pc>=0 ){ cnt++; } p = p->pNext; } - assert( cnt==db->activeVdbeCnt ); } #else @@ -1147,60 +1154,41 @@ static void checkActiveVdbeCnt(sqlite *db){ #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. +** This routine is called the when a VDBE tries to halt. If the VDBE +** has made changes and is in autocommit mode, then commit those +** changes. If a rollback is needed, then do the rollback. ** -** After this routine is run, the VDBE should be ready to be executed -** again. +** This routine is the only way to move the state of a VM from +** SQLITE_MAGIC_RUN to SQLITE_MAGIC_HALT. +** +** Return an error code. If the commit could not complete because of +** lock contention, return SQLITE_BUSY. If SQLITE_BUSY is returned, it +** means the close did not happen and needs to be repeated. */ -int sqlite3VdbeReset(Vdbe *p){ +int sqlite3VdbeHalt(Vdbe *p){ sqlite *db = p->db; int i; int (*xFunc)(Btree *pBt) = 0; /* Function to call on each btree backend */ - if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){ - sqlite3Error(p->db, SQLITE_MISUSE, 0 ,0); - return SQLITE_MISUSE; + if( p->magic!=VDBE_MAGIC_RUN ){ + /* Already halted. Nothing to do. */ + assert( p->magic==VDBE_MAGIC_HALT ); + return SQLITE_OK; } - if( p->zErrMsg ){ - sqlite3Error(p->db, p->rc, "%s", p->zErrMsg, 0); - sqliteFree(p->zErrMsg); - p->zErrMsg = 0; - }else if( p->rc ){ - sqlite3Error(p->db, p->rc, 0); - }else{ - sqlite3Error(p->db, SQLITE_OK, 0); - } - Cleanup(p); - - /* What is done now depends on the exit status of the vdbe, the value of - ** the sqlite.autoCommit flag and whether or not there are any other - ** queries in progress. A transaction or statement transaction may need - ** to be committed or rolled back on each open database file. - */ + closeAllCursors(p); checkActiveVdbeCnt(db); if( db->autoCommit && db->activeVdbeCnt==1 ){ if( p->rc==SQLITE_OK || p->errorAction==OE_Fail ){ /* The auto-commit flag is true, there are no other active queries ** using this handle and the vdbe program was successful or hit an - ** 'OR FAIL' constraint. This means a commit is required, which is - ** handled a little differently from the other options. + ** 'OR FAIL' constraint. This means a commit is required. */ - p->rc = vdbeCommit(db); - if( p->rc!=SQLITE_OK ){ - sqlite3Error(p->db, p->rc, 0); - if( p->rc==SQLITE_BUSY && p->autoCommitOn ){ - /* If we just now have turned autocommit on (meaning we just have - ** finished executing a COMMIT command) but the commit fails due - ** to lock contention, autocommit back off. This gives the user - ** the opportunity to try again after the lock that was preventing - ** the commit has cleared. */ - db->autoCommit = 0; - }else{ - /* If the command just executed was not a COMMIT command, then - ** rollback whatever the results of that command were */ - xFunc = sqlite3BtreeRollback; - } + int rc = vdbeCommit(db); + if( rc==SQLITE_BUSY ){ + return SQLITE_BUSY; + }else if( rc!=SQLITE_OK ){ + p->rc = rc; + xFunc = sqlite3BtreeRollback; } }else{ xFunc = sqlite3BtreeRollback; @@ -1216,7 +1204,6 @@ int sqlite3VdbeReset(Vdbe *p){ abortOtherActiveVdbes(p); } } - p->autoCommitOn = 0; /* If xFunc is not NULL, then it is one of sqlite3BtreeRollback, ** sqlite3BtreeRollbackStmt or sqlite3BtreeCommitStmt. Call it once on @@ -1242,16 +1229,65 @@ int sqlite3VdbeReset(Vdbe *p){ p->nChange = 0; } + /* Rollback or commit any schema changes that occurred. */ if( p->rc!=SQLITE_OK ){ sqlite3RollbackInternalChanges(db); }else if( db->flags & SQLITE_InternChanges ){ sqlite3CommitInternalChanges(db); } - if( (p->magic==VDBE_MAGIC_RUN && p->pc>=0) || p->magic==VDBE_MAGIC_HALT ){ + /* We have successfully halted and closed the VM. Record this fact. */ + if( p->pc>=0 ){ db->activeVdbeCnt--; } + p->magic = VDBE_MAGIC_HALT; + checkActiveVdbeCnt(db); + return SQLITE_OK; +} + +/* +** Clean up a VDBE after execution but do not delete the VDBE just yet. +** Write any error messages into *pzErrMsg. Return the result code. +** +** After this routine is run, the VDBE should be ready to be executed +** again. +** +** To look at it another way, this routine resets the state of the +** virtual machine from VDBE_MAGIC_RUN or VDBE_MAGIC_HALT back to +** VDBE_MAGIC_INIT. +*/ +int sqlite3VdbeReset(Vdbe *p){ + if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){ + sqlite3Error(p->db, SQLITE_MISUSE, 0 ,0); + return SQLITE_MISUSE; + } + + /* If the VM did not run to completion or if it encountered an + ** error, then it might not have been halted properly. So halt + ** it now. + */ + sqlite3VdbeHalt(p); + + /* Transfer the error code and error message from the VDBE into the + ** main database structure. + */ + if( p->zErrMsg ){ + sqlite3Error(p->db, p->rc, "%s", p->zErrMsg, 0); + sqliteFree(p->zErrMsg); + p->zErrMsg = 0; + }else if( p->rc ){ + sqlite3Error(p->db, p->rc, 0); + }else{ + sqlite3Error(p->db, SQLITE_OK, 0); + } + + /* Reclaim all memory used by the VDBE + */ + Cleanup(p); + + /* Save profiling information from this VDBE run. + */ assert( p->pTos<&p->aStack[p->pc<0?0:p->pc] || sqlite3_malloc_failed==1 ); #ifdef VDBE_PROFILE { @@ -1279,7 +1315,7 @@ int sqlite3VdbeReset(Vdbe *p){ p->aborted = 0; return p->rc; } - + /* ** Clean up and delete a VDBE after execution. Return an integer which is ** the result code. Write any error message text into *pzErrMsg. diff --git a/test/attach2.test b/test/attach2.test index 6fbb7f9c4c..940f3cc7a2 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.25 2004/08/18 16:05:20 drh Exp $ +# $Id: attach2.test,v 1.26 2004/09/02 14:57:09 drh Exp $ # set testdir [file dirname $argv0] @@ -263,7 +263,6 @@ do_test attach2-4.9 { lock_status 4.9.1 db {main shared temp closed file2 shared} lock_status 4.9.2 db2 {main reserved temp closed file2 reserved} -btree_breakpoint do_test attach2-4.10 { # We cannot commit db2 while db is holding a read-lock catchsql {COMMIT} db2 @@ -273,7 +272,6 @@ lock_status 4.10.1 db {main shared temp closed file2 shared} lock_status 4.10.2 db2 {main pending temp closed file2 reserved} set sqlite_os_trace 0 -btree_breakpoint do_test attach2-4.11 { # db is able to commit. catchsql {COMMIT} diff --git a/test/capi2.test b/test/capi2.test index 6af1989dcc..e4514c90fa 100644 --- a/test/capi2.test +++ b/test/capi2.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # -# $Id: capi2.test,v 1.18 2004/06/30 06:30:26 danielk1977 Exp $ +# $Id: capi2.test,v 1.19 2004/09/02 14:57:09 drh Exp $ # set testdir [file dirname $argv0] @@ -203,7 +203,8 @@ do_test capi2-3.10 { # Update for v3 - the change has not actually happened until the query is # finalized. Is this going to cause trouble for anyone? Lee Nelson maybe? -do_test capi2-3.10b {db changes} {0} +# (Later:) The change now happens just before SQLITE_DONE is returned. +do_test capi2-3.10b {db changes} {1} do_test capi2-3.11 { sqlite3_finalize $VM } {SQLITE_OK} @@ -220,8 +221,9 @@ do_test capi2-3.13 { } {SQLITE_ERROR 0 {} {}} # Update for v3: Preparing a statement does not affect the change counter. -# (Test result changes from 0 to 1). -do_test capi2-3.13b {db changes} {1} +# (Test result changes from 0 to 1). (Later:) change counter updates occur +# when sqlite3_step returns, not at finalize time. +do_test capi2-3.13b {db changes} {0} do_test capi2-3.14 { list [sqlite3_finalize $VM] [sqlite3_errmsg $DB] diff --git a/test/capi3.test b/test/capi3.test index 1d8f5d550f..b2c2f7ee48 100644 --- a/test/capi3.test +++ b/test/capi3.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this script testing the callback-free C/C++ API. # -# $Id: capi3.test,v 1.20 2004/07/22 15:02:26 drh Exp $ +# $Id: capi3.test,v 1.21 2004/09/02 14:57:09 drh Exp $ # set testdir [file dirname $argv0] @@ -536,7 +536,7 @@ if {![sqlite3 -has-codec]} { btree_close_cursor $::bc btree_commit $::bt btree_close $::bt - } {} + } {}; do_test capi3-8.5 { db close sqlite3 db test.db diff --git a/test/capi3b.test b/test/capi3b.test new file mode 100644 index 0000000000..93240e7b25 --- /dev/null +++ b/test/capi3b.test @@ -0,0 +1,90 @@ +# 2004 September 2 +# +# 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 script testing the callback-free C/C++ API and in +# particular the behavior of sqlite3_step() when trying to commit +# with lock contention. +# +# $Id: capi3b.test,v 1.1 2004/09/02 14:57:09 drh Exp $ +# + +set testdir [file dirname $argv0] +source $testdir/tester.tcl + + +db close +set DB [sqlite3 db test.db] +set DB2 [sqlite3 db2 test.db] + +# Create some data in the database +# +do_test capi3b-1.1 { + execsql { + CREATE TABLE t1(x); + INSERT INTO t1 VALUES(1); + INSERT INTO t1 VALUES(2); + SELECT * FROM t1 + } +} {1 2} + +# Make sure the second database connection can see the data +# +do_test capi3b-1.2 { + execsql { + SELECT * FROM t1 + } db2 +} {1 2} + +# First database connection acquires a shared lock +# +do_test capi3b-1.3 { + execsql { + BEGIN; + SELECT * FROM t1; + } +} {1 2} + +# Second database connection tries to write. The sqlite3_step() +# function returns SQLITE_BUSY because it cannot commit. +# +do_test capi3b-1.4 { + set VM [sqlite3_prepare $DB2 {INSERT INTO t1 VALUES(3)} -1 TAIL] + sqlite3_step $VM +} SQLITE_BUSY + +# The sqlite3_step call can be repeated multiple times. +# +do_test capi3b-1.5.1 { + sqlite3_step $VM +} SQLITE_BUSY +do_test capi3b-1.5.2 { + sqlite3_step $VM +} SQLITE_BUSY + +# The first connection closes its transaction. This allows the second +# connections sqlite3_step to succeed. +# +do_test capi3b-1.6 { + execsql COMMIT + sqlite3_step $VM +} SQLITE_DONE +do_test capi3b-1.7 { + sqlite3_finalize $VM +} SQLITE_OK +do_test capi3b-1.8 { + execsql {SELECT * FROM t1} db2 +} {1 2 3} +do_test capi3b-1.9 { + execsql {SELECT * FROM t1} +} {1 2 3} + +catch {db2 close} +finish_test diff --git a/test/quick.test b/test/quick.test index a0338dc0b4..7fd641d17d 100644 --- a/test/quick.test +++ b/test/quick.test @@ -10,7 +10,7 @@ #*********************************************************************** # This file runs all tests. # -# $Id: quick.test,v 1.29 2004/08/30 16:52:19 drh Exp $ +# $Id: quick.test,v 1.30 2004/09/02 14:57:09 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -21,6 +21,10 @@ set ISQUICK 1 set EXCLUDE { all.test btree2.test + btree3.test + btree4.test + btree5.test + btree6.test corrupt.test crash.test malloc.test