]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Progress toward registerification of the constraint checking logic for
authordrh <drh@noemail.net>
Tue, 8 Jan 2008 02:57:55 +0000 (02:57 +0000)
committerdrh <drh@noemail.net>
Tue, 8 Jan 2008 02:57:55 +0000 (02:57 +0000)
INSERT and UPDATE. (CVS 4693)

FossilOrigin-Name: b9bf509e39f5ac38c2149d2a648f68e5df5ae9e3

manifest
manifest.uuid
src/delete.c
src/expr.c
src/insert.c
src/sqliteInt.h
src/update.c
src/vdbe.c
src/vdbeaux.c
src/vdbemem.c

index 06f45be0999822412bc139ade8e6feee8e71cdbf..02b0ee81f492d8b6404cce88ee0d1352db63e2b6 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Registerify\sthe\sAUTOINCREMENT\sprocessing\sand\sthe\sOP_IsNull\sand\sOP_NotNull\noperators.\s(CVS\s4692)
-D 2008-01-07T19:20:25
+C Progress\stoward\sregisterification\sof\sthe\sconstraint\schecking\slogic\sfor\nINSERT\sand\sUPDATE.\s(CVS\s4693)
+D 2008-01-08T02:57:56
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in 30789bf70614bad659351660d76b8e533f3340e9
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -90,13 +90,13 @@ F src/build.c 22b50a462d7b2be82e29071069d1c3daf29e953f
 F src/callback.c 77b302b0d41468dcda78c70e706e5b84577f0fa0
 F src/complete.c 4cf68fd75d60257524cbe74f87351b9848399131
 F src/date.c 49c5a6d2de6c12000905b4d36868b07d3011bbf6
-F src/delete.c 09c7b312a061d08df8a95b1f75cb10c6af14114a
+F src/delete.c d78e46b259a94a5f98a1bceee206c5fd21276ae7
 F src/experimental.c 1b2d1a6cd62ecc39610e97670332ca073c50792b
-F src/expr.c f84b4901dff3bacd08ece3f0de09318a5a298121
+F src/expr.c 6f2a852227ba2abd5ad0916f539c1f2159da28b4
 F src/func.c 996071cf0af9d967e58b69fce1909555059ebc7d
 F src/hash.c 45a7005aac044b6c86bd7e49c44bc15d30006d6c
 F src/hash.h 031cd9f915aff27e12262cb9eb570ac1b8326b53
-F src/insert.c 9c1a6501d79c9c4e674e0e2c3bc4a5207f9b3b95
+F src/insert.c 3a45102002b611aa1707bb6c6c5c148547d2630a
 F src/journal.c 807bed7a158979ac8d63953e1774e8d85bff65e2
 F src/legacy.c 4ac53191fad2e3c4d59bde1228879b2dc5a96d66
 F src/limits.h 71ab25f17e35e0a9f3f6f234b8ed49cc56731d35
@@ -136,7 +136,7 @@ F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c 5391e889384d2062249f668110d64ed16f601c4b
 F src/sqlite.h.in 2a7e3776534bbe6ff2cdc058f3abebe91e7e429f
 F src/sqlite3ext.h a93f59cdee3638dc0c9c086f80df743a4e68c3cb
-F src/sqliteInt.h 95cdddce11ee871fad1d91d6b6e405969dcc405f
+F src/sqliteInt.h 964754dcd508ddf0dd0b326072ad80678452e5c2
 F src/sqliteLimit.h ee4430f88f69bf63527967bb35ca52af7b0ccb1e
 F src/table.c 1aeb9eab57b4235db86fe15a35dec76fb445a9c4
 F src/tclsqlite.c 9923abeffc9b3d7dad58e92b319661521f60debf
@@ -164,18 +164,18 @@ F src/test_tclvar.c b2d1115e4d489179d3f029e765211b2ad527ba59
 F src/test_thread.c e297dd41db0b249646e69f97d36ec13e56e8b730
 F src/tokenize.c a4e04438c11fed2c67ec47fe3edbef9cca2d1b48
 F src/trigger.c 33071215111825634b85567bfc36c14094eebe54
-F src/update.c 38e9e4c27896df2d189927e3b483cadf5641f47c
+F src/update.c acd1c38dbbf253183fe2a8e5be0b3f3fee59be15
 F src/utf.c ef4b7d83bae533b76c3e1bf635b113fdad86a736
 F src/util.c 05f31144bbd3f1a24f4139ae029c42545cb72624
 F src/vacuum.c 3f34f278809bf3eb0b62ec46ff779e9c385b28f0
-F src/vdbe.c 3d849013558e52b2c85134fc6ed655d6dc00ace7
+F src/vdbe.c e71595acce83c585c31ac0551cee1c8cf9540fd2
 F src/vdbe.h bb128757b84280504a1243c450fd13ead248ede5
 F src/vdbeInt.h 31bd686595356284d5484592e2dc6e58025aa346
 F src/vdbeapi.c f14174843bf4be2c9afdf2ef48b61e7c3ac62d7c
-F src/vdbeaux.c 75b7d3e42c94310f28f6f7d3e08b69797fbe8a78
+F src/vdbeaux.c b6241be0277795ecd902743366434704f03b7636
 F src/vdbeblob.c b90f7494c408d47ce6835000b01e40b371e27baf
 F src/vdbefifo.c 334c838c8f42d61a94813d136019ee566b5dc2f6
