]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Enhance the sqlite3VdbeGetOp() routine so that it always returns a pointer
authordrh <drh@noemail.net>
Fri, 29 May 2009 19:00:12 +0000 (19:00 +0000)
committerdrh <drh@noemail.net>
Fri, 29 May 2009 19:00:12 +0000 (19:00 +0000)
to VdbeOp, even following an OOM fault.  This simplifies error handling in
callers.  Cleanup to the column cache logic and the expr.c source module. (CVS 6691)

FossilOrigin-Name: ede06dacdf7acab23cd9666a0a0d092a637bcb78

manifest
manifest.uuid
src/expr.c
src/insert.c
src/vdbeaux.c

index 65538976496dbc8a9efa09360ad8202e73e6d4a3..31af058f6e7f9efdc0a702a1c8fadb957ae98299 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Refinements\sin\sexpression\shandling\slogic\sthat\shave\sresulted\sfrom\srecent\nstructural\stesting.\s(CVS\s6690)
-D 2009-05-29T14:39:08
+C Enhance\sthe\ssqlite3VdbeGetOp()\sroutine\sso\sthat\sit\salways\sreturns\sa\spointer\nto\sVdbeOp,\seven\sfollowing\san\sOOM\sfault.\s\sThis\ssimplifies\serror\shandling\sin\ncallers.\s\sCleanup\sto\sthe\scolumn\scache\slogic\sand\sthe\sexpr.c\ssource\smodule.\s(CVS\s6691)
+D 2009-05-29T19:00:13
 F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
 F Makefile.in 583e87706abc3026960ed759aff6371faf84c211
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -114,14 +114,14 @@ F src/callback.c 57359fa93de47c341b6b8ee504a88ff276397686
 F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
 F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3
 F src/delete.c cb791855c7948cecc96def9d97989879ca26f257
-F src/expr.c ba5ba6a6332ec07d81cda97585dabf6c88bffbab
+F src/expr.c b844f5f63bc46c160ce20ec7b76ca2fe4aa70323
 F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
 F src/func.c 9d7b47729c337c5e4b78d795922ed34eec4aef67
 F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c
 F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
 F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1
 F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
-F src/insert.c 050536ea91c6cf74d87a2386b5da241141943c94
+F src/insert.c 69ef88ce30d1f65315b57aba63b2d4e9bdca1090
 F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0
 F src/legacy.c 9a56cf126ceee332b56061bf16bd0fb4ff9e26c0
 F src/loadext.c a281f9890ce4f8f2b68967a124322c6ae98f1245
@@ -207,7 +207,7 @@ F src/vdbe.c b859cb274024e5755aa03625251ff859e3e95158
 F src/vdbe.h 35a648bc3279a120da24f34d9a25213ec15daf8a
 F src/vdbeInt.h 43183a2a18654fa570219ab65e53a608057c48ae
 F src/vdbeapi.c 86aa27a5f3493aaffb8ac051782aa3b22670d7ed
-F src/vdbeaux.c 1a07329bdf51cc3687f88d9f5b2bd3f1d47cc5a8
+F src/vdbeaux.c 37730f227a5301c04e5bf03fd303b9086ada990c
 F src/vdbeblob.c 5c5abe9af28316772e7829359f6f9cda2c737ebd
 F src/vdbemem.c 05183d46094aa99b8f8350e5761b9369dbef35a8
 F src/vtab.c b0216337ae7d27708dedd56d220e6f4fecda92f1
@@ -731,7 +731,7 @@ F tool/speedtest16.c c8a9c793df96db7e4933f0852abb7a03d48f2e81
 F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
 F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
 F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
-P 726b425e43e5d864e7e83853bdf134debc1ffb59
-R 7782c740d0e684d85e0d73fa4ed3175a
+P bd89f2c29b00e6b473f30c2e929d2f626721ad92
+R 29b49f3922c1a42fc4c3255229bf7dca
 U drh
-Z 3b276276ba95400e6569bffb7e01828d
+Z 402c7be7f2f60e461e03a4ddcdf6f1bd
index 56bb8a97680820cafe1751d8cfd20fa408bb0636..c67e2e159ed5e758622435a5a9287dd36998d600 100644 (file)
@@ -1 +1 @@
-bd89f2c29b00e6b473f30c2e929d2f626721ad92
\ No newline at end of file
+ede06dacdf7acab23cd9666a0a0d092a637bcb78
\ No newline at end of file
index d0b96a039ae804fc52cd11534573c871bb20d870..b9979d6020ea1d143eecc1cd009d891da058c3e0 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.440 2009/05/29 14:39:08 drh Exp $
+** $Id: expr.c,v 1.441 2009/05/29 19:00:13 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -1773,6 +1773,9 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
   int idxLru;
   struct yColCache *p;
 
