]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add a complicated assert() to check that statement transactions are opened when required.
authordan <dan@noemail.net>
Wed, 9 Sep 2009 11:37:20 +0000 (11:37 +0000)
committerdan <dan@noemail.net>
Wed, 9 Sep 2009 11:37:20 +0000 (11:37 +0000)
FossilOrigin-Name: 28aa1f4ea8dad56ffedb31d6c2bc27c1d6be2407

configure [changed mode: 0644->0755]
manifest
manifest.uuid
src/build.c
src/vdbe.h
src/vdbeaux.c

old mode 100644 (file)
new mode 100755 (executable)
index 7c094215f9a50b63843798646c7dbe56c108864c..3337dad7079227028db7ab55be39ded65e160f1f 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Combine\sthe\sOP_Statement\sand\sOP_Transaction\sopcodes.
-D 2009-09-08T19:15:01
+C Add\sa\scomplicated\sassert()\sto\scheck\sthat\sstatement\stransactions\sare\sopened\swhen\srequired.
+D 2009-09-09T11:37:20
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 73ddeec9dd10b85876c5c2ce1fdce627e1dcc7f8
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -19,7 +19,7 @@ F art/src_logo.gif 9341ef09f0e53cd44c0c9b6fc3c16f7f3d6c2ad9
 F config.guess 226d9a188c6196f3033ffc651cbc9dcee1a42977
 F config.h.in 868fdb48c028421a203470e15c69ada15b9ba673
 F config.sub 9ebe4c3b3dab6431ece34f16828b594fb420da55
-F configure bccfdabb9982b7e88a33470741f1d6ba14a6b684
+F configure bccfdabb9982b7e88a33470741f1d6ba14a6b684 x
 F configure.ac 14740970ddb674d92a9f5da89083dff1179014ff
 F contrib/sqlitecon.tcl 210a913ad63f9f991070821e599d600bd913e0ad
 F doc/lemon.html f0f682f50210928c07e562621c3b7e8ab912a538
@@ -109,7 +109,7 @@ F src/btmutex.c 0f43a75bb5b8147b386e8e1c3e71ba734e3863b7
 F src/btree.c 873a82706e07604a638e02e12617983df8e8070a
 F src/btree.h 577448a890c2ab9b21e6ab74f073526184bceebe
 F src/btreeInt.h 1c86297e69380f6577e7ae67452597dd8d5c2705
-F src/build.c 1a21d6dcb6a60b065f5407c6a5f2d021f946fa34
+F src/build.c 5269733241f459705189aa39f4eacf18b10d7661
 F src/callback.c f49c305dc94b78da948953c392963929c0e70f9b
 F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
 F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3
@@ -206,10 +206,10 @@ F src/utf.c 99cf927eabb104621ba889ac0dd075fc1657ad30
 F src/util.c 59d4e9456bf1fe581f415a783fa0cee6115c8f35
 F src/vacuum.c 3fe0eebea6d2311c1c2ab2962887d11f7a4dcfb0
 F src/vdbe.c aba680ec9cf68890f3600a4c0c1936b1d789d111
-F src/vdbe.h afd9c99544fd916c93c6de5b1d11490899e483ea
+F src/vdbe.h 13e00f573bccf0c03e95fd3d4759da4ea9b75e60
 F src/vdbeInt.h 004dbb28a9195b6c85fe3255c7cc300ffd8b9453
 F src/vdbeapi.c b7e5f34436e298e2b0168e71323b5d97f7e9b080
-F src/vdbeaux.c 75dff9148f3bcdb5772ca00be774f7194a4fce61
+F src/vdbeaux.c 257f9ab8631b3f31e69a937f1fd8aa3adf3f4209
 F src/vdbeblob.c 4d6b702ca714a2d52552eee72d3e3191f8444eab
 F src/vdbemem.c 0ff2b209fccade3ff6709286057b82ed7f6c1e70
 F src/vtab.c 3e54fe39374e5feb8b174de32a90e7a21966025d
@@ -750,7 +750,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
 F tool/vdbe-compress.tcl d70ea6d8a19e3571d7ab8c9b75cba86d1173ff0f
-P 85cb0c94a63eda5f059ebe40887c7af9b4869893
-R 6a11a24dc821178a3e61515331c83e2c
+P aec9dbd8d21c55c3945287a3dfa55d3ed168f977
+R a1841d0403c06c3b9b5f6e774b694b14
 U dan