-F src/vdbemem.c 123994fcd344993d2fb050a83b91b341bbbd08b4
+F src/vdbemem.c a94f3e9e85578ba457133ad3446fc6114a03ec5a
 F src/vtab.c 03014b2bfa8096ecac5fcdc80d34cd76e06af52a
 F src/where.c 306fafa709ced14b1c816d38b96a8f4446ec1eeb
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
@@ -604,7 +604,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 38020592f15c072e0d221ae2e0df13508ac4bd49
-R dde2d5dbca593f8bc201758cd5d40a3d
+P aa48867cfa04da265b906e5b583bc7ac6b6a1157
+R af4f73c6bffdbedd3861a3c5eb6d920e
 U drh
-Z 07f47472df3751ae71471b817e3e70f7
+Z 313f66697e8ae592eab31fdd061363d6
index 8eebc9f5c436757215104d42b959f5d7cea70a8c..bf6b8b32fb1d017008cb443ccb2d2e2fc194aa5f 100644 (file)
@@ -1 +1 @@
-aa48867cfa04da265b906e5b583bc7ac6b6a1157
\ No newline at end of file
+b9bf509e39f5ac38c2149d2a648f68e5df5ae9e3
\ No newline at end of file
index 65333f6356ffd0e91a980963843d03b051ec97ff..2a416e93d261656a3be1508f80fff84cf584edf5 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** in order to generate code for DELETE FROM statements.
 **
-** $Id: delete.c,v 1.152 2008/01/06 00:25:22 drh Exp $
+** $Id: delete.c,v 1.153 2008/01/08 02:57:56 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -492,13 +492,13 @@ void sqlite3GenerateRowIndexDelete(
   Vdbe *v,           /* Generate code into this VDBE */
   Table *pTab,       /* Table containing the row to be deleted */
   int iCur,          /* Cursor number for the table */
-  char *aIdxUsed     /* Only delete if aIdxUsed!=0 && aIdxUsed[i]!=0 */
+  int *aRegIdx       /* Only delete if aRegIdx!=0 && aRegIdx[i]>0 */
 ){
   int i;
   Index *pIdx;
 
   for(i=1, pIdx=pTab->pIndex; pIdx; i++, pIdx=pIdx->pNext){
-    if( aIdxUsed!=0 && aIdxUsed[i-1]==0 ) continue;
+    if( aRegIdx!=0 && aRegIdx[i-1]==0 ) continue;
     sqlite3GenerateIndexKey(v, pIdx, iCur);
     sqlite3VdbeAddOp1(v, OP_IdxDelete, iCur+i);
   }
index d332e4f8660deb3a094140345a6e12bfdcd5bd5a..651f1cd9ace724a6d177a40265cb89a23ca87a96 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.336 2008/01/07 19:20:25 drh Exp $
+** $Id: expr.c,v 1.337 2008/01/08 02:57:56 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -1944,15 +1944,12 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
   Vdbe *v = pParse->pVdbe;
   int op;
   int inReg = 0;
-  int stackChng = 0;
   int origTarget = target;
 
   assert( v!=0 || pParse->db->mallocFailed );
   if( v==0 ) return 0;
   if( target<0 ){
     target = ++pParse->nMem;
-  }else if( target==0 ){
-    stackChng = 1;
   }
 
   if( pExpr==0 ){
@@ -1979,9 +1976,8 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
     case TK_COLUMN: {
       if( pExpr->iTable<0 ){
         /* This only happens when coding check constraints */
-        assert( pParse->ckOffset>0 );
-        sqlite3VdbeAddOp1(v, OP_SCopy, -(pParse->ckOffset-pExpr->iColumn-1));
-        /* inReg = -(pParse->ckOffset-pExpr->iColumn-1); */
+        assert( pParse->ckBase>0 );
+        inReg = pExpr->iColumn + pParse->ckBase;
       }else{
         sqlite3ExprCodeGetColumn(v, pExpr->pTab,
                                  pExpr->iColumn, pExpr->iTable, target);
@@ -2052,7 +2048,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
       assert( to_op==OP_ToInt     || aff!=SQLITE_AFF_INTEGER );
       assert( to_op==OP_ToReal    || aff!=SQLITE_AFF_REAL    );
       sqlite3VdbeAddOp1(v, to_op, target);
-      stackChng = 0;
       inReg = target;
       break;
     }
@@ -2072,7 +2067,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
       sqlite3ExprCode(pParse, pExpr->pLeft, 0);
       sqlite3ExprCode(pParse, pExpr->pRight, 0);
       codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op, 0, 0);
-      stackChng = -1;
       break;
     }
     case TK_AND:
@@ -2099,12 +2093,9 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
       assert( TK_LSHIFT==OP_ShiftLeft );
       assert( TK_RSHIFT==OP_ShiftRight );
       assert( TK_CONCAT==OP_Concat );
-      r1 = sqlite3ExprCode(pParse, pExpr->pLeft, 0);
-      r2 = sqlite3ExprCode(pParse, pExpr->pRight, 0);
+      r1 = sqlite3ExprCode(pParse, pExpr->pLeft, -1);
+      r2 = sqlite3ExprCode(pParse, pExpr->pRight, -1);
       sqlite3VdbeAddOp3(v, op, r2, r1, target);
-      if( r1==0 ) stackChng--;
-      if( r2==0 ) stackChng--;
-      if( target==0 ) stackChng++;
       inReg = target;
       break;
     }
