]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Combine cases 3 and 4 in where.c, since case 4 is now a special case of case 3. ...
authordanielk1977 <danielk1977@noemail.net>
Fri, 18 Apr 2008 10:25:24 +0000 (10:25 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Fri, 18 Apr 2008 10:25:24 +0000 (10:25 +0000)
FossilOrigin-Name: 9a976819246eb558ba43429f8889972c4a4bce9d

manifest
manifest.uuid
src/vdbe.c
src/where.c

index 5a456e3c1a27bbc96e71c79e008bb5c197ac1de1..5f4675a8a5868b5ccccaf17c3fa037a7d55e3d32 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Allow\sOP_MoveGt\sand\ssimilar\sto\suse\san\sarray\sof\sregisters\sinstead\sof\sa\sserialized\srecord.\sModify\sone\stype\sof\sindex\srange\sscan\sto\suse\sthis.\s(CVS\s5028)
-D 2008-04-18T09:01:16
+C Combine\scases\s3\sand\s4\sin\swhere.c,\ssince\scase\s4\sis\snow\sa\sspecial\scase\sof\scase\s3.\s(CVS\s5029)
+D 2008-04-18T10:25:24
 F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
 F Makefile.in 25b3282a4ac39388632c2fb0e044ff494d490952
 F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
@@ -174,7 +174,7 @@ F src/update.c 57282dae1ffffaf4aedc3201ed77f8ef09be4f45
 F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b
 F src/util.c 943caa4071488b20ed90588f0704c6825f91836b
 F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
-F src/vdbe.c 6b3a2273255d7527f17a2f4c123bcaa02969ddc0
+F src/vdbe.c 892a871879c80a905eaa0d1f7bd24e0221bad56d
 F src/vdbe.h bfd84bda447f39cb599302c7ec85067dae20453c
 F src/vdbeInt.h 05316345da487b0cf540482576f9ae3337d133cd
 F src/vdbeapi.c 0e1b5a808bb0e556f2a975eb7d11fd3153e922bf
@@ -183,7 +183,7 @@ F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb
 F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
 F src/vdbemem.c 237e61216381998ff71c6431e5e7bd03386f6225
 F src/vtab.c f5e78bf73df3b0c1b53861109c1b2e0800b108cc
-F src/where.c e6850aa2fbe655c15914e9b102a20abf2834ab89
+F src/where.c 011f866cf0f05c832eea5a30e079eb108253ac64
 F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
 F test/all.test d56a3ca8acdf761204aff0a2e7aa5eb8e11b31e6
@@ -631,7 +631,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
-P 4a72a7bb9c5793cdaf4ee038482053e042d8db54
-R 63ab958aeb1a64fb1b489284d8bf24a2
+P c448f15aa5ed3dec511426775e893efea324faa1
+R 2fd8586df4700418bc96607c52d60fc1
 U danielk1977
-Z ffb6897ecd3dcda79af541b97309bd4b
+Z 63b2d6660f8e65e3dba8e17623deefd8
index 83af5c671c14bd1f20e7e679748815e463eb15af..eb2840abdf2bf282e9d9e731cc4b92b9bc385ce2 100644 (file)
@@ -1 +1 @@
-c448f15aa5ed3dec511426775e893efea324faa1
\ No newline at end of file
+9a976819246eb558ba43429f8889972c4a4bce9d
\ No newline at end of file
index 16cd578b7af1cbef8ed4fbdc630a78f0bbeafc4e..62a8c1a4327a099db5715b4fe798b18bfba0b49f 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.731 2008/04/18 09:01:16 danielk1977 Exp $
+** $Id: vdbe.c,v 1.732 2008/04/18 10:25:24 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -2148,6 +2148,7 @@ case OP_Affinity: {
   Mem *pRec;
 
   for(pRec=pData0; pRec<=pLast; pRec++){
+    ExpandBlob(pRec);
     applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
   }
   break;
@@ -2790,13 +2791,16 @@ case OP_Close: {
   break;
 }
 
-/* Opcode: MoveGe P1 P2 P3 * *
+/* Opcode: MoveGe P1 P2 P3 P4 *
 **
-** Use the value in register P3 as a key.  Reposition
-** cursor P1 so that it points to the smallest entry that is greater
-** than or equal to the key in register P3.
-** If there are no records greater than or equal to the key and P2 
-** is not zero, then jump to P2.
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
+** use the integer value in register P3 as a key. If cursor P1 refers 
+** to an SQL index, then P3 is the first in an array of P4 registers 
+** that are used as an unpacked index key. 
+**
+** Reposition cursor P1 so that  it points to the smallest entry that 
+** is greater than or equal to the key value. If there are no records 
+** greater than or equal to the key and P2 is not zero, then jump to P2.
 **
 ** A special feature of this opcode (and different from the
 ** related OP_MoveGt, OP_MoveLt, and OP_MoveLe) is that if P2 is
@@ -2807,37 +2811,42 @@ case OP_Close: {
 **
 ** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe
 */
-/* Opcode: MoveGt P1 P2 P3 * *
+/* Opcode: MoveGt P1 P2 P3 P4 *
+**
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
+** use the integer value in register P3 as a key. If cursor P1 refers 
+** to an SQL index, then P3 is the first in an array of P4 registers 
+** that are used as an unpacked index key. 
 **
-** Use the value in register P3 as a key.  Reposition
-** cursor P1 so that it points to the smallest entry that is greater
-** than the key in register P3.
-** If there are no records greater than the key 
-** then jump to P2.
+** Reposition cursor P1 so that  it points to the smallest entry that 
+** is greater than the key value. If there are no records greater than 
+** the key and P2 is not zero, then jump to P2.
 **
 ** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe
 */
-/* Opcode: MoveLt P1 P2 P3 * * 
+/* Opcode: MoveLt P1 P2 P3 P4 * 
+**
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
+** use the integer value in register P3 as a key. If cursor P1 refers 
+** to an SQL index, then P3 is the first in an array of P4 registers 
+** that are used as an unpacked index key. 
 **
-** Use the value in register P3 as a key.  Reposition
-** cursor P1 so that it points to the largest entry that is less
-** than the key in register P3.
-** If there are no records less than the key
-** then jump to P2.
+** Reposition cursor P1 so that  it points to the largest entry that 
+** is less than the key value. If there are no records less than 
+** the key and P2 is not zero, then jump to P2.
 **
 ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe
 */
 /* Opcode: MoveLe P1 P2 P3 P4 *
 **
-** P4 is always an integer value. If it is zero, then use the value in
-** register P3 as a key. Reposition cursor P1 so that it points to the
-** largest entry that is less than or equal to the key. If there are no 
-** records less than or eqal to the key then jump to P2.
+** If cursor P1 refers to an SQL table (B-Tree that uses integer keys), 
+** use the integer value in register P3 as a key. If cursor P1 refers 
+** to an SQL index, then P3 is the first in an array of P4 registers 
+** that are used as an unpacked index key. 
 **
-** If the integer value in operand P4 is non-zero, then P3 is the first
-** of a contiguous array of P4 memory cells that form an unpacked index
-** key. In this case the unpacked key is used instead of the value of
-** register P3 in the procedure described above.
+** Reposition cursor P1 so that it points to the largest entry that 
+** is less than or equal to the key value. If there are no records 
+** less than or equal to the key and P2 is not zero, then jump to P2.
 **
 ** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
 */
@@ -2872,20 +2881,16 @@ case OP_MoveGt: {       /* jump, in3 */
       pC->lastRowid = iKey;
       pC->rowidIsValid = res==0;
     }else{
-      int nField = ((pOp->p4type==P4_INT32)?pOp->p4.i:0);
-      assert( pIn3->flags&MEM_Blob || nField>0 );
-      if( nField==0 ){
-        ExpandBlob(pIn3);
-        rc = sqlite3BtreeMoveto(pC->pCursor, pIn3->z, 0, pIn3->n, 0, &res);
-      }else{
-        UnpackedRecord r;
-        r.pKeyInfo = pC->pKeyInfo;
-        r.nField = nField;
-        r.needFree = 0;
-        r.needDestroy = 0;
-        r.aMem = &p->aMem[pOp->p3];
-        rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res);
-      }
+      UnpackedRecord r;
+      int nField = pOp->p4.i;
+      assert( pOp->p4type==P4_INT32 );
+      assert( nField>0 );
+      r.pKeyInfo = pC->pKeyInfo;
+      r.nField = nField;
+      r.needFree = 0;
+      r.needDestroy = 0;
+      r.aMem = &p->aMem[pOp->p3];
+      rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res);
       if( rc!=SQLITE_OK ){
         goto abort_due_to_error;
       }
index 0ccc601663cb3108b271d02595825b01fe8ee62e..5bce2262eec876c4c0eb237cf0b577b04f6f7a7f 100644 (file)
@@ -16,7 +16,7 @@
 ** so is applicable.  Because this module is responsible for selecting
 ** indices, you might also think of this module as the "query optimizer".
 **
-** $Id: where.c,v 1.300 2008/04/18 09:01:16 danielk1977 Exp $
+** $Id: where.c,v 1.301 2008/04/18 10:25:24 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -1727,27 +1727,17 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
 }
 
 /*
-** Generate code that builds a probe for an index.
-**
-** There should be nColumn values on the stack.  The index
-** to be probed is pIdx.  Pop the values from the stack and
-** replace them all with a single record that is the index
-** problem.
+** Apply the affinities associated with the first n columns of index
+** pIdx to the values in the n registers starting at base.
 */
