diff options
Diffstat (limited to 'src/expr.c')
-rw-r--r-- | src/expr.c | 38 |
1 files changed, 24 insertions, 14 deletions
diff --git a/src/expr.c b/src/expr.c index 403ecc8c2..37d16fe40 100644 --- a/src/expr.c +++ b/src/expr.c @@ -611,6 +611,7 @@ static void codeVectorCompare( int regLeft = 0; int regRight = 0; u8 opx = op; + int addrCmp = 0; int addrDone = sqlite3VdbeMakeLabel(pParse); int isCommuted = ExprHasProperty(pExpr,EP_Commuted); @@ -630,21 +631,24 @@ static void codeVectorCompare( assert( p5==0 || pExpr->op!=op ); assert( p5==SQLITE_NULLEQ || pExpr->op==op ); - p5 |= SQLITE_STOREP2; - if( opx==TK_LE ) opx = TK_LT; - if( opx==TK_GE ) opx = TK_GT; + if( op==TK_LE ) opx = TK_LT; + if( op==TK_GE ) opx = TK_GT; + if( op==TK_NE ) opx = TK_EQ; regLeft = exprCodeSubselect(pParse, pLeft); regRight = exprCodeSubselect(pParse, pRight); + sqlite3VdbeAddOp2(v, OP_Integer, 1, dest); for(i=0; 1 /*Loop exits by "break"*/; i++){ int regFree1 = 0, regFree2 = 0; Expr *pL, *pR; int r1, r2; assert( i>=0 && i<nLeft ); + if( addrCmp ) sqlite3VdbeJumpHere(v, addrCmp); r1 = exprVectorRegister(pParse, pLeft, i, regLeft, &pL, ®Free1); r2 = exprVectorRegister(pParse, pRight, i, regRight, &pR, ®Free2); - codeCompare(pParse, pL, pR, opx, r1, r2, dest, p5, isCommuted); + addrCmp = sqlite3VdbeCurrentAddr(v); + codeCompare(pParse, pL, pR, opx, r1, r2, addrDone, p5, isCommuted); testcase(op==OP_Lt); VdbeCoverageIf(v,op==OP_Lt); testcase(op==OP_Le); VdbeCoverageIf(v,op==OP_Le); testcase(op==OP_Gt); VdbeCoverageIf(v,op==OP_Gt); @@ -653,26 +657,32 @@ static void codeVectorCompare( testcase(op==OP_Ne); VdbeCoverageIf(v,op==OP_Ne); sqlite3ReleaseTempReg(pParse, regFree1); sqlite3ReleaseTempReg(pParse, regFree2); + if( (opx==TK_LT || opx==TK_GT) && i<nLeft-1 ){ + addrCmp = sqlite3VdbeAddOp0(v, OP_ElseEq); + testcase(opx==TK_LT); VdbeCoverageIf(v,opx==TK_LT); + testcase(opx==TK_GT); VdbeCoverageIf(v,opx==TK_GT); + } + if( p5==SQLITE_NULLEQ ){ + sqlite3VdbeAddOp2(v, OP_Integer, 0, dest); + }else{ + sqlite3VdbeAddOp3(v, OP_ZeroOrNull, r1, dest, r2); + } if( i==nLeft-1 ){ break; } if( opx==TK_EQ ){ - sqlite3VdbeAddOp2(v, OP_IfNot, dest, addrDone); VdbeCoverage(v); - p5 |= SQLITE_KEEPNULL; - }else if( opx==TK_NE ){ - sqlite3VdbeAddOp2(v, OP_If, dest, addrDone); VdbeCoverage(v); - p5 |= SQLITE_KEEPNULL; + sqlite3VdbeAddOp2(v, OP_NotNull, dest, addrDone); VdbeCoverage(v); }else{ assert( op==TK_LT || op==TK_GT || op==TK_LE || op==TK_GE ); - sqlite3VdbeAddOp2(v, OP_ElseNotEq, 0, addrDone); - VdbeCoverageIf(v, op==TK_LT); - VdbeCoverageIf(v, op==TK_GT); - VdbeCoverageIf(v, op==TK_LE); - VdbeCoverageIf(v, op==TK_GE); + sqlite3VdbeAddOp2(v, OP_Goto, 0, addrDone); if( i==nLeft-2 ) opx = op; } } + sqlite3VdbeJumpHere(v, addrCmp); sqlite3VdbeResolveLabel(v, addrDone); + if( op==TK_NE ){ + sqlite3VdbeAddOp2(v, OP_Not, dest, dest); + } } #if SQLITE_MAX_EXPR_DEPTH>0 |