mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-27 20:41:58 +03:00
Enable optimization of IN operators on constraints to virtual tables.
FossilOrigin-Name: aa650746b19e4a6a373f7e47effff3ab2f48e78c
This commit is contained in:
19
manifest
19
manifest
@ -1,5 +1,5 @@
|
|||||||
C Correct\scomments\sand\senhance\sreadability\sof\sthe\smkvsix\stool.
|
C Enable\soptimization\sof\sIN\soperators\son\sconstraints\sto\svirtual\stables.
|
||||||
D 2012-10-15T20:28:22.029
|
D 2012-10-16T23:17:14.207
|
||||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||||
F Makefile.in 5f4f26109f9d80829122e0e09f9cda008fa065fb
|
F Makefile.in 5f4f26109f9d80829122e0e09f9cda008fa065fb
|
||||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||||
@ -249,7 +249,7 @@ F src/vtab.c 9c64ae18af78c740610df841c6f49fc2d240a279
|
|||||||
F src/wal.c f5c7b5027d0ed0e9bc9afeb4a3a8dfea762ec7d2
|
F src/wal.c f5c7b5027d0ed0e9bc9afeb4a3a8dfea762ec7d2
|
||||||
F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6
|
F src/wal.h 29c197540b19044e6cd73487017e5e47a1d3dac6
|
||||||
F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b
|
F src/walker.c 3d75ba73de15e0f8cd0737643badbeb0e002f07b
|
||||||
F src/where.c 3e6c1f9efe4c6a029b0a750e0f6a63964f43bcce
|
F src/where.c 62f667db8cdbb81028bf1c55ba4b0e845b79622c
|
||||||
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
|
F test/8_3_names.test 631ea964a3edb091cf73c3b540f6bcfdb36ce823
|
||||||
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
|
||||||
F test/aggnested.test 0be144b453e0622a085fae8665c32f5676708e00
|
F test/aggnested.test 0be144b453e0622a085fae8665c32f5676708e00
|
||||||
@ -916,7 +916,7 @@ F test/vacuum4.test d3f8ecff345f166911568f397d2432c16d2867d9
|
|||||||
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
|
||||||
F test/veryquick.test 7701bb609fe8bf6535514e8b849a309e8f00573b
|
F test/veryquick.test 7701bb609fe8bf6535514e8b849a309e8f00573b
|
||||||
F test/view.test b182a67ec43f490b156b5a710827a341be83dd17
|
F test/view.test b182a67ec43f490b156b5a710827a341be83dd17
|
||||||
F test/vtab1.test 10fb9e656fe4b318cd82ff1616a340acc01aac4b
|
F test/vtab1.test 524beb672c42463fe3d37351b74253c0b835498d
|
||||||
F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
|
F test/vtab2.test 7bcffc050da5c68f4f312e49e443063e2d391c0d
|
||||||
F test/vtab3.test baad99fd27217f5d6db10660522e0b7192446de1
|
F test/vtab3.test baad99fd27217f5d6db10660522e0b7192446de1
|
||||||
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
|
F test/vtab4.test 942f8b8280b3ea8a41dae20e7822d065ca1cb275
|
||||||
@ -1021,7 +1021,10 @@ F tool/vdbe-compress.tcl f12c884766bd14277f4fcedcae07078011717381
|
|||||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||||
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
F tool/warnings.sh fbc018d67fd7395f440c28f33ef0f94420226381
|
||||||
F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9
|
F tool/win/sqlite.vsix 67d8a99aceb56384a81b3f30d6c71743146d2cc9
|
||||||
P 629a42d47a0d8f73de900f469845ce800bdb8959
|
P 2c3af657fee6153842d660a6ce29aa7d791ebd38
|
||||||
R c7830c7c0cb344c8cb6a175c95e5eb7f
|
R 5cbef12c646a3899761eba454f8c4105
|
||||||
U mistachkin
|
T *branch * vtab-IN-opt
|
||||||
Z f2086ddd83e8b281e8d53ba90c91d2db
|
T *sym-vtab-IN-opt *
|
||||||
|
T -sym-trunk *
|
||||||
|
U drh
|
||||||
|
Z 07568d163c180c755b6278e856d28eda
|
||||||
|
@ -1 +1 @@
|
|||||||
2c3af657fee6153842d660a6ce29aa7d791ebd38
|
aa650746b19e4a6a373f7e47effff3ab2f48e78c
|
27
src/where.c
27
src/where.c
@ -253,7 +253,7 @@ struct WhereCost {
|
|||||||
#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
|
#define WHERE_COLUMN_NULL 0x00080000 /* x IS NULL */
|
||||||
#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
|
#define WHERE_INDEXED 0x000f0000 /* Anything that uses an index */
|
||||||
#define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */
|
#define WHERE_NOT_FULLSCAN 0x100f3000 /* Does not do a full table scan */
|
||||||
#define WHERE_IN_ABLE 0x000f1000 /* Able to support an IN operator */
|
#define WHERE_IN_ABLE 0x080f1000 /* Able to support an IN operator */
|
||||||
#define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
|
#define WHERE_TOP_LIMIT 0x00100000 /* x<EXPR or x<=EXPR constraint */
|
||||||
#define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
|
#define WHERE_BTM_LIMIT 0x00200000 /* x>EXPR or x>=EXPR constraint */
|
||||||
#define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */
|
#define WHERE_BOTH_LIMIT 0x00300000 /* Both x>EXPR and x<EXPR */
|
||||||
@ -2038,7 +2038,7 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
|
|||||||
assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
|
assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
|
||||||
testcase( pTerm->eOperator==WO_IN );
|
testcase( pTerm->eOperator==WO_IN );
|
||||||
testcase( pTerm->eOperator==WO_ISNULL );
|
testcase( pTerm->eOperator==WO_ISNULL );
|
||||||
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
|
if( pTerm->eOperator & (WO_ISNULL) ) continue;
|
||||||
if( pTerm->wtFlags & TERM_VNULL ) continue;
|
if( pTerm->wtFlags & TERM_VNULL ) continue;
|
||||||
nTerm++;
|
nTerm++;
|
||||||
}
|
}
|
||||||
@ -2086,15 +2086,18 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
|
|||||||
pUsage;
|
pUsage;
|
||||||
|
|
||||||
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
|
for(i=j=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
|
||||||
|
u8 op;
|
||||||
if( pTerm->leftCursor != pSrc->iCursor ) continue;
|
if( pTerm->leftCursor != pSrc->iCursor ) continue;
|
||||||
assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
|
assert( (pTerm->eOperator&(pTerm->eOperator-1))==0 );
|
||||||
testcase( pTerm->eOperator==WO_IN );
|
testcase( pTerm->eOperator==WO_IN );
|
||||||
testcase( pTerm->eOperator==WO_ISNULL );
|
testcase( pTerm->eOperator==WO_ISNULL );
|
||||||
if( pTerm->eOperator & (WO_IN|WO_ISNULL) ) continue;
|
if( pTerm->eOperator & (WO_ISNULL) ) continue;
|
||||||
if( pTerm->wtFlags & TERM_VNULL ) continue;
|
if( pTerm->wtFlags & TERM_VNULL ) continue;
|
||||||
pIdxCons[j].iColumn = pTerm->u.leftColumn;
|
pIdxCons[j].iColumn = pTerm->u.leftColumn;
|
||||||
pIdxCons[j].iTermOffset = i;
|
pIdxCons[j].iTermOffset = i;
|
||||||
pIdxCons[j].op = (u8)pTerm->eOperator;
|
op = (u8)pTerm->eOperator;
|
||||||
|
if( op==WO_IN ) op = WO_EQ;
|
||||||
|
pIdxCons[j].op = op;
|
||||||
/* The direct assignment in the previous line is possible only because
|
/* The direct assignment in the previous line is possible only because
|
||||||
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
|
** the WO_ and SQLITE_INDEX_CONSTRAINT_ codes are identical. The
|
||||||
** following asserts verify this fact. */
|
** following asserts verify this fact. */
|
||||||
@ -2104,7 +2107,7 @@ static sqlite3_index_info *allocateIndexInfo(WhereBestIdx *p){
|
|||||||
assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
|
assert( WO_GT==SQLITE_INDEX_CONSTRAINT_GT );
|
||||||
assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
|
assert( WO_GE==SQLITE_INDEX_CONSTRAINT_GE );
|
||||||
assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
|
assert( WO_MATCH==SQLITE_INDEX_CONSTRAINT_MATCH );
|
||||||
assert( pTerm->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
|
assert( pTerm->eOperator & (WO_IN|WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE|WO_MATCH) );
|
||||||
j++;
|
j++;
|
||||||
}
|
}
|
||||||
for(i=0; i<nOrderBy; i++){
|
for(i=0; i<nOrderBy; i++){
|
||||||
@ -4030,6 +4033,7 @@ static Bitmask codeOneLoopStart(
|
|||||||
** to access the data.
|
** to access the data.
|
||||||
*/
|
*/
|
||||||
int iReg; /* P3 Value for OP_VFilter */
|
int iReg; /* P3 Value for OP_VFilter */
|
||||||
|
int addrNotFound;
|
||||||
sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
|
sqlite3_index_info *pVtabIdx = pLevel->plan.u.pVtabIdx;
|
||||||
int nConstraint = pVtabIdx->nConstraint;
|
int nConstraint = pVtabIdx->nConstraint;
|
||||||
struct sqlite3_index_constraint_usage *aUsage =
|
struct sqlite3_index_constraint_usage *aUsage =
|
||||||
@ -4039,11 +4043,18 @@ static Bitmask codeOneLoopStart(
|
|||||||
|
|
||||||
sqlite3ExprCachePush(pParse);
|
sqlite3ExprCachePush(pParse);
|
||||||
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
|
iReg = sqlite3GetTempRange(pParse, nConstraint+2);
|
||||||
|
addrNotFound = pLevel->addrBrk;
|
||||||
for(j=1; j<=nConstraint; j++){
|
for(j=1; j<=nConstraint; j++){
|
||||||
for(k=0; k<nConstraint; k++){
|
for(k=0; k<nConstraint; k++){
|
||||||
if( aUsage[k].argvIndex==j ){
|
if( aUsage[k].argvIndex==j ){
|
||||||
int iTerm = aConstraint[k].iTermOffset;
|
WhereTerm *pTerm = &pWC->a[aConstraint[k].iTermOffset];
|
||||||
sqlite3ExprCode(pParse, pWC->a[iTerm].pExpr->pRight, iReg+j+1);
|
int iTarget = iReg+j+1;
|
||||||
|
if( pTerm->eOperator & WO_IN ){
|
||||||
|
codeEqualityTerm(pParse, pTerm, pLevel, iTarget);
|
||||||
|
addrNotFound = pLevel->addrNxt;
|
||||||
|
}else{
|
||||||
|
sqlite3ExprCode(pParse, pTerm->pExpr->pRight, iTarget);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4051,7 +4062,7 @@ static Bitmask codeOneLoopStart(
|
|||||||
}
|
}
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
|
sqlite3VdbeAddOp2(v, OP_Integer, pVtabIdx->idxNum, iReg);
|
||||||
sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
|
sqlite3VdbeAddOp2(v, OP_Integer, j-1, iReg+1);
|
||||||
sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrBrk, iReg, pVtabIdx->idxStr,
|
sqlite3VdbeAddOp4(v, OP_VFilter, iCur, addrNotFound, iReg, pVtabIdx->idxStr,
|
||||||
pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
|
pVtabIdx->needToFreeIdxStr ? P4_MPRINTF : P4_STATIC);
|
||||||
pVtabIdx->needToFreeIdxStr = 0;
|
pVtabIdx->needToFreeIdxStr = 0;
|
||||||
for(j=0; j<nConstraint; j++){
|
for(j=0; j<nConstraint; j++){
|
||||||
|
@ -1091,12 +1091,54 @@ do_test vtab1.13-3 {
|
|||||||
} {15 {} 16}
|
} {15 {} 16}
|
||||||
|
|
||||||
|
|
||||||
|
do_test vtab1-14.001 {
|
||||||
|
execsql {SELECT rowid, * FROM echo_c WHERE +rowid IN (1,2,3)}
|
||||||
|
} {1 3 G H 2 {} 15 16 3 15 {} 16}
|
||||||
|
do_test vtab1-14.002 {
|
||||||
|
execsql {SELECT rowid, * FROM echo_c WHERE rowid IN (1,2,3)}
|
||||||
|
} {1 3 G H 2 {} 15 16 3 15 {} 16}
|
||||||
|
do_test vtab1-14.003 {
|
||||||
|
execsql {SELECT rowid, * FROM echo_c WHERE +rowid IN (0,1,5,2,'a',3,NULL)}
|
||||||
|
} {1 3 G H 2 {} 15 16 3 15 {} 16}
|
||||||
|
do_test vtab1-14.004 {
|
||||||
|
execsql {SELECT rowid, * FROM echo_c WHERE rowid IN (0,1,5,'a',2,3,NULL)}
|
||||||
|
} {1 3 G H 2 {} 15 16 3 15 {} 16}
|
||||||
|
do_test vtab1-14.005 {
|
||||||
|
execsql {SELECT rowid, * FROM echo_c WHERE rowid NOT IN (0,1,5,'a',2,3)}
|
||||||
|
} {}
|
||||||
|
do_test vtab1-14.006 {
|
||||||
|
execsql {SELECT rowid, * FROM echo_c WHERE rowid NOT IN (0,5,'a',2,3)}
|
||||||
|
} {1 3 G H}
|
||||||
|
do_test vtab1-14.007 {
|
||||||
|
execsql {SELECT rowid, * FROM echo_c WHERE +rowid NOT IN (0,5,'a',2,3,NULL)}
|
||||||
|
} {}
|
||||||
|
do_test vtab1-14.008 {
|
||||||
|
execsql {SELECT rowid, * FROM echo_c WHERE rowid NOT IN (0,5,'a',2,3,NULL)}
|
||||||
|
} {}
|
||||||
|
do_test vtab1-14.011 {
|
||||||
|
execsql {SELECT * FROM echo_c WHERE +a IN (1,3,8,'x',NULL,15,24)}
|
||||||
|
} {3 G H 15 {} 16}
|
||||||
|
do_test vtab1-14.012 {
|
||||||
|
execsql {SELECT * FROM echo_c WHERE a IN (1,3,8,'x',NULL,15,24)}
|
||||||
|
} {3 G H 15 {} 16}
|
||||||
|
do_test vtab1-14.013 {
|
||||||
|
execsql {SELECT * FROM echo_c WHERE a NOT IN (1,8,'x',15,24)}
|
||||||
|
} {3 G H}
|
||||||
|
do_test vtab1-14.014 {
|
||||||
|
execsql {SELECT * FROM echo_c WHERE a NOT IN (1,8,'x',NULL,15,24)}
|
||||||
|
} {}
|
||||||
|
do_test vtab1-14.015 {
|
||||||
|
execsql {SELECT * FROM echo_c WHERE +a NOT IN (1,8,'x',NULL,15,24)}
|
||||||
|
} {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
do_test vtab1-14.1 {
|
do_test vtab1-14.1 {
|
||||||
execsql { DELETE FROM c }
|
execsql { DELETE FROM c }
|
||||||
set echo_module ""
|
set echo_module ""
|
||||||
execsql { SELECT * FROM echo_c WHERE rowid IN (1, 2, 3) }
|
execsql { SELECT * FROM echo_c WHERE rowid IN (1, 2, 3) }
|
||||||
set echo_module
|
set echo_module
|
||||||
} [list xBestIndex {SELECT rowid, * FROM 'c'} xFilter {SELECT rowid, * FROM 'c'}]
|
} {/xBestIndex {SELECT rowid, . FROM 'c' WHERE rowid = .} xFilter {SELECT rowid, . FROM 'c' WHERE rowid = .} 1/}
|
||||||
|
|
||||||
do_test vtab1-14.2 {
|
do_test vtab1-14.2 {
|
||||||
set echo_module ""
|
set echo_module ""
|
||||||
@ -1114,7 +1156,7 @@ do_test vtab1-14.4 {
|
|||||||
set echo_module ""
|
set echo_module ""
|
||||||
execsql { SELECT * FROM echo_c WHERE a IN (1, 2) }
|
execsql { SELECT * FROM echo_c WHERE a IN (1, 2) }
|
||||||
set echo_module
|
set echo_module
|
||||||
} [list xBestIndex {SELECT rowid, * FROM 'c'} xFilter {SELECT rowid, * FROM 'c'}]
|
} {/xBestIndex {SELECT rowid, . FROM 'c' WHERE a = .} xFilter {SELECT rowid, . FROM 'c' WHERE a = .} 1/}
|
||||||
|
|
||||||
do_test vtab1-15.1 {
|
do_test vtab1-15.1 {
|
||||||
execsql {
|
execsql {
|
||||||
|
Reference in New Issue
Block a user