diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/expr.c | 53 | ||||
-rw-r--r-- | src/resolve.c | 34 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/vdbe.c | 28 |
4 files changed, 86 insertions, 32 deletions
diff --git a/src/expr.c b/src/expr.c index 5079035ca..f32a03a6d 100644 --- a/src/expr.c +++ b/src/expr.c @@ -3543,12 +3543,8 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ codeInteger(pParse, pExpr, 0, target); return target; } - case TK_TRUE: { - sqlite3VdbeAddOp2(v, OP_Integer, 1, target); - return target; - } - case TK_FALSE: { - sqlite3VdbeAddOp2(v, OP_Integer, 0, target); + case TK_TRUEFALSE: { + sqlite3VdbeAddOp2(v, OP_Integer, pExpr->iTable, target); return target; } #ifndef SQLITE_OMIT_FLOATING_POINT @@ -3706,11 +3702,14 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){ sqlite3VdbeAddOp2(v, op, r1, inReg); break; } - case TK_ISTRUE: { + case TK_TRUTH: { + assert( pExpr->pRight->op==TK_TRUEFALSE ); + assert( pExpr->pRight->iTable==0 || pExpr->pRight->iTable==1 ); + assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); r1 = sqlite3ExprCodeTemp(pParse, pExpr->pLeft, ®Free1); testcase( regFree1==0 ); - sqlite3VdbeAddOp2(v, OP_Not, r1, inReg); - sqlite3VdbeAddOp2(v, OP_Not, inReg, inReg); + sqlite3VdbeAddOp4Int(v, OP_IsTrue, r1, inReg, !pExpr->pRight->iTable, + pExpr->pRight->iTable ^ (pExpr->op2==TK_IS)); break; } case TK_ISNULL: @@ -4488,9 +4487,21 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); break; } - case TK_ISTRUE: { + case TK_TRUTH: { + int isNot; testcase( jumpIfNull==0 ); - sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); + assert( pExpr->pRight->op==TK_TRUEFALSE ); + assert( pExpr->pRight->iTable==0 || pExpr->pRight->iTable==1 ); + testcase( pExpr->pRight->iTable==0 ); + assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); + isNot = pExpr->op2==TK_ISNOT; + if( pExpr->pRight->iTable ^ isNot ){ + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, + isNot ? SQLITE_JUMPIFNULL : 0); + }else{ + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, + isNot ? SQLITE_JUMPIFNULL : 0); + } break; } case TK_IS: @@ -4647,9 +4658,25 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){ sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, jumpIfNull); break; } - case TK_ISTRUE: { + case TK_TRUTH: { testcase( jumpIfNull==0 ); - sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, jumpIfNull); + int isNot; + testcase( jumpIfNull==0 ); + assert( pExpr->pRight->op==TK_TRUEFALSE ); + assert( pExpr->pRight->iTable==0 || pExpr->pRight->iTable==1 ); + testcase( pExpr->pRight->iTable==0 ); + assert( pExpr->op2==TK_IS || pExpr->op2==TK_ISNOT ); + isNot = pExpr->op2==TK_ISNOT; + if( pExpr->pRight->iTable ^ isNot ){ + /* IS TRUE and IS NOT FALSE */ + sqlite3ExprIfFalse(pParse, pExpr->pLeft, dest, + isNot ? 0 : SQLITE_JUMPIFNULL); + + }else{ + /* IS FALSE and IS NOT TRUE */ + sqlite3ExprIfTrue(pParse, pExpr->pLeft, dest, + isNot ? 0: SQLITE_JUMPIFNULL); + } break; } case TK_IS: diff --git a/src/resolve.c b/src/resolve.c index fb00788dd..c6b086c3a 100644 --- a/src/resolve.c +++ b/src/resolve.c @@ -437,13 +437,9 @@ static int lookupName( pExpr->pTab = 0; return WRC_Prune; } - if( sqlite3StrICmp(zCol, "true")==0 ){ - pExpr->op = TK_TRUE; - pExpr->pTab = 0; - return WRC_Prune; - } - if( sqlite3StrICmp(zCol, "false")==0 ){ - pExpr->op = TK_FALSE; + if( sqlite3StrICmp(zCol, "true")==0 || sqlite3StrICmp(zCol, "false")==0 ){ + pExpr->op = TK_TRUEFALSE; + pExpr->iTable = zCol[4]==0; pExpr->pTab = 0; return WRC_Prune; } @@ -796,28 +792,30 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){ break; } case TK_IS: - /* Handle special cases of "x IS TRUE" and "x IS FALSE". The first - ** is transformed into "+x" and the second into "NOT x". */ - if( pExpr->pRight->op==TK_ID ){ - int rc = resolveExprStep(pWalker, pExpr->pRight); + case TK_ISNOT: { + Expr *pRight; + assert( !ExprHasProperty(pExpr, EP_Reduced) ); + /* Handle special cases of "x IS TRUE", "x IS FALSE", "x IS NOT TRUE", + ** and "x IS NOT FALSE". */ + if( (pRight = pExpr->pRight)->op==TK_ID ){ + int rc = resolveExprStep(pWalker, pRight); if( rc==WRC_Abort ) return WRC_Abort; - if( pExpr->pRight->op==TK_TRUE ){ - pExpr->op = TK_ISTRUE; - return WRC_Continue; - }else if( pExpr->pRight->op==TK_FALSE ){ - pExpr->op = TK_NOT; + if( pRight->op==TK_TRUEFALSE ){ + assert( pRight->iTable==0 || pRight->iTable==1 ); + pExpr->op2 = pExpr->op; + pExpr->op = TK_TRUTH; return WRC_Continue; } } /* Fall thru */ + } case TK_BETWEEN: case TK_EQ: case TK_NE: case TK_LT: case TK_LE: case TK_GT: - case TK_GE: - case TK_ISNOT: { + case TK_GE: { int nLeft, nRight; if( pParse->db->mallocFailed ) break; assert( pExpr->pLeft!=0 ); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index f4c82cdb6..6da57c25f 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -2387,7 +2387,8 @@ struct Expr { ** TK_REGISTER: register number ** TK_TRIGGER: 1 -> new, 0 -> old ** EP_Unlikely: 134217728 times likelihood - ** TK_SELECT: 1st register of result vector */ + ** TK_SELECT: 1st register of result vector + ** TK_TRUEFALSE: 1 for true, 0 for false */ ynVar iColumn; /* TK_COLUMN: column index. -1 for rowid. ** TK_VARIABLE: variable number (always >= 1). ** TK_SELECT_COLUMN: column of the result vector */ diff --git a/src/vdbe.c b/src/vdbe.c index 61fc55e4d..cdc16292b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -2191,6 +2191,34 @@ case OP_Or: { /* same as TK_OR, in1, in2, out3 */ break; } +/* Opcode: IsTrue P1 P2 P3 P4 * +** Synopsis: r[P2] = coalesce(r[P1]==TRUE,P3) ^ P4 +** +** This opcode implements the IS TRUE, IS FALSE, IS NOT TRUE, and +** IS NOT FALSE operators. +** +** Interpret the value in register P1 as a boolean value. Store the that +** boolean (a 0 or 1) in register P2. Or if the value in register P1 is +** NULL, then the P3 is stored in register P2. Invert the answer if P4 +** is 1. +** +** The logic is summarized like this: +** +** <ul> +** <li> P3==0, P4==0 → r[P2] = r[P1] IS TRUE +** <li> P3==1, P4==1 → r[P2] = r[P1] IS FALSE +** <li> P3==0, P4==1 → r[P2] = r[P1] IS NOT TRUE +** <li> P3==1, P4==0 → r[P2] = r[P1] IS NOT FALSE +** </ul> +*/ +case OP_IsTrue: { /* in1, out2 */ + assert( pOp->p4type==P4_INT32 ); + assert( pOp->p4.i==0 || pOp->p4.i==1 ); + sqlite3VdbeMemSetInt64(&aMem[pOp->p2], + sqlite3VdbeBooleanValue(&aMem[pOp->p1], pOp->p3) ^ pOp->p4.i); + break; +} + /* Opcode: Not P1 P2 * * * ** Synopsis: r[P2]= !r[P1] ** |