@@ -2129,7 +2120,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
       assert( TK_NOT==OP_Not );
       sqlite3ExprCode(pParse, pExpr->pLeft, 0);
       sqlite3VdbeAddOp0(v, op);
-      stackChng = 0;
       break;
     }
     case TK_ISNULL:
@@ -2142,7 +2132,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
       addr = sqlite3VdbeAddOp0(v, op);
       sqlite3VdbeAddOp2(v, OP_AddImm, target, -1);
       sqlite3VdbeJumpHere(v, addr);
-      stackChng = 0;
       inReg = target;
       break;
     }
@@ -2207,7 +2196,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
       }
       sqlite3VdbeAddOp4(v, OP_Function, constMask, nExpr, 0,
                         (char*)pDef, P4_FUNCDEF);
-      stackChng = 1-nExpr;
       break;
     }
 #ifndef SQLITE_OMIT_SUBQUERY
@@ -2224,7 +2212,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
     case TK_IN: {
       int j1, j2, j3, j4, j5;
       char affinity;
-      int ckOffset = pParse->ckOffset;
       int eType;
 
       eType = sqlite3FindInIndex(pParse, pExpr, 0);
@@ -2236,7 +2223,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
       affinity = comparisonAffinity(pExpr);
 
       sqlite3VdbeAddOp1(v, OP_Integer, 1);
-      pParse->ckOffset = (ckOffset ? (ckOffset+1) : 0);
 
       /* Code the <expr> from "<expr> IN (...)". The temporary table
       ** pExpr->iTable contains the values that make up the (...) set.
@@ -2282,7 +2268,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
     }
     case TK_UPLUS: {
       inReg = sqlite3ExprCode(pParse, pExpr->pLeft, origTarget);
-      stackChng = 0;
       break;
     }
     case TK_CASE: {
@@ -2349,7 +2334,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
          sqlite3VdbeAddOp2(v, OP_Goto, 0, pParse->trigStack->ignoreJump);
          VdbeComment((v, "raise(IGNORE)"));
       }
-      stackChng = 0;
       break;
     }
 #endif
@@ -2360,11 +2344,6 @@ int sqlite3ExprCode(Parse *pParse, Expr *pExpr, int target){
     }else{
       target = inReg;
     }
-    stackChng = 0;
-  }
-  if( pParse->ckOffset ){
-    pParse->ckOffset += stackChng;
-    assert( pParse->ckOffset );
   }
   return target;
 }
@@ -2443,7 +2422,6 @@ int sqlite3ExprCodeExprList(
 void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
   Vdbe *v = pParse->pVdbe;
   int op = 0;
-  int ckOffset = pParse->ckOffset;
   if( v==0 || pExpr==0 ) return;
   op = pExpr->op;
   switch( op ){
@@ -2518,7 +2496,6 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
       break;
     }
   }
-  pParse->ckOffset = ckOffset;
 }
 
 /*
@@ -2532,7 +2509,6 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
 void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
   Vdbe *v = pParse->pVdbe;
   int op = 0;
-  int ckOffset = pParse->ckOffset;
   if( v==0 || pExpr==0 ) return;
 
   /* The value of pExpr->op and op are related as follows:
@@ -2629,7 +2605,6 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
       break;
     }
   }
-  pParse->ckOffset = ckOffset;
 }
 
 /*
index c4fe10717c4ef4b7c06b03d8837d24c304007614..a9ba0ea2eefe74dcd907bc8860519cc93ff60d1d 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.215 2008/01/07 19:20:25 drh Exp $
+** $Id: insert.c,v 1.216 2008/01/08 02:57:56 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -373,6 +373,7 @@ void sqlite3Insert(
   int regRowid;         /* registers holding insert rowid */
   int regData;          /* register holding first column to insert */
   int regRecord;        /* Holds the assemblied row record */
+  int *aRegIdx = 0;     /* One register allocated to each index */
 
 
 #ifndef SQLITE_OMIT_TRIGGER
@@ -631,8 +632,18 @@ void sqlite3Insert(
 
   /* If this is not a view, open the table and and all indices */
   if( !isView ){
+    int nIdx;
+    int i;
+
     base = pParse->nTab;
-    sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
+    nIdx = sqlite3OpenTableAndIndices(pParse, pTab, base, OP_OpenWrite);
+    aRegIdx = sqlite3DbMallocZero(db, sizeof(int)*(nIdx+1));
+    if( aRegIdx==0 ){
+      goto insert_cleanup;
+    }
+    for(i=0; i<nIdx; i++){
+      aRegIdx[i] = ++pParse->nMem;
+    }
   }
 
   /* If the data source is a temporary table, then we have to create
@@ -830,9 +841,9 @@ void sqlite3Insert(
 #endif
     {
       sqlite3RegToStack(pParse, regIns, pTab->nCol+1);
-      sqlite3GenerateConstraintChecks(pParse, pTab, base, 0, keyColumn>=0,
+      sqlite3GenerateConstraintChecks(pParse, pTab, base, aRegIdx, keyColumn>=0,
                                      0, onError, endOfLoop);
-      sqlite3CompleteInsertion(pParse, pTab, base, 0,0,0,
+      sqlite3CompleteInsertion(pParse, pTab, base, aRegIdx,0,0,
                             (triggers_exist & TRIGGER_AFTER)!=0 ? newIdx : -1,
                             appendFlag);
     }
@@ -895,6 +906,7 @@ insert_cleanup:
   sqlite3ExprListDelete(pList);
   sqlite3SelectDelete(pSelect);
   sqlite3IdListDelete(pColumn);
+  sqlite3_free(aRegIdx);
 }
 
 /*
@@ -919,11 +931,11 @@ insert_cleanup:
 ** and rowidChng are 1.  isUpdate is true for UPDATEs and false for
 ** INSERTs and rowidChng is true if the record number is being changed.
 **
-** The code generated by this routine pushes additional entries onto
-** the stack which are the keys for new index entries for the new record.
-** The order of index keys is the same as the order of the indices on
-** the pTable->pIndex list.  A key is only created for index i if 
-** aIdxUsed!=0 and aIdxUsed[i]!=0.
+** The code generated by this routine store new index entries into
+** registers identified by aRegIdx[].  No index entry is created for
+** indices where aRegIdx[i]==0.  The order of indices in aRegIdx[] is
+** the same as the order of indices on the linked list of indices
+** attached to the table.
 **
 ** This routine also generates code to check constraints.  NOT NULL,
 ** CHECK, and UNIQUE constraints are all checked.  If a constraint fails,
@@ -968,7 +980,7 @@ insert_cleanup:
 ** cursor number "base".  All indices of pTab must also have open
 ** read/write cursors with cursor number base+i for the i-th cursor.
 ** Except, if there is no possibility of a REPLACE action then
-** cursors do not need to be open for indices where aIdxUsed[i]==0.
+** cursors do not need to be open for indices where aRegIdx[i]==0.
 **
 ** If the isUpdate flag is true, it means that the "base" cursor is
 ** initially pointing to an entry that is being updated.  The isUpdate
@@ -980,7 +992,7 @@ void sqlite3GenerateConstraintChecks(
   Parse *pParse,      /* The parser context */
   Table *pTab,        /* the table into which we are inserting */
   int base,           /* Index of a read/write cursor pointing at pTab */
-  char *aIdxUsed,     /* Which indices are used.  NULL means all are used */
+  int *aRegIdx,       /* Register used by each index.  0 for unused indices */
   int rowidChng,      /* True if the record number will change */
   int isUpdate,       /* True for UPDATE, False for INSERT */
   int overrideError,  /* Override onError to this if not OE_Default */
@@ -990,19 +1002,26 @@ void sqlite3GenerateConstraintChecks(
   Vdbe *v;
   int nCol;
   int onError;
-  int addr;
-  int extra;
+  int j1, j2, j3;     /* Address of jump instructions */
   int iCur;
   Index *pIdx;
   int seenReplace = 0;
-  int jumpInst1=0, jumpInst2;
   int hasTwoRowids = (isUpdate && rowidChng);
 
+  int regRowid, regData;
+
   v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
   assert( pTab->pSelect==0 );  /* This table is not a VIEW */
   nCol = pTab->nCol;
 
+  /* Copy rowids and data into registers 
+  */
+  regRowid = sqlite3StackToReg(pParse, nCol+1+hasTwoRowids);
+  sqlite3RegToStack(pParse, regRowid, nCol+1+hasTwoRowids);
+  if( hasTwoRowids ) regRowid++;
+  regData = regRowid+1;
+
   /* Test all NOT NULL constraints.
   */
   for(i=0; i<nCol; i++){
@@ -1019,8 +1038,7 @@ void sqlite3GenerateConstraintChecks(
     if( onError==OE_Replace && pTab->aCol[i].pDflt==0 ){
       onError = OE_Abort;
     }
-    sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol-1-i));
-    addr = sqlite3VdbeAddOp0(v, OP_NotNull);
+    j1 = sqlite3VdbeAddOp1(v, OP_NotNull, regData+i);
     assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
         || onError==OE_Ignore || onError==OE_Replace );
     switch( onError ){
@@ -1041,11 +1059,12 @@ void sqlite3GenerateConstraintChecks(
       }
       case OE_Replace: {
         sqlite3ExprCode(pParse, pTab->aCol[i].pDflt, 0);
+        sqlite3VdbeAddOp2(v, OP_Copy, 0, regData+i);
         sqlite3VdbeAddOp1(v, OP_Push, nCol-i);
         break;
       }
     }
-    sqlite3VdbeJumpHere(v, addr);
+    sqlite3VdbeJumpHere(v, j1);
   }
 
   /* Test all CHECK constraints
@@ -1053,11 +1072,8 @@ void sqlite3GenerateConstraintChecks(
 #ifndef SQLITE_OMIT_CHECK
   if( pTab->pCheck && (pParse->db->flags & SQLITE_IgnoreChecks)==0 ){
     int allOk = sqlite3VdbeMakeLabel(v);
-    assert( pParse->ckOffset==0 );
-    pParse->ckOffset = nCol;
+    pParse->ckBase = regData;
     sqlite3ExprIfTrue(pParse, pTab->pCheck, allOk, 1);
-    assert( pParse->ckOffset==nCol );
-    pParse->ckOffset = 0;
     onError = overrideError!=OE_Default ? overrideError : OE_Abort;
     if( onError==OE_Ignore ){
       sqlite3VdbeAddOp2(v, OP_Pop, nCol+1+hasTwoRowids, 0);
@@ -1082,12 +1098,11 @@ void sqlite3GenerateConstraintChecks(
     }
     
     if( isUpdate ){
-      sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
-      sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
-      jumpInst1 = sqlite3VdbeAddOp2(v, OP_Eq, 0, 0);
+      sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-1);
+      sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
+      j2 = sqlite3VdbeAddOp2(v, OP_Eq, 0, 0);
     }
-    sqlite3VdbeAddOp1(v, OP_SCopy, -nCol);
-    jumpInst2 = sqlite3VdbeAddOp2(v, OP_NotExists, base, 0);
+    j3 = sqlite3VdbeAddOp3(v, OP_NotExists, base, 0, regRowid);
     switch( onError ){
       default: {
         onError = OE_Abort;
@@ -1103,7 +1118,7 @@ void sqlite3GenerateConstraintChecks(
       case OE_Replace: {
         sqlite3GenerateRowIndexDelete(v, pTab, base, 0);
         if( isUpdate ){
-          sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+hasTwoRowids));
+          sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
           sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
         }
         seenReplace = 1;
@@ -1116,10 +1131,10 @@ void sqlite3GenerateConstraintChecks(
         break;
       }
     }
-    sqlite3VdbeJumpHere(v, jumpInst2);
+    sqlite3VdbeJumpHere(v, j3);
     if( isUpdate ){
-      sqlite3VdbeJumpHere(v, jumpInst1);
-      sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+1));
+      sqlite3VdbeJumpHere(v, j2);
+      sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-1);
       sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
     }
   }
@@ -1128,22 +1143,20 @@ void sqlite3GenerateConstraintChecks(
   ** index and making sure that duplicate entries do not already exist.
   ** Add the new records to the indices as we go.
   */
-  extra = -1;
   for(iCur=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, iCur++){
-    if( aIdxUsed && aIdxUsed[iCur]==0 ) continue;  /* Skip unused indices */
-    extra++;
+    if( aRegIdx[iCur]==0 ) continue;  /* Skip unused indices */
 
     /* Create a key for accessing the index entry */
-    sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+extra));
+    sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
     for(i=0; i<pIdx->nColumn; i++){
       int idx = pIdx->aiColumn[i];
       if( idx==pTab->iPKey ){
-        sqlite3VdbeAddOp1(v, OP_SCopy, -(i+extra+nCol+1));
+        sqlite3VdbeAddOp1(v, OP_SCopy, regRowid);
       }else{
-        sqlite3VdbeAddOp1(v, OP_SCopy, -(i+extra+nCol-idx));
+        sqlite3VdbeAddOp1(v, OP_SCopy, regData+idx);
       }
     }
