]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Transactions commit on the last sqlite3_step(), not on sqlite3_finalize().
authordrh <drh@noemail.net>
Thu, 2 Sep 2004 14:57:08 +0000 (14:57 +0000)
committerdrh <drh@noemail.net>
Thu, 2 Sep 2004 14:57:08 +0000 (14:57 +0000)
This allows the sqlite3_step() to return SQLITE_BUSY if the commit is
blocked by a lock.  Ticket #885. (CVS 1928)

FossilOrigin-Name: d1b29156558f1c576002cdb2544dffaa693da39b

12 files changed:
manifest
manifest.uuid
src/main.c
src/pager.c
src/vdbe.c
src/vdbeInt.h
src/vdbeaux.c
test/attach2.test
test/capi2.test
test/capi3.test
test/capi3b.test [new file with mode: 0644]
test/quick.test

index ae4458bea33f0b7871db5395204d844bda50e0c1..38ccf08d704260369dc47d6b358c226b05771ca3 100644 (file)
--- 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
index b0ae7163c51c501699de450ebb08cbf0cb173a77..c22d4c09c4669fcd051a1ed7068b1a895e03a9db 100644 (file)
@@ -1 +1 @@
-18af6ba580a5ad50a20955bfe2ebce8e30b1d39e
\ No newline at end of file
+d1b29156558f1c576002cdb2544dffaa693da39b
\ No newline at end of file
index af07d904585781f593f135e796e2ce6c8b29286d..91dd1b23b5c9d332614e83b7ebda6c41102a7551 100644 (file)
@@ -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);
index b53962ad66a4ab1e1792bd850c3cf75432aa3cfd..d94847be58df1b77ceb7c40307850e6a48d4d3cf 100644 (file)
@@ -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;
 }
 
index 4151e43b105b7e8ab19ce1ecbdf81e14690a75b6..a3d3dd65116714860ec59387165671a33f65d9a8 100644 (file)
@@ -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;
 
index c16c2613673a2518d5ff34a6f78eba7f0cb16e75..ef92acc9cfe36c732be0fc317a0e9af3aa604f5f 100644 (file)
@@ -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);
index 1734677c31a3149c251be218f8547b4a596d9f5d..ba81e1be373205f890571ff2623938f50a26c894 100644 (file)
@@ -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->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);
+  if( p->magic!=VDBE_MAGIC_RUN ){
+    /* Already halted.  Nothing to do. */
+    assert( p->magic==VDBE_MAGIC_HALT );
+    return SQLITE_OK;
   }
-  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.
index 6fbb7f9c4cfccd49b06194aa955b2ec93e513a63..940f3cc7a226e74f4f44aeba69b8654979cbf464 100644 (file)
@@ -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}
index 6af1989dcc093f68c5a1196c3bb36f576e6a503d..e4514c90fa2115d046666f4aaa243569485fcfb7 100644 (file)
@@ -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]
index 1d8f5d550fec76de19907333cd3a846b59ac5452..b2c2f7ee48af8c6757fd338e7605e476cb831ff3 100644 (file)
@@ -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 (file)
index 0000000..93240e7
--- /dev/null
@@ -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
index a0338dc0b42aa7cfe263c9a6e5dca71f8f5d57a5..7fd641d17dd1ebd5da93dfea9950f0fd8b460e24 100644 (file)
@@ -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