aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/expr.c53
-rw-r--r--src/resolve.c34
-rw-r--r--src/sqliteInt.h3
-rw-r--r--src/vdbe.c28
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, &regFree1);
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 &rarr; r[P2] = r[P1] IS TRUE
+** <li> P3==1, P4==1 &rarr; r[P2] = r[P1] IS FALSE
+** <li> P3==0, P4==1 &rarr; r[P2] = r[P1] IS NOT TRUE
+** <li> P3==1, P4==0 &rarr; 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]
**