-    jumpInst1 = sqlite3VdbeAddOp2(v, OP_MakeIdxRec, pIdx->nColumn, 0);
+    j2 = sqlite3VdbeAddOp3(v, OP_MakeIdxRec, pIdx->nColumn, 0, aRegIdx[iCur]);
     sqlite3IndexAffinityStr(v, pIdx);
 
     /* Find out what action to take in case there is an indexing conflict */
@@ -1161,8 +1174,9 @@ void sqlite3GenerateConstraintChecks(
     
 
     /* Check to see if the new index entry will be unique */
-    sqlite3VdbeAddOp1(v, OP_SCopy, -(extra+nCol+1+hasTwoRowids));
-    jumpInst2 = sqlite3VdbeAddOp2(v, OP_IsUnique, base+iCur+1, 0);
+    sqlite3VdbeAddOp1(v, OP_SCopy, aRegIdx[iCur]);
+    sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
+    j3 = sqlite3VdbeAddOp2(v, OP_IsUnique, base+iCur+1, 0);
 
     /* Generate code that executes if the new index entry is not unique */
     assert( onError==OE_Rollback || onError==OE_Abort || onError==OE_Fail
@@ -1199,7 +1213,7 @@ void sqlite3GenerateConstraintChecks(
       }
       case OE_Ignore: {
         assert( seenReplace==0 );
-        sqlite3VdbeAddOp2(v, OP_Pop, nCol+extra+3+hasTwoRowids, 0);
+        sqlite3VdbeAddOp2(v, OP_Pop, nCol+3+hasTwoRowids, 0);
         sqlite3VdbeAddOp2(v, OP_Goto, 0, ignoreDest);
         break;
       }
@@ -1207,17 +1221,18 @@ void sqlite3GenerateConstraintChecks(
         int iRowid = sqlite3StackToReg(pParse, 1);
         sqlite3GenerateRowDelete(pParse->db, v, pTab, base, iRowid, 0);
         if( isUpdate ){
-          sqlite3VdbeAddOp1(v, OP_SCopy, -(nCol+extra+1+hasTwoRowids));
+          sqlite3VdbeAddOp1(v, OP_SCopy, regRowid-hasTwoRowids);
           sqlite3VdbeAddOp2(v, OP_MoveGe, base, 0);
         }
         seenReplace = 1;
         break;
       }
     }
+    sqlite3VdbeJumpHere(v, j3);
+    sqlite3VdbeAddOp1(v, OP_Pop, 1);
 #if NULL_DISTINCT_FOR_UNIQUE
-    sqlite3VdbeJumpHere(v, jumpInst1);
+    sqlite3VdbeJumpHere(v, j2);
 #endif
-    sqlite3VdbeJumpHere(v, jumpInst2);
   }
 }
 
