An early attempt to get indexes to work with the IS operator. This code

passes tests, but much more testing is needed to verify that it works on
all corner cases.

FossilOrigin-Name: 6f7f1673d00d216a5aa456acb44793a14f3b3d91
This commit is contained in:
drh
2015-05-13 15:24:07 +00:00
parent 13a24f841c
commit fcd49531c9
4 changed files with 32 additions and 22 deletions
+11 -8
View File
@@ -1,5 +1,5 @@
C Enhancements\sto\sthe\sMSVC\smakefile.
D 2015-05-13T04:50:30.732
C An\searly\sattempt\sto\sget\sindexes\sto\swork\swith\sthe\sIS\soperator.\s\sThis\scode\npasses\stests,\sbut\smuch\smore\stesting\sis\sneeded\sto\sverify\sthat\sit\sworks\son\nall\scorner\scases.
D 2015-05-13T15:24:07.257
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in edfc69769e613a6359c42c06ea1d42c3bece1736
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
@@ -307,8 +307,8 @@ F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c ce2cb2d06faab54d1bce3e739bec79e063dd9113
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F src/walker.c c253b95b4ee44b21c406e2a1052636c31ea27804
F src/where.c 85fff9c40569ccb79c3177419b339e7d7df566cb
F src/whereInt.h cbe4aa57326998d89e7698ca65bb7c28541d483c
F src/where.c 48e3c1f0a8a7ecbaeb5a57c195254243d49430ba
F src/whereInt.h 6b5a8ac7b4adc055176c3330d755735ed674335d
F test/8_3_names.test ebbb5cd36741350040fd28b432ceadf495be25b2
F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2
F test/aggnested.test b35b4cd69fc913f90d39a575e171e1116c3a4bb7
@@ -1258,7 +1258,10 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
P b33f1bacfdb34fe66b7b073e68bfac38498d6e88
R 786cf9bafb843a30daaea508385a36b1
U mistachkin
Z cf0d8cd171ac487c0fd87c289759c254
P 59e3e9e764440b7feaafadff74f422535d21bca2
R 9f6038338a4c8e424f8c4ba92f9afc16
T *branch * index-is-operator
T *sym-index-is-operator *
T -sym-trunk *
U drh
Z a0eadd388567e992c46f2fabbded464e
+1 -1
View File
@@ -1 +1 @@
59e3e9e764440b7feaafadff74f422535d21bca2
6f7f1673d00d216a5aa456acb44793a14f3b3d91
+19 -13
View File
@@ -363,7 +363,7 @@ static int allowedOp(int op){
assert( TK_LT>TK_EQ && TK_LT<TK_GE );
assert( TK_LE>TK_EQ && TK_LE<TK_GE );
assert( TK_GE==TK_EQ+4 );
return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL;
return op==TK_IN || (op>=TK_EQ && op<=TK_GE) || op==TK_ISNULL || op==TK_IS;
}
/*
@@ -416,6 +416,8 @@ static u16 operatorMask(int op){
c = WO_IN;
}else if( op==TK_ISNULL ){
c = WO_ISNULL;
}else if( op==TK_IS ){
c = WO_EQ;
}else{
assert( (WO_EQ<<(op-TK_EQ)) < 0x7fff );
c = (u16)(WO_EQ<<(op-TK_EQ));
@@ -427,6 +429,7 @@ static u16 operatorMask(int op){
assert( op!=TK_LE || c==WO_LE );
assert( op!=TK_GT || c==WO_GT );
assert( op!=TK_GE || c==WO_GE );
assert( op!=TK_IS || c==WO_EQ );
return c;
}
@@ -1254,6 +1257,7 @@ static void exprAnalyze(
pTerm->u.leftColumn = pLeft->iColumn;
pTerm->eOperator = operatorMask(op) & opMask;
}
if( op==TK_IS ) pTerm->wtFlags |= TERM_NULLOK;
if( pRight && pRight->op==TK_COLUMN ){
WhereTerm *pNew;
Expr *pDup;
@@ -1278,6 +1282,7 @@ static void exprAnalyze(
pTerm->eOperator |= WO_EQUIV;
eExtraOp = WO_EQUIV;
}
if( op==TK_IS ) pNew->wtFlags |= TERM_NULLOK;
}else{
pDup = pExpr;
pNew = pTerm;
@@ -1468,10 +1473,8 @@ static void exprAnalyze(
** as "x>NULL" if x is not an INTEGER PRIMARY KEY. So construct a
** virtual term of that form.
**
** Note that the virtual term must be tagged with TERM_VNULL. This
** TERM_VNULL tag will suppress the not-null check at the beginning
** of the loop. Without the TERM_VNULL flag, the not-null check at
** the start of the loop will prevent any results from being returned.
** Note that the virtual term must be tagged with both TERM_VNULL
** and TERM_NULLOK.
*/
if( pExpr->op==TK_NOTNULL
&& pExpr->pLeft->op==TK_COLUMN
@@ -1488,7 +1491,7 @@ static void exprAnalyze(
sqlite3PExpr(pParse, TK_NULL, 0, 0, 0), 0);
idxNew = whereClauseInsert(pWC, pNewExpr,
TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL);
TERM_VIRTUAL|TERM_DYNAMIC|TERM_VNULL|TERM_NULLOK);
if( idxNew ){
pNewTerm = &pWC->a[idxNew];
pNewTerm->prereqRight = 0;
@@ -2792,7 +2795,7 @@ static int codeEqualityTerm(
int iReg; /* Register holding results */
assert( iTarget>0 );
if( pX->op==TK_EQ ){
if( pX->op==TK_EQ || pX->op==TK_IS ){
iReg = sqlite3ExprCodeTarget(pParse, pX->pRight, iTarget);
}else if( pX->op==TK_ISNULL ){
iReg = iTarget;
@@ -2977,7 +2980,9 @@ static int codeAllEqualityTerms(
testcase( pTerm->eOperator & WO_IN );
if( (pTerm->eOperator & (WO_ISNULL|WO_IN))==0 ){
Expr *pRight = pTerm->pExpr->pRight;
if( sqlite3ExprCanBeNull(pRight) ){
if( (pTerm->wtFlags & TERM_NULLOK)==0
&& sqlite3ExprCanBeNull(pRight)
){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+j, pLevel->addrBrk);
VdbeCoverage(v);
}
@@ -3626,7 +3631,7 @@ static Bitmask codeOneLoopStart(
Expr *pRight = pRangeStart->pExpr->pRight;
sqlite3ExprCode(pParse, pRight, regBase+nEq);
whereLikeOptimizationStringFixup(v, pLevel, pRangeStart);
if( (pRangeStart->wtFlags & TERM_VNULL)==0
if( (pRangeStart->wtFlags & TERM_NULLOK)==0
&& sqlite3ExprCanBeNull(pRight)
){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
@@ -3672,7 +3677,7 @@ static Bitmask codeOneLoopStart(
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
sqlite3ExprCode(pParse, pRight, regBase+nEq);
whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
if( (pRangeEnd->wtFlags & TERM_NULLOK)==0
&& sqlite3ExprCanBeNull(pRight)
){
sqlite3VdbeAddOp2(v, OP_IsNull, regBase+nEq, addrNxt);
@@ -4158,9 +4163,10 @@ static void whereTermPrint(WhereTerm *pTerm, int iTerm){
if( pTerm->wtFlags & TERM_VIRTUAL ) zType[0] = 'V';
if( pTerm->eOperator & WO_EQUIV ) zType[1] = 'E';
if( ExprHasProperty(pTerm->pExpr, EP_FromJoin) ) zType[2] = 'L';
sqlite3DebugPrintf("TERM-%-3d %p %s cursor=%-3d prob=%-3d op=0x%03x\n",
iTerm, pTerm, zType, pTerm->leftCursor, pTerm->truthProb,
pTerm->eOperator);
sqlite3DebugPrintf(
"TERM-%-3d %p %s cursor=%-3d prob=%-3d op=0x%03x wtFlags=0x%04x\n",
iTerm, pTerm, zType, pTerm->leftCursor, pTerm->truthProb,
pTerm->eOperator, pTerm->wtFlags);
sqlite3TreeViewExpr(0, pTerm->pExpr, 0);
}
}
+1
View File
@@ -280,6 +280,7 @@ struct WhereTerm {
#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */
#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
#define TERM_LIKE 0x400 /* The original LIKE operator */
#define TERM_NULLOK 0x800 /* Comparison operators against NULL work */
/*
** An instance of the WhereScan object is used as an iterator for locating