-Z 33e8150d74d6f5afb30b73dad757212c
+Z 90b3c5c92554cb2f54c26452d6fcd827
index 75afbe71487476b0591c24040be6d32ce26a52e4..113190949e769f3b897ffcdb359f2272c51a787a 100644 (file)
@@ -1 +1 @@
-aec9dbd8d21c55c3945287a3dfa55d3ed168f977
\ No newline at end of file
+28aa1f4ea8dad56ffedb31d6c2bc27c1d6be2407
\ No newline at end of file
index 4e0f13475aff4d5e356f57dae643c9801a04d466..da47a6ab6ba17a746bfbc75a956f9ea017df0a84 100644 (file)
@@ -138,6 +138,7 @@ void sqlite3FinishCoding(Parse *pParse){
   ** vdbe program
   */
   v = sqlite3GetVdbe(pParse);
+  assert( pParse->isMultiWrite==0 || sqlite3VdbeMayAbort(v)==pParse->mayAbort );
   if( v ){
     sqlite3VdbeAddOp0(v, OP_Halt);
 
index 3df12c363ce5452cd2e7a4222ec76633a12eb682..a89e4218b321fd5440da1c69e61243d5571a9e87 100644 (file)
@@ -189,6 +189,7 @@ int sqlite3VdbeFinalize(Vdbe*);
 void sqlite3VdbeResolveLabel(Vdbe*, int);
 int sqlite3VdbeCurrentAddr(Vdbe*);
 #ifdef SQLITE_DEBUG
+  int sqlite3VdbeMayAbort(Vdbe*);
   void sqlite3VdbeTrace(Vdbe*,FILE*);
 #endif
 void sqlite3VdbeResetStepResult(Vdbe*);
index b410c4322068bccfb0349f704bab56dd0dba746c..b968c7bbc59dce500aa3484d2c854a88d1dca576 100644 (file)
@@ -240,6 +240,113 @@ void sqlite3VdbeResolveLabel(Vdbe *p, int x){
   }
 }
 
+#ifdef SQLITE_DEBUG
+
+/*
+** The following type and function are used to iterate through all opcodes
+** in a Vdbe main program and each of the sub-programs (triggers) it may 
+** invoke directly or indirectly. It should be used as follows:
+**
+**   Op *pOp;
+**   VdbeOpIter sIter;
+**
+**   memset(&sIter, 0, sizeof(sIter));
+**   sIter.v = v;                            // v is of type Vdbe* 
+**   while( (pOp = opIterNext(&sIter)) ){
+**     // Do something with pOp
+**   }
+**   sqlite3DbFree(v->db, sIter.apSub);
+** 
+*/
+typedef struct VdbeOpIter VdbeOpIter;
+struct VdbeOpIter {
+  Vdbe *v;                   /* Vdbe to iterate through the opcodes of */
+  SubProgram **apSub;        /* Array of subprograms */
+  int nSub;                  /* Number of entries in apSub */
+  int iAddr;                 /* Address of next instruction to return */
+  int iSub;                  /* 0 = main program, 1 = first sub-program etc. */
+};
+static Op *opIterNext(VdbeOpIter *p){
+  Vdbe *v = p->v;
+  Op *pRet = 0;
+  Op *aOp;
+  int nOp;
+
+  if( p->iSub<=p->nSub ){
+
+    if( p->iSub==0 ){
+      aOp = v->aOp;
+      nOp = v->nOp;
+    }else{
+      aOp = p->apSub[p->iSub-1]->aOp;
+      nOp = p->apSub[p->iSub-1]->nOp;
+    }
+    assert( p->iAddr<nOp );
+
+    pRet = &aOp[p->iAddr];
+    p->iAddr++;
+    if( p->iAddr==nOp ){
+      p->iSub++;
+      p->iAddr = 0;
+    }
+  
+    if( pRet->p4type==P4_SUBPROGRAM ){
+      int nByte = (p->nSub+1)*sizeof(SubProgram*);
+      int j;
+      for(j=0; j<p->nSub; j++){
+        if( p->apSub[j]==pRet->p4.pProgram ) break;
+      }
+      if( j==p->nSub ){
+        p->apSub = sqlite3DbReallocOrFree(v->db, p->apSub, nByte);
+        if( !p->apSub ){
+          pRet = 0;
+        }else{
+          p->apSub[p->nSub++] = pRet->p4.pProgram;
+        }
+      }
+    }
+  }
+
+  return pRet;
+}
+
+/*
+** Return true if the program stored in the VM passed as an argument may
+** throw an ABORT exception (causing the statement, but not transaction
+** to be rolled back). This condition is true if the main program or any
+** sub-programs contains any of the following:
+**
+**   *  OP_Halt with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
+**   *  OP_HaltIfNull with P1=SQLITE_CONSTRAINT and P2=OE_Abort.
+**   *  OP_Destroy
+**   *  OP_VUpdate
+**   *  OP_VRename
+**
+** This function is only used as part of an assert() statement. 
+*/
+int sqlite3VdbeMayAbort(Vdbe *v){
+  int mayAbort = 0;
+  Op *pOp;
+  VdbeOpIter sIter;
+  memset(&sIter, 0, sizeof(sIter));
+  sIter.v = v;
+
+  while( (pOp = opIterNext(&sIter))!=0 ){
+    int opcode = pOp->opcode;
+    if( opcode==OP_Destroy || opcode==OP_VUpdate || opcode==OP_VRename 
+     || ((opcode==OP_Halt || opcode==OP_HaltIfNull) 
+      && (pOp->p1==SQLITE_CONSTRAINT && pOp->p2==OE_Abort))
+    ){
+      mayAbort = 1;
+      break;
+    }
+  }
+
+  sqlite3DbFree(v->db, sIter.apSub);
+  return mayAbort;
+}
+#endif
+
 /*
 ** Loop through the program looking for P2 values that are negative
 ** on jump instructions.  Each such value is a label.  Resolve the