@@ -1235,7 +1250,7 @@ void sqlite3CompleteInsertion(
   Parse *pParse,      /* The parser context */
   Table *pTab,        /* the table into which we are inserting */
   int base,           /* Index of a read/write cursor pointing at pTab */
-  char *aIdxUsed,     /* Which indices are used.  NULL means all are used */
+  int *aRegIdx,       /* Register used by each index.  0 for unused indices */
   int rowidChng,      /* True if the record number will change */
   int isUpdate,       /* True for UPDATE, False for INSERT */
   int newIdx,         /* Index of NEW table for triggers.  -1 if none */
@@ -1252,8 +1267,8 @@ void sqlite3CompleteInsertion(
   assert( pTab->pSelect==0 );  /* This table is not a VIEW */
   for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
   for(i=nIdx-1; i>=0; i--){
-    if( aIdxUsed && aIdxUsed[i]==0 ) continue;
-    sqlite3VdbeAddOp2(v, OP_IdxInsert, base+i+1, 0);
+    if( aRegIdx[i]==0 ) continue;
+    sqlite3VdbeAddOp2(v, OP_IdxInsert, base+i+1, aRegIdx[i]);
   }
   sqlite3VdbeAddOp2(v, OP_MakeRecord, pTab->nCol, 0);
   sqlite3TableAffinityStr(v, pTab);
@@ -1287,8 +1302,10 @@ void sqlite3CompleteInsertion(
 ** Generate code that will open cursors for a table and for all
 ** indices of that table.  The "base" parameter is the cursor number used
 ** for the table.  Indices are opened on subsequent cursors.
+**
+** Return the number of indices on the table.
 */
-void sqlite3OpenTableAndIndices(
+int sqlite3OpenTableAndIndices(
   Parse *pParse,   /* Parsing context */
   Table *pTab,     /* Table to be opened */
   int base,        /* Cursor number assigned to the table */
@@ -1299,7 +1316,7 @@ void sqlite3OpenTableAndIndices(
   Index *pIdx;
   Vdbe *v;
 
-  if( IsVirtual(pTab) ) return;
+  if( IsVirtual(pTab) ) return 0;
   iDb = sqlite3SchemaToIndex(pParse->db, pTab->pSchema);
   v = sqlite3GetVdbe(pParse);
   assert( v!=0 );
@@ -1314,6 +1331,7 @@ void sqlite3OpenTableAndIndices(
   if( pParse->nTab<=base+i ){
     pParse->nTab = base+i;
   }
+  return i-1;
 }
 
 
@@ -1614,7 +1632,7 @@ static int xferOptimization(
     VdbeComment((v, "%s", pDestIdx->zName));
     addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0);
     sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, 0);
-    sqlite3VdbeAddOp2(v, OP_IdxInsert, iDest, 1);
+    sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, 0, 1);
     sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1);
     sqlite3VdbeJumpHere(v, addr1);
   }
index d5c02e74df8b393b972f88afef171a385376b3c2..b4e236cb7edfdc149e2db2942799b71c1f5fb8fd 100644 (file)
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.641 2008/01/06 00:25:22 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.642 2008/01/08 02:57:56 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -1389,7 +1389,7 @@ struct Parse {
   int nTab;            /* Number of previously allocated VDBE cursors */
   int nMem;            /* Number of memory cells used so far */
   int nSet;            /* Number of sets used so far */
-  int ckOffset;        /* Stack offset to data used by CHECK constraints */
+  int ckBase;          /* Base register of data during check constraints */
   u32 writeMask;       /* Start a write transaction on these databases */
   u32 cookieMask;      /* Bitmask of schema verified databases */
   int cookieGoto;      /* Address of OP_Goto to cookie verifier subroutine */
@@ -1774,11 +1774,11 @@ int sqlite3ExprIsConstantOrFunction(Expr*);
 int sqlite3ExprIsInteger(Expr*, int*);
 int sqlite3IsRowid(const char*);
 void sqlite3GenerateRowDelete(sqlite3*, Vdbe*, Table*, int, int, int);
-void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, char*);
+void sqlite3GenerateRowIndexDelete(Vdbe*, Table*, int, int*);
 void sqlite3GenerateIndexKey(Vdbe*, Index*, int);
-void sqlite3GenerateConstraintChecks(Parse*,Table*,int,char*,int,int,int,int);
-void sqlite3CompleteInsertion(Parse*, Table*, int, char*, int, int, int, int);
-void sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
+void sqlite3GenerateConstraintChecks(Parse*,Table*,int,int*,int,int,int,int);
+void sqlite3CompleteInsertion(Parse*, Table*, int, int*, int, int, int, int);
+int sqlite3OpenTableAndIndices(Parse*, Table*, int, int);
 void sqlite3BeginWriteOperation(Parse*, int, int);
 Expr *sqlite3ExprDup(sqlite3*,Expr*);
 void sqlite3TokenCopy(sqlite3*,Token*, Token*);
index d31d0b93eb3e4a80337399a1348c7a3e021ee63b..afb5e89addffb0955c2d47ba05da1ce83b11c740 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle UPDATE statements.
 **
-** $Id: update.c,v 1.162 2008/01/06 00:25:22 drh Exp $
+** $Id: update.c,v 1.163 2008/01/08 02:57:56 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -90,11 +90,9 @@ void sqlite3Update(
   Vdbe *v;               /* The virtual database engine */
   Index *pIdx;           /* For looping over indices */
   int nIdx;              /* Number of indices that need updating */
-  int nIdxTotal;         /* Total number of indices */
   int iCur;              /* VDBE Cursor number of pTab */
   sqlite3 *db;           /* The database structure */
-  Index **apIdx = 0;     /* An array of indices that need updating too */
-  char *aIdxUsed = 0;    /* aIdxUsed[i]==1 if the i-th index is used */
+  int *aRegIdx = 0;      /* One register assigned to each index to be updated */
   int *aXRef = 0;        /* aXRef[i] is the index in pChanges->a[] of the
                          ** an expression for the i-th column of the table.
                          ** aXRef[i]==-1 if the i-th column is not changed. */
@@ -227,40 +225,30 @@ void sqlite3Update(
 #endif
   }
 
-  /* Allocate memory for the array apIdx[] and fill it with pointers to every
-  ** index that needs to be updated.  Indices only need updating if their
-  ** key includes one of the columns named in pChanges or if the record
-  ** number of the original table entry is changing.
+  /* Allocate memory for the array aRegIdx[].  There is one entry in the
+  ** array for each index associated with table being updated.  Fill in
+  ** the value with a register number for indices that are to be used
+  ** and with zero for unused indices.
   */
-  for(nIdx=nIdxTotal=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdxTotal++){
-    if( chngRowid ){
-      i = 0;
-    }else {
-      for(i=0; i<pIdx->nColumn; i++){
-        if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
-      }
-    }
-    if( i<pIdx->nColumn ) nIdx++;
-  }
-  if( nIdxTotal>0 ){
-    apIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx + nIdxTotal );
-    if( apIdx==0 ) goto update_cleanup;
-    aIdxUsed = (char*)&apIdx[nIdx];
+  for(nIdx=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, nIdx++){}
+  if( nIdx>0 ){
+    aRegIdx = sqlite3DbMallocRaw(db, sizeof(Index*) * nIdx );
+    if( aRegIdx==0 ) goto update_cleanup;
   }
-  for(nIdx=j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+  for(j=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, j++){
+    int reg;
     if( chngRowid ){
-      i = 0;
+      reg = ++pParse->nMem;
     }else{
+      reg = 0;
       for(i=0; i<pIdx->nColumn; i++){
-        if( aXRef[pIdx->aiColumn[i]]>=0 ) break;
+        if( aXRef[pIdx->aiColumn[i]]>=0 ){
+          reg = ++pParse->nMem;
+          break;
+        }
       }
     }
-    if( i<pIdx->nColumn ){
-      apIdx[nIdx++] = pIdx;
-      aIdxUsed[j] = 1;
-    }else{
-      aIdxUsed[j] = 0;
-    }
+    aRegIdx[j] = reg;
   }
 
   /* Begin generating code.
@@ -380,7 +368,7 @@ void sqlite3Update(
       }
     }
     for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
-      if( openAll || aIdxUsed[i] ){
+      if( openAll || aRegIdx[i]>0 ){
         KeyInfo *pKey = sqlite3IndexKeyinfo(pParse, pIdx);
         sqlite3VdbeAddOp4(v, OP_OpenWrite, iCur+i+1, pIdx->tnum, iDb,
                        (char*)pKey, P4_KEYINFO_HANDOFF);
@@ -486,12 +474,12 @@ void sqlite3Update(
 
     /* Do constraint checks
     */
-    sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aIdxUsed, chngRowid, 1,
+    sqlite3GenerateConstraintChecks(pParse, pTab, iCur, aRegIdx, chngRowid, 1,
                                    onError, addr);
 
     /* Delete the old indices for the current record.
     */
-    sqlite3GenerateRowIndexDelete(v, pTab, iCur, aIdxUsed);
+    sqlite3GenerateRowIndexDelete(v, pTab, iCur, aRegIdx);
 
     /* If changing the record number, delete the old record.
     */
@@ -501,7 +489,7 @@ void sqlite3Update(
 
     /* Create the new index entries and the new record.
     */
-    sqlite3CompleteInsertion(pParse, pTab, iCur, aIdxUsed, chngRowid, 1, -1, 0);
+    sqlite3CompleteInsertion(pParse, pTab, iCur, aRegIdx, chngRowid, 1, -1, 0);
   }
 
   /* Increment the row counter 
@@ -526,7 +514,7 @@ void sqlite3Update(
 
   /* Close all tables */
   for(i=0, pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext, i++){
-    if( openAll || aIdxUsed[i] ){
+    if( openAll || aRegIdx[i]>0 ){
       sqlite3VdbeAddOp2(v, OP_Close, iCur+i+1, 0);
     }
   }
@@ -549,7 +537,7 @@ void sqlite3Update(
 
 update_cleanup:
   sqlite3AuthContextPop(&sContext);
-  sqlite3_free(apIdx);
+  sqlite3_free(aRegIdx);
   sqlite3_free(aXRef);
   sqlite3SrcListDelete(pTabList);
   sqlite3ExprListDelete(pChanges);
index 58b1b1454fe0eb35bc1f6a58d371a5f428346b01..7ac12ffeae16b92ca6c6bde5718b87c5d3074704 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.687 2008/01/07 19:20:25 drh Exp $
+** $Id: vdbe.c,v 1.688 2008/01/08 02:57:56 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -717,6 +717,26 @@ int sqlite3VdbeExec(
           pOut = &p->aMem[pOp->p2];
         }
       }
+    }else if( (opProperty & OPFLG_IN2)!=0 ){
+      assert( pOp->p2>=0 );
+      if( pOp->p2==0 ){
+        pIn2 = pTos;
+        nPop = 1;
+      }else{
+        assert( pOp->p2<=p->nMem );
+        pIn2 = &p->aMem[pOp->p2];
+        REGISTER_TRACE(pOp->p2, pIn2);
+      }
+    }else if( (opProperty & OPFLG_IN3)!=0 ){
+      assert( pOp->p3>=0 );
+      if( pOp->p3==0 ){
+        pIn3 = pTos;
+        nPop = 1;
+      }else{
+        assert( pOp->p3<=p->nMem );
+        pIn3 = &p->aMem[pOp->p3];
+        REGISTER_TRACE(pOp->p3, pIn3);
+      }
     }
 
     switch( pOp->opcode ){
@@ -4166,67 +4186,60 @@ case OP_Next: {        /* no-push, jump */
   break;
 }
 
-/* Opcode: IdxInsert P1 P2 *
+/* Opcode: IdxInsert P1 P2 P3
 **
-** The top of the stack holds a SQL index key made using either the
-** MakeIdxRec or MakeRecord instructions.  This opcode writes that key
+** Register P2 holds a SQL index key made using the
+** MakeIdxRec instructions.  This opcode writes that key
 ** into the index P1.  Data for the entry is nil.
 **
-** P2 is a flag that provides a hint to the b-tree layer that this
+** P3 is a flag that provides a hint to the b-tree layer that this
 ** insert is likely to be an append.
 **
 ** This instruction only works for indices.  The equivalent instruction
 ** for tables is OP_Insert.
 */
-case OP_IdxInsert: {        /* no-push */
+case OP_IdxInsert: {        /* no-push, in2 */
   int i = pOp->p1;
   Cursor *pC;
   BtCursor *pCrsr;
-  assert( pTos>=p->aStack );
   assert( i>=0 && i<p->nCursor );
   assert( p->apCsr[i]!=0 );
-  assert( pTos->flags & MEM_Blob );
+  assert( pIn2->flags & MEM_Blob );
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     assert( pC->isTable==0 );
-    rc = ExpandBlob(pTos);
+    rc = ExpandBlob(pIn2);
     if( rc==SQLITE_OK ){
-      int nKey = pTos->n;
-      const char *zKey = pTos->z;
-      rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p2);
+      int nKey = pIn2->n;
+      const char *zKey = pIn2->z;
+      rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0, 0, pOp->p3);
       assert( pC->deferredMoveto==0 );
       pC->cacheStatus = CACHE_STALE;
     }
   }
-  Release(pTos);
-  pTos--;
   break;
 }
 
-/* Opcode: IdxDelete P1 * *
+/* Opcode: IdxDelete P1 P2 *
 **
-** The top of the stack is an index key built using the either the
-** MakeIdxRec or MakeRecord opcodes.
-** This opcode removes that entry from the index.
+** The content of register P2 is an index key built using the either the
+** MakeIdxRec opcode.  Removes that entry from the index.
 */
-case OP_IdxDelete: {        /* no-push */
+case OP_IdxDelete: {        /* no-push, in2 */
   int i = pOp->p1;
   Cursor *pC;
   BtCursor *pCrsr;
-  assert( pTos>=p->aStack );
-  assert( pTos->flags & MEM_Blob );
+  assert( pIn2->flags & MEM_Blob );
   assert( i>=0 && i<p->nCursor );
   assert( p->apCsr[i]!=0 );
   if( (pCrsr = (pC = p->apCsr[i])->pCursor)!=0 ){
     int res;
-    rc = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, 0, &res);
+    rc = sqlite3BtreeMoveto(pCrsr, pIn2->z, pIn2->n, 0, &res);
     if( rc==SQLITE_OK && res==0 ){
       rc = sqlite3BtreeDelete(pCrsr);
     }
     assert( pC->deferredMoveto==0 );
     pC->cacheStatus = CACHE_STALE;
   }
-  Release(pTos);
-  pTos--;
   break;
 }
 
index e6d489f08fe6986639ae9e71abdba8548a05143d..391b0d0dca1645ac5a9d4ce8efe1dd6172ca6a3a 100644 (file)
@@ -821,12 +821,14 @@ int sqlite3VdbeList(
       pMem++;
   
       pMem->flags = MEM_Null;                       /* Comment */
+#ifdef SQLITE_DEBUG
       if( pOp->zComment ){
         pMem->flags = MEM_Str|MEM_Term;
         pMem->z = pOp->zComment;
         pMem->n = strlen(pMem->z);
         pMem->enc = SQLITE_UTF8;
       }
+#endif
     }
 
     p->nResColumn = 8 - 5*(p->explain-1);
index 9da14dd3265d12e4cafa9b260beb9896b6780381..18a29ab3e909a66ba7779096216eee3f6613a4b1 100644 (file)
@@ -529,7 +529,7 @@ int sqlite3VdbeMemMove(Mem *pTo, Mem *pFrom){
   }
   pFrom->flags = MEM_Null;
   pFrom->xDel = 0;
-  if( pTo->flags & MEM_Ephem ){
+  if( 0 /* pTo->flags & MEM_Ephem */ ){
     rc = sqlite3VdbeMemMakeWriteable(pTo);
   }else{
     rc = SQLITE_OK;