+  assert( iReg>0 );  /* Register numbers are always positive */
+  assert( iCol>=-1 && iCol<32768 );  /* Finite column numbers */
+
   /* First replace any existing entry */
   for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
     if( p->iReg && p->iTable==iTab && p->iColumn==iCol ){
@@ -1784,7 +1787,6 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
       return;
     }
   }
-  if( iReg<=0 ) return;
 
   /* Find an empty slot and replace it */
   for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
@@ -1809,7 +1811,7 @@ void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int iReg){
       minLru = p->lru;
     }
   }
-  if( idxLru>=0 ){
+  if( ALWAYS(idxLru>=0) ){
     p = &pParse->aColCache[idxLru];
     p->iLevel = pParse->iCacheLevel;
     p->iTable = iTab;
@@ -1911,10 +1913,6 @@ int sqlite3ExprCodeGetColumn(
   for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
     if( p->iReg>0 && p->iTable==iTable && p->iColumn==iColumn
            && (!p->affChange || allowAffChng) ){
-#if 0
-      sqlite3VdbeAddOp0(v, OP_Noop);
-      VdbeComment((v, "OPT: tab%d.col%d -> r%d", iTable, iColumn, p->iReg));
-#endif
       p->lru = pParse->iCacheCnt++;
       sqlite3ExprCachePinRegister(pParse, p->iReg);
       return p->iReg;
@@ -1923,9 +1921,7 @@ int sqlite3ExprCodeGetColumn(
   assert( v!=0 );
   if( iColumn<0 ){
     sqlite3VdbeAddOp2(v, OP_Rowid, iTable, iReg);
-  }else if( pTab==0 ){
-    sqlite3VdbeAddOp3(v, OP_Column, iTable, iColumn, iReg);
-  }else{
+  }else if( ALWAYS(pTab!=0) ){
     int op = IsVirtual(pTab) ? OP_VColumn : OP_Column;
     sqlite3VdbeAddOp3(v, op, iTable, iColumn, iReg);
     sqlite3ColumnDefault(v, pTab, iColumn);
@@ -1977,7 +1973,7 @@ void sqlite3ExprCacheAffinityChange(Parse *pParse, int iStart, int iCount){
 void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
   int i;
   struct yColCache *p;
-  if( iFrom==iTo ) return;
+  if( NEVER(iFrom==iTo) ) return;
   sqlite3VdbeAddOp3(pParse->pVdbe, OP_Move, iFrom, iTo, nReg);
   for(i=0, p=pParse->aColCache; i<SQLITE_N_COLCACHE; i++, p++){
     int x = p->iReg;
@@ -1993,7 +1989,7 @@ void sqlite3ExprCodeMove(Parse *pParse, int iFrom, int iTo, int nReg){
 */
 void sqlite3ExprCodeCopy(Parse *pParse, int iFrom, int iTo, int nReg){
   int i;
-  if( iFrom==iTo ) return;
+  if( NEVER(iFrom==iTo) ) return;
   for(i=0; i<nReg; i++){
     sqlite3VdbeAddOp2(pParse->pVdbe, OP_Copy, iFrom+i, iTo+i);
   }
@@ -2019,15 +2015,15 @@ static int usedAsColumnCache(Parse *pParse, int iFrom, int iTo){
 ** convert the last instruction from OP_SCopy to OP_Copy.
 */
 void sqlite3ExprHardCopy(Parse *pParse, int iReg, int nReg){
-  int addr;
   VdbeOp *pOp;
   Vdbe *v;
 
+  assert( pParse->db->mallocFailed==0 );
   v = pParse->pVdbe;
-  addr = sqlite3VdbeCurrentAddr(v);
-  pOp = sqlite3VdbeGetOp(v, addr-1);
-  assert( pOp || pParse->db->mallocFailed );
-  if( pOp && pOp->opcode==OP_SCopy && pOp->p1>=iReg && pOp->p1<iReg+nReg ){
+  assert( v!=0 );
+  pOp = sqlite3VdbeGetOp(v, -1);
+  assert( pOp!=0 );
+  if( pOp->opcode==OP_SCopy && pOp->p1>=iReg && pOp->p1<iReg+nReg ){
     pOp->opcode = OP_Copy;
   }
 }
@@ -2098,12 +2094,13 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
   int regFree1 = 0;         /* If non-zero free this temporary register */
   int regFree2 = 0;         /* If non-zero free this temporary register */
   int r1, r2, r3, r4;       /* Various register numbers */
-  sqlite3 *db;
+  sqlite3 *db = pParse->db; /* The database connection */
 
-  db = pParse->db;
-  assert( v!=0 || db->mallocFailed );
   assert( target>0 && target<=pParse->nMem );
-  if( v==0 ) return 0;
+  if( v==0 ){
+    assert( pParse->db->mallocFailed );
+    return 0;
+  }
 
   if( pExpr==0 ){
     op = TK_NULL;
@@ -2173,14 +2170,12 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
     }
 #endif
     case TK_VARIABLE: {
-      int iPrior;
       VdbeOp *pOp;
       assert( !ExprHasProperty(pExpr, EP_IntValue) );
       assert( pExpr->u.zToken!=0 );
       assert( pExpr->u.zToken[0]!=0 );
       if( pExpr->u.zToken[1]==0
-         && (iPrior = sqlite3VdbeCurrentAddr(v)-1)>=0
-         && (pOp = sqlite3VdbeGetOp(v, iPrior))->opcode==OP_Variable
+         && (pOp = sqlite3VdbeGetOp(v, -1))->opcode==OP_Variable
          && pOp->p1+pOp->p3==pExpr->iTable
          && pOp->p2+pOp->p3==target
          && pOp->p4.z==0
@@ -2888,7 +2883,7 @@ int sqlite3ExprCodeExprList(
     }else{
       sqlite3ExprCode(pParse, pItem->pExpr, target+i);
     }
-    if( doHardCopy ){
+    if( doHardCopy && !pParse->db->mallocFailed ){
       sqlite3ExprHardCopy(pParse, target, n);
     }
   }
index 89c5df6b4d51694a70d3ee4a335c80fca9af7153..27549f0018d29397685c1f9a9359e4b7a5f2777b 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle INSERT statements in SQLite.
 **
-** $Id: insert.c,v 1.267 2009/05/04 11:42:30 danielk1977 Exp $
+** $Id: insert.c,v 1.268 2009/05/29 19:00:13 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -862,7 +862,7 @@ void sqlite3Insert(
       }else{
         VdbeOp *pOp;
         sqlite3ExprCode(pParse, pList->a[keyColumn].pExpr, regRowid);
-        pOp = sqlite3VdbeGetOp(v, sqlite3VdbeCurrentAddr(v) - 1);
+        pOp = sqlite3VdbeGetOp(v, -1);
         if( ALWAYS(pOp) && pOp->opcode==OP_Null && !IsVirtual(pTab) ){
           appendFlag = 1;
           pOp->opcode = OP_NewRowid;
index 8d696e57cbc2eaf620bf1d2b6d08d46c7bb2961e..711de8b5f9258db39ca84e37229a8b76fbb9b384 100644 (file)
@@ -14,7 +14,7 @@
 ** to version 2.8.7, all this code was combined into the vdbe.c source file.
 ** But that file was getting too big so this subroutines were split out.
 **
-** $Id: vdbeaux.c,v 1.457 2009/05/06 18:57:10 shane Exp $
+** $Id: vdbeaux.c,v 1.458 2009/05/29 19:00:13 drh Exp $
 */
 #include "sqliteInt.h"
 #include "vdbeInt.h"
@@ -618,12 +618,25 @@ void sqlite3VdbeNoopComment(Vdbe *p, const char *zFormat, ...){
 #endif  /* NDEBUG */
 
 /*
-** Return the opcode for a given address.
+** Return the opcode for a given address.  If the address is -1, then
+** return the most recently inserted opcode.
+**
+** If a memory allocation error has occurred prior to the calling of this
+** routine, then a pointer to a dummy VdbeOp will be returned.  That opcode
+** is readable and writable, but it has no effect.  The return of a dummy
+** opcode allows the call to continue functioning after a OOM fault without
+** having to check to see if the return from this routine is a valid pointer.
 */
 VdbeOp *sqlite3VdbeGetOp(Vdbe *p, int addr){
+  static VdbeOp dummy;
   assert( p->magic==VDBE_MAGIC_INIT );
+  if( addr<0 ) addr = p->nOp - 1;
   assert( (addr>=0 && addr<p->nOp) || p->db->mallocFailed );
-  return ((addr>=0 && addr<p->nOp)?(&p->aOp[addr]):0);
+  if( p->db->mallocFailed ){
+    return &dummy;
+  }else{
+    return &p->aOp[addr];
+  }
 }
 
 #if !defined(SQLITE_OMIT_EXPLAIN) || !defined(NDEBUG) \