mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-06 15:49:35 +03:00
If a binary operator in a WHERE clause that should be performed with no affinity conversions applied to its operands (see http://www.sqlite.org/datatype3.html) is optimized by index lookup, do not apply any conversions to the key value before looking it up in the index. Fix for 93fb9f89d6.
FossilOrigin-Name: e72186f2d68d28c2e0c32894f9adb28c155b5f63
This commit is contained in:
30
manifest
30
manifest
@@ -1,8 +1,5 @@
|
|||||||
-----BEGIN PGP SIGNED MESSAGE-----
|
C If\sa\sbinary\soperator\sin\sa\sWHERE\sclause\sthat\sshould\sbe\sperformed\swith\sno\saffinity\sconversions\sapplied\sto\sits\soperands\s(see\shttp://www.sqlite.org/datatype3.html)\sis\soptimized\sby\sindex\slookup,\sdo\snot\sapply\sany\sconversions\sto\sthe\skey\svalue\sbefore\slooking\sit\sup\sin\sthe\sindex.\sFix\sfor\s93fb9f89d6.
|
||||||
Hash: SHA1
|
D 2009-08-13T19:21:17
|
||||||
|
|
||||||
C Enhancements\sto\sthe\swhereB.test\sto\scheck\smore\saffinity\scorner\scases.
|
|
||||||
D 2009-08-13T18:14:32
|
|
||||||
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
F Makefile.arm-wince-mingw32ce-gcc fcd5e9cd67fe88836360bb4f9ef4cb7f8e2fb5a0
|
||||||
F Makefile.in c606c9b502dfde3b9c3b2d23ed49f3737829693b
|
F Makefile.in c606c9b502dfde3b9c3b2d23ed49f3737829693b
|
||||||
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
F Makefile.linux-gcc d53183f4aa6a9192d249731c90dbdffbd2c68654
|
||||||
@@ -116,7 +113,7 @@ F src/build.c a15de7c5d020a778b641fca0b2510126843f4b30
|
|||||||
F src/callback.c cb68b21b0d4ae7d11ae0e487933bce3323784dcf
|
F src/callback.c cb68b21b0d4ae7d11ae0e487933bce3323784dcf
|
||||||
F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
|
F src/complete.c 5ad5c6cd4548211867c204c41a126d73a9fbcea0
|
||||||
F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3
|
F src/date.c ab5f7137656652a48434d64f96bdcdc823bb23b3
|
||||||
F src/delete.c f1502d3c210f80eebef475a04891e8ea80099553
|
F src/delete.c dcf07632d8ca3d4086df8b65ea907a47278e6382
|
||||||
F src/expr.c d069ba1e060f296ea4f18fb85198fafefd00b22f
|
F src/expr.c d069ba1e060f296ea4f18fb85198fafefd00b22f
|
||||||
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
|
F src/fault.c dc88c821842157460750d2d61a8a8b4197d047ff
|
||||||
F src/func.c 9856373f5315f6b8690d7f07f7191aa9f279ca87
|
F src/func.c 9856373f5315f6b8690d7f07f7191aa9f279ca87
|
||||||
@@ -124,7 +121,7 @@ F src/global.c 448419c44ce0701104c2121b0e06919b44514c0c
|
|||||||
F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
|
F src/hash.c ebcaa921ffd9d86f7ea5ae16a0a29d1c871130a7
|
||||||
F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1
|
F src/hash.h 35b216c13343d0b4f87d9f21969ac55ad72174e1
|
||||||
F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
|
F src/hwtime.h 4a1d45f4cae1f402ea19686acf24acf4f0cb53cb
|
||||||
F src/insert.c a4bbd811a15f8b24a311753da947d61368685db1
|
F src/insert.c 95625f99f377a9ef264c289407173b722c7af6e8
|
||||||
F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0
|
F src/journal.c e00df0c0da8413ab6e1bb7d7cab5665d4a9000d0
|
||||||
F src/legacy.c 303b4ffcf1ae652fcf5ef635846c563c254564f6
|
F src/legacy.c 303b4ffcf1ae652fcf5ef635846c563c254564f6
|
||||||
F src/lempar.c 0c4d1ab0a5ef2b0381eb81a732c54f68f27a574d
|
F src/lempar.c 0c4d1ab0a5ef2b0381eb81a732c54f68f27a574d
|
||||||
@@ -166,7 +163,7 @@ F src/select.c 67b0778c9585905c8aa75aaa469e76ef3c1d315a
|
|||||||
F src/shell.c db2643650b9268df89a4bedca3f1c6d9e786f1bb
|
F src/shell.c db2643650b9268df89a4bedca3f1c6d9e786f1bb
|
||||||
F src/sqlite.h.in eb42257503a48f6f12ff0b23a81067ba9b5ac1eb
|
F src/sqlite.h.in eb42257503a48f6f12ff0b23a81067ba9b5ac1eb
|
||||||
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
|
F src/sqlite3ext.h 1db7d63ab5de4b3e6b83dd03d1a4e64fef6d2a17
|
||||||
F src/sqliteInt.h 6337542c0eb0e6521991b29f59c8bcbdfda222e7
|
F src/sqliteInt.h 6a90791138ba3447572d184d0798c24f3cbbec98
|
||||||
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
|
F src/sqliteLimit.h ffe93f5a0c4e7bd13e70cd7bf84cfb5c3465f45d
|
||||||
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
F src/status.c 237b193efae0cf6ac3f0817a208de6c6c6ef6d76
|
||||||
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
|
F src/table.c cc86ad3d6ad54df7c63a3e807b5783c90411a08d
|
||||||
@@ -216,7 +213,7 @@ F src/vdbeblob.c a3f3e0e877fc64ea50165eec2855f5ada4477611
|
|||||||
F src/vdbemem.c 364cfce843926224f917ab89ee476be958c864ed
|
F src/vdbemem.c 364cfce843926224f917ab89ee476be958c864ed
|
||||||
F src/vtab.c aedd76e8670d5a5379f93804398d3ba960125547
|
F src/vtab.c aedd76e8670d5a5379f93804398d3ba960125547
|
||||||
F src/walker.c 1edca756275f158b80f20eb6f104c8d3fcc96a04
|
F src/walker.c 1edca756275f158b80f20eb6f104c8d3fcc96a04
|
||||||
F src/where.c 53adef2c7b8bc888755cf41fb3449aedb36a429c
|
F src/where.c 7573120c1f2fe6d4c246f138f1e30fbcda3db241
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87
|
||||||
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
|
F test/all.test 14165b3e32715b700b5f0cbf8f6e3833dda0be45
|
||||||
@@ -746,14 +743,7 @@ F tool/speedtest2.tcl ee2149167303ba8e95af97873c575c3e0fab58ff
|
|||||||
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
F tool/speedtest8.c 2902c46588c40b55661e471d7a86e4dd71a18224
|
||||||
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
F tool/speedtest8inst1.c 293327bc76823f473684d589a8160bde1f52c14e
|
||||||
F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746
|
F tool/vdbe-compress.tcl 672f81d693a03f80f5ae60bfefacd8a349e76746
|
||||||
P 149ec24e61437fac2b0dd6239276d3aa543c56cb
|
P 1048459824746307c9e4296cbc21716bf8b5449d
|
||||||
R 1ea36fc2c7e0c32d5b2483eec1ce1a06
|
R 9cf12527faa6d7b7304f1183ac06fe71
|
||||||
U drh
|
U dan
|
||||||
Z cdd6f1e89b3618add099c3116553394a
|
Z 0b088089cd7635bacda9499fff4849b7
|
||||||
-----BEGIN PGP SIGNATURE-----
|
|
||||||
Version: GnuPG v1.4.6 (GNU/Linux)
|
|
||||||
|
|
||||||
iD8DBQFKhFgLoxKgR168RlERAgjMAJ0e/xokwSjX2hsY3q8mvlUGu+555wCfZL+Z
|
|
||||||
ThH1uVO4nfptbHxSFohZy1U=
|
|
||||||
=PHPU
|
|
||||||
-----END PGP SIGNATURE-----
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
1048459824746307c9e4296cbc21716bf8b5449d
|
e72186f2d68d28c2e0c32894f9adb28c155b5f63
|
||||||
@@ -622,7 +622,7 @@ int sqlite3GenerateIndexKey(
|
|||||||
}
|
}
|
||||||
if( doMakeRec ){
|
if( doMakeRec ){
|
||||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nCol+1, regOut);
|
||||||
sqlite3IndexAffinityStr(v, pIdx);
|
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0);
|
||||||
sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1);
|
sqlite3ExprCacheAffinityChange(pParse, regBase, nCol+1);
|
||||||
}
|
}
|
||||||
sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
|
sqlite3ReleaseTempRange(pParse, regBase, nCol+1);
|
||||||
|
|||||||
18
src/insert.c
18
src/insert.c
@@ -37,9 +37,9 @@ void sqlite3OpenTable(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Set P4 of the most recently inserted opcode to a column affinity
|
** Return a pointer to the column affinity string associated with index
|
||||||
** string for index pIdx. A column affinity string has one character
|
** pIdx. A column affinity string has one character for each column in
|
||||||
** for each column in the table, according to the affinity of the column:
|
** the table, according to the affinity of the column:
|
||||||
**
|
**
|
||||||
** Character Column affinity
|
** Character Column affinity
|
||||||
** ------------------------------
|
** ------------------------------
|
||||||
@@ -51,8 +51,12 @@ void sqlite3OpenTable(
|
|||||||
**
|
**
|
||||||
** An extra 'b' is appended to the end of the string to cover the
|
** An extra 'b' is appended to the end of the string to cover the
|
||||||
** rowid that appears as the last column in every index.
|
** rowid that appears as the last column in every index.
|
||||||
|
**
|
||||||
|
** Memory for the buffer containing the column index affinity string
|
||||||
|
** is managed along with the rest of the Index structure. It will be
|
||||||
|
** released when sqlite3DeleteIndex() is called.
|
||||||
*/
|
*/
|
||||||
void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
|
const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
|
||||||
if( !pIdx->zColAff ){
|
if( !pIdx->zColAff ){
|
||||||
/* The first time a column affinity string for a particular index is
|
/* The first time a column affinity string for a particular index is
|
||||||
** required, it is allocated and populated here. It is then stored as
|
** required, it is allocated and populated here. It is then stored as
|
||||||
@@ -68,7 +72,7 @@ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
|
|||||||
pIdx->zColAff = (char *)sqlite3Malloc(pIdx->nColumn+2);
|
pIdx->zColAff = (char *)sqlite3Malloc(pIdx->nColumn+2);
|
||||||
if( !pIdx->zColAff ){
|
if( !pIdx->zColAff ){
|
||||||
db->mallocFailed = 1;
|
db->mallocFailed = 1;
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
for(n=0; n<pIdx->nColumn; n++){
|
for(n=0; n<pIdx->nColumn; n++){
|
||||||
pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity;
|
pIdx->zColAff[n] = pTab->aCol[pIdx->aiColumn[n]].affinity;
|
||||||
@@ -77,7 +81,7 @@ void sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){
|
|||||||
pIdx->zColAff[n] = 0;
|
pIdx->zColAff[n] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3VdbeChangeP4(v, -1, pIdx->zColAff, 0);
|
return pIdx->zColAff;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -1298,7 +1302,7 @@ void sqlite3GenerateConstraintChecks(
|
|||||||
}
|
}
|
||||||
sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
|
sqlite3VdbeAddOp2(v, OP_SCopy, regRowid, regIdx+i);
|
||||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
|
sqlite3VdbeAddOp3(v, OP_MakeRecord, regIdx, pIdx->nColumn+1, aRegIdx[iCur]);
|
||||||
sqlite3IndexAffinityStr(v, pIdx);
|
sqlite3VdbeChangeP4(v, -1, sqlite3IndexAffinityStr(v, pIdx), 0);
|
||||||
sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
|
sqlite3ExprCacheAffinityChange(pParse, regIdx, pIdx->nColumn+1);
|
||||||
|
|
||||||
/* Find out what action to take in case there is an indexing conflict */
|
/* Find out what action to take in case there is an indexing conflict */
|
||||||
|
|||||||
@@ -2755,7 +2755,7 @@ int sqlite3VarintLen(u64 v);
|
|||||||
#define putVarint sqlite3PutVarint
|
#define putVarint sqlite3PutVarint
|
||||||
|
|
||||||
|
|
||||||
void sqlite3IndexAffinityStr(Vdbe *, Index *);
|
const char *sqlite3IndexAffinityStr(Vdbe *, Index *);
|
||||||
void sqlite3TableAffinityStr(Vdbe *, Table *);
|
void sqlite3TableAffinityStr(Vdbe *, Table *);
|
||||||
char sqlite3CompareAffinity(Expr *pExpr, char aff2);
|
char sqlite3CompareAffinity(Expr *pExpr, char aff2);
|
||||||
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
|
int sqlite3IndexAffinityOk(Expr *pExpr, char idx_affinity);
|
||||||
|
|||||||
77
src/where.c
77
src/where.c
@@ -2275,18 +2275,20 @@ static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Apply the affinities associated with the first n columns of index
|
** Code an OP_Affinity opcode to apply the column affinity string zAff
|
||||||
** pIdx to the values in the n registers starting at base.
|
** to the n registers starting at base.
|
||||||
|
**
|
||||||
|
** Buffer zAff was allocated using sqlite3DbMalloc(). It is the
|
||||||
|
** responsibility of this function to arrange for it to be eventually
|
||||||
|
** freed using sqlite3DbFree().
|
||||||
*/
|
*/
|
||||||
static void codeApplyAffinity(Parse *pParse, int base, int n, Index *pIdx){
|
static void codeApplyAffinity(Parse *pParse, int base, int n, char *zAff){
|
||||||
if( n>0 ){
|
|
||||||
Vdbe *v = pParse->pVdbe;
|
Vdbe *v = pParse->pVdbe;
|
||||||
assert( v!=0 );
|
assert( v!=0 );
|
||||||
sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
|
sqlite3VdbeAddOp2(v, OP_Affinity, base, n);
|
||||||
sqlite3IndexAffinityStr(v, pIdx);
|
sqlite3VdbeChangeP4(v, -1, zAff, P4_DYNAMIC);
|
||||||
sqlite3ExprCacheAffinityChange(pParse, base, n);
|
sqlite3ExprCacheAffinityChange(pParse, base, n);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -2376,13 +2378,29 @@ static int codeEqualityTerm(
|
|||||||
** key value of the loop. If one or more IN operators appear, then
|
** key value of the loop. If one or more IN operators appear, then
|
||||||
** this routine allocates an additional nEq memory cells for internal
|
** this routine allocates an additional nEq memory cells for internal
|
||||||
** use.
|
** use.
|
||||||
|
**
|
||||||
|
** Before returning, *pzAff is set to point to a buffer containing a
|
||||||
|
** copy of the column affinity string of the index allocated using
|
||||||
|
** sqlite3DbMalloc(). Except, entries in the copy of the string associated
|
||||||
|
** with equality constraints that use NONE affinity are set to
|
||||||
|
** SQLITE_AFF_NONE. This is to deal with SQL such as the following:
|
||||||
|
**
|
||||||
|
** CREATE TABLE t1(a TEXT PRIMARY KEY, b);
|
||||||
|
** SELECT ... FROM t1 AS t2, t1 WHERE t1.a = t2.b;
|
||||||
|
**
|
||||||
|
** In the example above, the index on t1(a) has TEXT affinity. But since
|
||||||
|
** the right hand side of the equality constraint (t2.b) has NONE affinity,
|
||||||
|
** no conversion should be attempted before using a t2.b value as part of
|
||||||
|
** a key to search the index. Hence the first byte in the returned affinity
|
||||||
|
** string in this example would be set to SQLITE_AFF_NONE.
|
||||||
*/
|
*/
|
||||||
static int codeAllEqualityTerms(
|
static int codeAllEqualityTerms(
|
||||||
Parse *pParse, /* Parsing context */
|
Parse *pParse, /* Parsing context */
|
||||||
WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
|
WhereLevel *pLevel, /* Which nested loop of the FROM we are coding */
|
||||||
WhereClause *pWC, /* The WHERE clause */
|
WhereClause *pWC, /* The WHERE clause */
|
||||||
Bitmask notReady, /* Which parts of FROM have not yet been coded */
|
Bitmask notReady, /* Which parts of FROM have not yet been coded */
|
||||||
int nExtraReg /* Number of extra registers to allocate */
|
int nExtraReg, /* Number of extra registers to allocate */
|
||||||
|
char **pzAff /* OUT: Set to point to affinity string */
|
||||||
){
|
){
|
||||||
int nEq = pLevel->plan.nEq; /* The number of == or IN constraints to code */
|
int nEq = pLevel->plan.nEq; /* The number of == or IN constraints to code */
|
||||||
Vdbe *v = pParse->pVdbe; /* The vm under construction */
|
Vdbe *v = pParse->pVdbe; /* The vm under construction */
|
||||||
@@ -2392,6 +2410,7 @@ static int codeAllEqualityTerms(
|
|||||||
int j; /* Loop counter */
|
int j; /* Loop counter */
|
||||||
int regBase; /* Base register */
|
int regBase; /* Base register */
|
||||||
int nReg; /* Number of registers to allocate */
|
int nReg; /* Number of registers to allocate */
|
||||||
|
char *zAff; /* Affinity string to return */
|
||||||
|
|
||||||
/* This module is only called on query plans that use an index. */
|
/* This module is only called on query plans that use an index. */
|
||||||
assert( pLevel->plan.wsFlags & WHERE_INDEXED );
|
assert( pLevel->plan.wsFlags & WHERE_INDEXED );
|
||||||
@@ -2403,6 +2422,11 @@ static int codeAllEqualityTerms(
|
|||||||
nReg = pLevel->plan.nEq + nExtraReg;
|
nReg = pLevel->plan.nEq + nExtraReg;
|
||||||
pParse->nMem += nReg;
|
pParse->nMem += nReg;
|
||||||
|
|
||||||
|
zAff = sqlite3DbStrDup(pParse->db, sqlite3IndexAffinityStr(v, pIdx));
|
||||||
|
if( !zAff ){
|
||||||
|
pParse->db->mallocFailed = 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Evaluate the equality constraints
|
/* Evaluate the equality constraints
|
||||||
*/
|
*/
|
||||||
assert( pIdx->nColumn>=nEq );
|
assert( pIdx->nColumn>=nEq );
|
||||||
@@ -2425,8 +2449,14 @@ static int codeAllEqualityTerms(
|
|||||||
testcase( pTerm->eOperator & WO_IN );
|
testcase( pTerm->eOperator & WO_IN );
|
||||||
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
|
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
|
||||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
|
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
|
||||||
|
if( zAff
|
||||||
|
&& sqlite3CompareAffinity(pTerm->pExpr->pRight, zAff[j])==SQLITE_AFF_NONE
|
||||||
|
){
|
||||||
|
zAff[j] = SQLITE_AFF_NONE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
*pzAff = zAff;
|
||||||
return regBase;
|
return regBase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2682,6 +2712,7 @@ static Bitmask codeOneLoopStart(
|
|||||||
int iIdxCur; /* The VDBE cursor for the index */
|
int iIdxCur; /* The VDBE cursor for the index */
|
||||||
int nExtraReg = 0; /* Number of extra registers needed */
|
int nExtraReg = 0; /* Number of extra registers needed */
|
||||||
int op; /* Instruction opcode */
|
int op; /* Instruction opcode */
|
||||||
|
char *zAff;
|
||||||
|
|
||||||
pIdx = pLevel->plan.u.pIdx;
|
pIdx = pLevel->plan.u.pIdx;
|
||||||
iIdxCur = pLevel->iIdxCur;
|
iIdxCur = pLevel->iIdxCur;
|
||||||
@@ -2721,10 +2752,11 @@ static Bitmask codeOneLoopStart(
|
|||||||
** and store the values of those terms in an array of registers
|
** and store the values of those terms in an array of registers
|
||||||
** starting at regBase.
|
** starting at regBase.
|
||||||
*/
|
*/
|
||||||
regBase = codeAllEqualityTerms(pParse, pLevel, pWC, notReady, nExtraReg);
|
regBase = codeAllEqualityTerms(
|
||||||
|
pParse, pLevel, pWC, notReady, nExtraReg, &zAff
|
||||||
|
);
|
||||||
addrNxt = pLevel->addrNxt;
|
addrNxt = pLevel->addrNxt;
|
||||||
|
|
||||||
|
|
||||||
/* If we are doing a reverse order scan on an ascending index, or
|
/* If we are doing a reverse order scan on an ascending index, or
|
||||||
** a forward order scan on a descending index, interchange the
|
** a forward order scan on a descending index, interchange the
|
||||||
** start and end terms (pRangeStart and pRangeEnd).
|
** start and end terms (pRangeStart and pRangeEnd).
|
||||||
@@ -2744,8 +2776,17 @@ static Bitmask codeOneLoopStart(
|
|||||||
/* Seek the index cursor to the start of the range. */
|
/* Seek the index cursor to the start of the range. */
|
||||||
nConstraint = nEq;
|
nConstraint = nEq;
|
||||||
if( pRangeStart ){
|
if( pRangeStart ){
|
||||||
sqlite3ExprCode(pParse, pRangeStart->pExpr->pRight, regBase+nEq);
|
Expr *pRight = pRangeStart->pExpr->pRight;
|
||||||
|
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
||||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
||||||
|
if( zAff
|
||||||
|
&& sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE
|
||||||
|
){
|
||||||
|
/* Since the comparison is to be performed with no conversions applied
|
||||||
|
** to the operands, set the affinity to apply to pRight to
|
||||||
|
** SQLITE_AFF_NONE. */
|
||||||
|
zAff[nConstraint] = SQLITE_AFF_NONE;
|
||||||
|
}
|
||||||
nConstraint++;
|
nConstraint++;
|
||||||
}else if( isMinQuery ){
|
}else if( isMinQuery ){
|
||||||
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
|
sqlite3VdbeAddOp2(v, OP_Null, 0, regBase+nEq);
|
||||||
@@ -2753,7 +2794,7 @@ static Bitmask codeOneLoopStart(
|
|||||||
startEq = 0;
|
startEq = 0;
|
||||||
start_constraints = 1;
|
start_constraints = 1;
|
||||||
}
|
}
|
||||||
codeApplyAffinity(pParse, regBase, nConstraint, pIdx);
|
codeApplyAffinity(pParse, regBase, nConstraint, zAff);
|
||||||
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
op = aStartOp[(start_constraints<<2) + (startEq<<1) + bRev];
|
||||||
assert( op!=0 );
|
assert( op!=0 );
|
||||||
testcase( op==OP_Rewind );
|
testcase( op==OP_Rewind );
|
||||||
@@ -2770,10 +2811,20 @@ static Bitmask codeOneLoopStart(
|
|||||||
*/
|
*/
|
||||||
nConstraint = nEq;
|
nConstraint = nEq;
|
||||||
if( pRangeEnd ){
|
if( pRangeEnd ){
|
||||||
|
Expr *pRight = pRangeEnd->pExpr->pRight;
|
||||||
sqlite3ExprCacheRemove(pParse, regBase+nEq);
|
sqlite3ExprCacheRemove(pParse, regBase+nEq);
|
||||||
sqlite3ExprCode(pParse, pRangeEnd->pExpr->pRight, regBase+nEq);
|
sqlite3ExprCode(pParse, pRight, regBase+nEq);
|
||||||
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
|
||||||
codeApplyAffinity(pParse, regBase, nEq+1, pIdx);
|
zAff = sqlite3DbStrDup(pParse->db, zAff);
|
||||||
|
if( zAff
|
||||||
|
&& sqlite3CompareAffinity(pRight, zAff[nConstraint])==SQLITE_AFF_NONE
|
||||||
|
){
|
||||||
|
/* Since the comparison is to be performed with no conversions applied
|
||||||
|
** to the operands, set the affinity to apply to pRight to
|
||||||
|
** SQLITE_AFF_NONE. */
|
||||||
|
zAff[nConstraint] = SQLITE_AFF_NONE;
|
||||||
|
}
|
||||||
|
codeApplyAffinity(pParse, regBase, nEq+1, zAff);
|
||||||
nConstraint++;
|
nConstraint++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user