mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-16 23:02:26 +03:00
Combine cases 3 and 4 in where.c, since case 4 is now a special case of case 3. (CVS 5029)
FossilOrigin-Name: 9a976819246eb558ba43429f8889972c4a4bce9d
This commit is contained in:
14
manifest
14
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)
|
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-18T09:01:16
|
D 2008-04-18T10:25:24
|
||||||
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
F Makefile.arm-wince-mingw32ce-gcc ac5f7b2cef0cd850d6f755ba6ee4ab961b1fadf7
|
||||||
F Makefile.in 25b3282a4ac39388632c2fb0e044ff494d490952
|
F Makefile.in 25b3282a4ac39388632c2fb0e044ff494d490952
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -174,7 +174,7 @@ F src/update.c 57282dae1ffffaf4aedc3201ed77f8ef09be4f45
|
|||||||
F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b
|
F src/utf.c 8c94fa10efc78c2568d08d436acc59df4df7191b
|
||||||
F src/util.c 943caa4071488b20ed90588f0704c6825f91836b
|
F src/util.c 943caa4071488b20ed90588f0704c6825f91836b
|
||||||
F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
|
F src/vacuum.c 3524411bfb58aac0d87eadd3e5b7cd532772af30
|
||||||
F src/vdbe.c 6b3a2273255d7527f17a2f4c123bcaa02969ddc0
|
F src/vdbe.c 892a871879c80a905eaa0d1f7bd24e0221bad56d
|
||||||
F src/vdbe.h bfd84bda447f39cb599302c7ec85067dae20453c
|
F src/vdbe.h bfd84bda447f39cb599302c7ec85067dae20453c
|
||||||
F src/vdbeInt.h 05316345da487b0cf540482576f9ae3337d133cd
|
F src/vdbeInt.h 05316345da487b0cf540482576f9ae3337d133cd
|
||||||
F src/vdbeapi.c 0e1b5a808bb0e556f2a975eb7d11fd3153e922bf
|
F src/vdbeapi.c 0e1b5a808bb0e556f2a975eb7d11fd3153e922bf
|
||||||
@@ -183,7 +183,7 @@ F src/vdbeblob.c cc713c142c3d4952b380c98ee035f850830ddbdb
|
|||||||
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
|
F src/vdbefifo.c a30c237b2a3577e1415fb6e288cbb6b8ed1e5736
|
||||||
F src/vdbemem.c 237e61216381998ff71c6431e5e7bd03386f6225
|
F src/vdbemem.c 237e61216381998ff71c6431e5e7bd03386f6225
|
||||||
F src/vtab.c f5e78bf73df3b0c1b53861109c1b2e0800b108cc
|
F src/vtab.c f5e78bf73df3b0c1b53861109c1b2e0800b108cc
|
||||||
F src/where.c e6850aa2fbe655c15914e9b102a20abf2834ab89
|
F src/where.c 011f866cf0f05c832eea5a30e079eb108253ac64
|
||||||
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
F tclinstaller.tcl 4356d9d94d2b5ed5e68f9f0c80c4df3048dd7617
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/all.test d56a3ca8acdf761204aff0a2e7aa5eb8e11b31e6
|
F test/all.test d56a3ca8acdf761204aff0a2e7aa5eb8e11b31e6
|
||||||
@@ -631,7 +631,7 @@ F www/tclsqlite.tcl 8be95ee6dba05eabcd27a9d91331c803f2ce2130
|
|||||||
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
|
||||||
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
|
||||||
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5
|
||||||
P 4a72a7bb9c5793cdaf4ee038482053e042d8db54
|
P c448f15aa5ed3dec511426775e893efea324faa1
|
||||||
R 63ab958aeb1a64fb1b489284d8bf24a2
|
R 2fd8586df4700418bc96607c52d60fc1
|
||||||
U danielk1977
|
U danielk1977
|
||||||
Z ffb6897ecd3dcda79af541b97309bd4b
|
Z 63b2d6660f8e65e3dba8e17623deefd8
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
c448f15aa5ed3dec511426775e893efea324faa1
|
9a976819246eb558ba43429f8889972c4a4bce9d
|
||||||
73
src/vdbe.c
73
src/vdbe.c
@@ -43,7 +43,7 @@
|
|||||||
** in this file for details. If in doubt, do not deviate from existing
|
** in this file for details. If in doubt, do not deviate from existing
|
||||||
** commenting and indentation practices when changing or adding code.
|
** 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 "sqliteInt.h"
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
@@ -2148,6 +2148,7 @@ case OP_Affinity: {
|
|||||||
Mem *pRec;
|
Mem *pRec;
|
||||||
|
|
||||||
for(pRec=pData0; pRec<=pLast; pRec++){
|
for(pRec=pData0; pRec<=pLast; pRec++){
|
||||||
|
ExpandBlob(pRec);
|
||||||
applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
|
applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -2790,13 +2791,16 @@ case OP_Close: {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Opcode: MoveGe P1 P2 P3 * *
|
/* Opcode: MoveGe P1 P2 P3 P4 *
|
||||||
**
|
**
|
||||||
** Use the value in register P3 as a key. Reposition
|
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
|
||||||
** cursor P1 so that it points to the smallest entry that is greater
|
** use the integer value in register P3 as a key. If cursor P1 refers
|
||||||
** than or equal to the key in register P3.
|
** to an SQL index, then P3 is the first in an array of P4 registers
|
||||||
** If there are no records greater than or equal to the key and P2
|
** that are used as an unpacked index key.
|
||||||
** is not zero, then jump to P2.
|
**
|
||||||
|
** 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
|
** A special feature of this opcode (and different from the
|
||||||
** related OP_MoveGt, OP_MoveLt, and OP_MoveLe) is that if P2 is
|
** 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
|
** See also: Found, NotFound, Distinct, MoveLt, MoveGt, MoveLe
|
||||||
*/
|
*/
|
||||||
/* Opcode: MoveGt P1 P2 P3 * *
|
/* Opcode: MoveGt P1 P2 P3 P4 *
|
||||||
**
|
**
|
||||||
** Use the value in register P3 as a key. Reposition
|
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
|
||||||
** cursor P1 so that it points to the smallest entry that is greater
|
** use the integer value in register P3 as a key. If cursor P1 refers
|
||||||
** than the key in register P3.
|
** to an SQL index, then P3 is the first in an array of P4 registers
|
||||||
** If there are no records greater than the key
|
** that are used as an unpacked index 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
|
** See also: Found, NotFound, Distinct, MoveLt, MoveGe, MoveLe
|
||||||
*/
|
*/
|
||||||
/* Opcode: MoveLt P1 P2 P3 * *
|
/* Opcode: MoveLt P1 P2 P3 P4 *
|
||||||
**
|
**
|
||||||
** Use the value in register P3 as a key. Reposition
|
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
|
||||||
** cursor P1 so that it points to the largest entry that is less
|
** use the integer value in register P3 as a key. If cursor P1 refers
|
||||||
** than the key in register P3.
|
** to an SQL index, then P3 is the first in an array of P4 registers
|
||||||
** If there are no records less than the key
|
** that are used as an unpacked index 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
|
** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLe
|
||||||
*/
|
*/
|
||||||
/* Opcode: MoveLe P1 P2 P3 P4 *
|
/* Opcode: MoveLe P1 P2 P3 P4 *
|
||||||
**
|
**
|
||||||
** P4 is always an integer value. If it is zero, then use the value in
|
** If cursor P1 refers to an SQL table (B-Tree that uses integer keys),
|
||||||
** register P3 as a key. Reposition cursor P1 so that it points to the
|
** use the integer value in register P3 as a key. If cursor P1 refers
|
||||||
** largest entry that is less than or equal to the key. If there are no
|
** to an SQL index, then P3 is the first in an array of P4 registers
|
||||||
** records less than or eqal to the key then jump to P2.
|
** that are used as an unpacked index key.
|
||||||
**
|
**
|
||||||
** If the integer value in operand P4 is non-zero, then P3 is the first
|
** Reposition cursor P1 so that it points to the largest entry that
|
||||||
** of a contiguous array of P4 memory cells that form an unpacked index
|
** is less than or equal to the key value. If there are no records
|
||||||
** key. In this case the unpacked key is used instead of the value of
|
** less than or equal to the key and P2 is not zero, then jump to P2.
|
||||||
** register P3 in the procedure described above.
|
|
||||||
**
|
**
|
||||||
** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
|
** See also: Found, NotFound, Distinct, MoveGt, MoveGe, MoveLt
|
||||||
*/
|
*/
|
||||||
@@ -2871,21 +2880,17 @@ case OP_MoveGt: { /* jump, in3 */
|
|||||||
}
|
}
|
||||||
pC->lastRowid = iKey;
|
pC->lastRowid = iKey;
|
||||||
pC->rowidIsValid = res==0;
|
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{
|
}else{
|
||||||
UnpackedRecord r;
|
UnpackedRecord r;
|
||||||
|
int nField = pOp->p4.i;
|
||||||
|
assert( pOp->p4type==P4_INT32 );
|
||||||
|
assert( nField>0 );
|
||||||
r.pKeyInfo = pC->pKeyInfo;
|
r.pKeyInfo = pC->pKeyInfo;
|
||||||
r.nField = nField;
|
r.nField = nField;
|
||||||
r.needFree = 0;
|
r.needFree = 0;
|
||||||
r.needDestroy = 0;
|
r.needDestroy = 0;
|
||||||
r.aMem = &p->aMem[pOp->p3];
|
r.aMem = &p->aMem[pOp->p3];
|
||||||
rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res);
|
rc = sqlite3BtreeMoveto(pC->pCursor, 0, &r, 0, 0, &res);
|
||||||
}
|
|
||||||
if( rc!=SQLITE_OK ){
|
if( rc!=SQLITE_OK ){
|
||||||
goto abort_due_to_error;
|
goto abort_due_to_error;
|
||||||
}
|
}
|
||||||
|
|||||||
136
src/where.c
136
src/where.c
@@ -16,7 +16,7 @@
|
|||||||
** so is applicable. Because this module is responsible for selecting
|
** so is applicable. Because this module is responsible for selecting
|
||||||
** indices, you might also think of this module as the "query optimizer".
|
** 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"
|
#include "sqliteInt.h"
|
||||||
|
|
||||||
@@ -1727,27 +1727,17 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Generate code that builds a probe for an index.
|
** Apply the affinities associated with the first n columns of index
|
||||||
**
|
** pIdx to the values in the n registers starting at base.
|
||||||
** 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.
|
|
||||||
*/
|
*/
|
||||||
static void buildIndexProbe(
|
static void codeApplyAffinity(Parse *pParse, int base, int n, Index *pIdx){
|
||||||
Parse *pParse, /* Parsing and code generation context */
|
if( n>0 ){
|
||||||
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;
|
Vdbe *v = pParse->pVdbe;
|
||||||
assert( regSrc>0 );
|
|
||||||
assert( regDest>0 );
|
|
||||||
assert( v!=0 );
|
assert( v!=0 );
|
||||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regSrc, nColumn, regDest);
|
sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
|
||||||
sqlite3IndexAffinityStr(v, pIdx);
|
sqlite3IndexAffinityStr(v, pIdx);
|
||||||
sqlite3ExprCacheAffinityChange(pParse, regSrc, nColumn);
|
sqlite3ExprCacheAffinityChange(pParse, base, n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2463,13 +2453,28 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
|
sqlite3VdbeChangeP5(v, SQLITE_AFF_NUMERIC | SQLITE_JUMPIFNULL);
|
||||||
sqlite3ReleaseTempReg(pParse, r1);
|
sqlite3ReleaseTempReg(pParse, r1);
|
||||||
}
|
}
|
||||||
}else if( pLevel->flags & WHERE_COLUMN_RANGE ){
|
}else if( pLevel->flags & (WHERE_COLUMN_RANGE|WHERE_COLUMN_EQ) ){
|
||||||
/* Case 3: The WHERE clause term that refers to the right-most
|
/* Case 3: A scan using an index.
|
||||||
** column of the index is an inequality. For example, if
|
**
|
||||||
** the index is on (x,y,z) and the WHERE clause is of the
|
** The WHERE clause may contain one or more equality
|
||||||
** form "x=5 AND y<10" then this case is used. Only the
|
** terms ("==" or "IN" operators) that refer to the N
|
||||||
** right-most column can be an inequality - the rest must
|
** left-most columns of the index. It may also contain
|
||||||
** use the "==" and "IN" operators.
|
** 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
|
** This case is also used when there are no WHERE clause
|
||||||
** constraints but an index is selected anyway, in order
|
** constraints but an index is selected anyway, in order
|
||||||
@@ -2486,7 +2491,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
OP_MoveLe /* 7: (start_constraints && startEq && bRev) */
|
OP_MoveLe /* 7: (start_constraints && startEq && bRev) */
|
||||||
};
|
};
|
||||||
int aEndOp[] = {
|
int aEndOp[] = {
|
||||||
OP_Noop, /* 0: () */
|
OP_Noop, /* 0: (!end_constraints) */
|
||||||
OP_IdxGE, /* 1: (end_constraints && !bRev) */
|
OP_IdxGE, /* 1: (end_constraints && !bRev) */
|
||||||
OP_IdxLT /* 2: (end_constraints && bRev) */
|
OP_IdxLT /* 2: (end_constraints && bRev) */
|
||||||
};
|
};
|
||||||
@@ -2526,7 +2531,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
isMinQuery = 1;
|
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.
|
** of the range.
|
||||||
*/
|
*/
|
||||||
if( pLevel->flags & WHERE_TOP_LIMIT ){
|
if( pLevel->flags & WHERE_TOP_LIMIT ){
|
||||||
@@ -2565,8 +2570,7 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
startEq = 0;
|
startEq = 0;
|
||||||
start_constraints = 1;
|
start_constraints = 1;
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp2(v, OP_Affinity, regBase, (int)ptr);
|
codeApplyAffinity(pParse, regBase, (int)ptr, pIdx);
|
||||||
sqlite3IndexAffinityStr(v, pIdx);
|
|
||||||
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
||||||
sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase, ptr, P4_INT32);
|
sqlite3VdbeAddOp4(v, op, iIdxCur, nxt, regBase, ptr, P4_INT32);
|
||||||
|
|
||||||
@@ -2577,10 +2581,9 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
if( pRangeEnd ){
|
if( pRangeEnd ){
|
||||||
sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq);
|
sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq);
|
||||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
|
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, nxt);
|
||||||
|
codeApplyAffinity(pParse, regBase, nEq+1, pIdx);
|
||||||
ptr++;
|
ptr++;
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp2(v, OP_Affinity, regBase, (int)ptr);
|
|
||||||
sqlite3IndexAffinityStr(v, pIdx);
|
|
||||||
|
|
||||||
/* Top of the loop body */
|
/* Top of the loop body */
|
||||||
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
|
pLevel->p2 = sqlite3VdbeCurrentAddr(v);
|
||||||
@@ -2615,77 +2618,6 @@ WhereInfo *sqlite3WhereBegin(
|
|||||||
pLevel->p1 = iIdxCur;
|
pLevel->p1 = iIdxCur;
|
||||||
disableTerm(pLevel, pRangeStart);
|
disableTerm(pLevel, pRangeStart);
|
||||||
disableTerm(pLevel, pRangeEnd);
|
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{
|
}else{
|
||||||
/* Case 5: There is no usable index. We must do a complete
|
/* Case 5: There is no usable index. We must do a complete
|
||||||
** scan of the entire table.
|
** scan of the entire table.
|
||||||
|
|||||||
Reference in New Issue
Block a user