-static void buildIndexProbe(
-  Parse *pParse,  /* Parsing and code generation context */
-  int nColumn,    /* The number of columns to check for NULL */
-  Index *pIdx,    /* Index that we will be searching */
-  int regSrc,     /* Take values from this register */
-  int regDest     /* Write the result into this register */
-){
-  Vdbe *v = pParse->pVdbe;
-  assert( regSrc>0 );
-  assert( regDest>0 );
-  assert( v!=0 );
-  sqlite3VdbeAddOp3(v, OP_MakeRecord, regSrc, nColumn, regDest);
-  sqlite3IndexAffinityStr(v, pIdx);
-  sqlite3ExprCacheAffinityChange(pParse, regSrc, nColumn);
+static void codeApplyAffinity(Parse *pParse, int base, int n, Index *pIdx){
+  if( n>0 ){
+    Vdbe *v = pParse->pVdbe;
+    assert( v!=0 );
+    sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
+    sqlite3IndexAffinityStr(v, pIdx);
+    sqlite3ExprCacheAffinityChange(pParse, base, n);
+  }
 }
 
 
@@ -2463,30 +2453,45 @@ WhereInfo *sqlite3WhereBegin(
         sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
         sqlite3ReleaseTempReg(pParse, r1);
       }
-    }else if( pLevel->flags & WHERE_COLUMN_RANGE ){
-      /* Case 3: The WHERE clause term that refers to the right-most
-      **         column of the index is an inequality.  For example, if
-      **         the index is on (x,y,z) and the WHERE clause is of the
-      **         form "x=5 AND y<10" then this case is used.  Only the
-      **         right-most column can be an inequality - the rest must
-      **         use the "==" and "IN" operators.
+    }else if( pLevel->flags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
+      /* Case 3: A scan using an index.
+      **
+      **         The WHERE clause may contain one or more equality 
+      **         terms ("==" or "IN" operators) that refer to the N
+      **         left-most columns of the index. It may also contain
+      **         inequality constraints (>, <, >= or <=) on the indexed
+      **         column that immediately follows the N equalities. Only 
+      **         the right-most column can be an inequality - the rest must
+      **         use the "==" and "IN" operators. For example, if the 
+      **         index is on (x,y,z), then the following clauses are all 
+      **         optimized:
+      **
+      **            x=5
+      **            x=5 AND y=10
+      **            x=5 AND y<10
+      **            x=5 AND y>5 AND y<10
+      **            x=5 AND y=5 AND z<=10
+      **
+      **         This cannot be optimized:
+      **
+      **            x=5 AND z<10
       **
       **         This case is also used when there are no WHERE clause
       **         constraints but an index is selected anyway, in order
       **         to force the output order to conform to an ORDER BY.
-      */
+      */  
       int aStartOp[] = {
         0,
         0,
-        OP_Rewind,           /* 2: (!start_constraints && startEq && !bRev) */
-        OP_Last,             /* 3: (!start_constraints && startEq && bRev)  */
+        OP_Rewind,           /* 2: (!start_constraints && startEq &&  !bRev) */
+        OP_Last,             /* 3: (!start_constraints && startEq &&   bRev) */
         OP_MoveGt,           /* 4: (start_constraints  && !startEq && !bRev) */
-        OP_MoveLt,           /* 5: (start_constraints  && !startEq && bRev) */
+        OP_MoveLt,           /* 5: (start_constraints  && !startEq &&  bRev) */
         OP_MoveGe,           /* 6: (start_constraints  &&  startEq && !bRev) */
-        OP_MoveLe            /* 7: (start_constraints  &&  startEq && bRev) */
+        OP_MoveLe            /* 7: (start_constraints  &&  startEq &&  bRev) */
       };
       int aEndOp[] = {
-        OP_Noop,             /* 0: () */
+        OP_Noop,             /* 0: (!end_constraints) */
         OP_IdxGE,            /* 1: (end_constraints && !bRev) */
         OP_IdxLT             /* 2: (end_constraints && bRev) */
       };
@@ -2526,7 +2531,7 @@ WhereInfo *sqlite3WhereBegin(
         isMinQuery = 1;
       }
 
-      /* Find the inequality constraint terms for the start and end 
+      /* Find any inequality constraint terms for the start and end 
       ** of the range. 
       */
       if( pLevel->flags & WHERE_TOP_LIMIT ){
@@ -2565,8 +2570,7 @@ WhereInfo *sqlite3WhereBegin(
         startEq = 0;
         start_constraints = 1;
       }
-      sqlite3VdbeAddOp2(v, OP_Affinity, regBase, (int)ptr);
-      sqlite3IndexAffinityStr(v, pIdx);
+      codeApplyAffinity(pParse, regBase, (int)ptr, pIdx);
       op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
       sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase, ptr, P4_INT32);
 
@@ -2577,10 +2581,9 @@ WhereInfo *sqlite3WhereBegin(
       if( pRangeEnd ){
         sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq);
         sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
+        codeApplyAffinity(pParse, regBase, nEq+1, pIdx);
         ptr++;
       }
-      sqlite3VdbeAddOp2(v, OP_Affinity, regBase, (int)ptr);
-      sqlite3IndexAffinityStr(v, pIdx);
 
       /* Top of the loop body */
       pLevel->p2 = sqlite3VdbeCurrentAddr(v);
@@ -2615,77 +2618,6 @@ WhereInfo *sqlite3WhereBegin(
       pLevel->p1 = iIdxCur;
       disableTerm(pLevel, pRangeStart);
       disableTerm(pLevel, pRangeEnd);
-    }else if( pLevel->flags & WHERE_COLUMN_EQ ){
-      /* Case 4:  There is an index and all terms of the WHERE clause that
-      **          refer to the index using the "==" or "IN" operators.
-      */
-      int start;
-      int nEq = pLevel->nEq;
-      int isMinQuery = 0;      /* If this is an optimized SELECT min(x) ... */
-      int regBase;             /* Base register of array holding constraints */
-      int r1;
-
-      /* Generate code to evaluate all constraint terms using == or IN
-      ** and leave the values of those terms on the stack.
-      */
-      regBase = codeAllEqualityTerms(pParse, pLevel, &wc, notReady, 1);
-      nxt = pLevel->nxt;
-
-      if( (wflags&WHERE_ORDERBY_MIN)!=0
-       && (pLevel->flags&WHERE_ORDERBY) 
-       && (pIdx->nColumn>nEq)
-       && (pOrderBy->a[0].pExpr->iColumn==pIdx->aiColumn[nEq])
-      ){
-        isMinQuery = 1;
-        buildIndexProbe(pParse, nEq, pIdx, regBase, pLevel->iMem);
-        sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
-        r1 = ++pParse->nMem;
-        buildIndexProbe(pParse, nEq+1, pIdx, regBase, r1);
-      }else{
-        /* Generate a single key that will be used to both start and 
-        ** terminate the search
-        */
-        r1 = pLevel->iMem;
-        buildIndexProbe(pParse, nEq, pIdx, regBase, r1);
-      }
-
-      /* Generate code (1) to move to the first matching element of the table.
-      ** Then generate code (2) that jumps to "nxt" after the cursor is past
-      ** the last matching element of the table.  The code (1) is executed
-      ** once to initialize the search, the code (2) is executed before each
-      ** iteration of the scan to see if the scan has finished. */
-      if( bRev ){
-        /* Scan in reverse order */
-        int op;
-        if( isMinQuery ){
-          op = OP_MoveLt;
-        }else{
-          op = OP_MoveLe;
-        }
-        sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1);
-        start = sqlite3VdbeAddOp3(v, OP_IdxLT, iIdxCur, nxt, pLevel->iMem);
-        pLevel->op = OP_Prev;
-      }else{
-        /* Scan in the forward order */
-        int op;
-        if( isMinQuery ){
-          op = OP_MoveGt;
-        }else{
-          op = OP_MoveGe;
-        }
-        sqlite3VdbeAddOp3(v, op, iIdxCur, nxt, r1);
-        start = sqlite3VdbeAddOp3(v, OP_IdxGE, iIdxCur, nxt, pLevel->iMem);
-        sqlite3VdbeChangeP5(v, 1);
-        pLevel->op = OP_Next;
-      }
-      if( !omitTable ){
-        r1 = sqlite3GetTempReg(pParse);
-        sqlite3VdbeAddOp2(v, OP_IdxRowid, iIdxCur, r1);
-        sqlite3VdbeAddOp3(v, OP_MoveGe, iCur, 0, r1);  /* Deferred seek */
-        sqlite3ReleaseTempReg(pParse, r1);
-      }
-      pLevel->p1 = iIdxCur;
-      pLevel->p2 = start;
     }else{
       /* Case 5:  There is no usable index.  We must do a complete
       **          scan of the entire table.