aboutsummaryrefslogtreecommitdiff
path: root/src/expr.c
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2009-09-23 02:29:36 +0000
committerdrh <drh@noemail.net>2009-09-23 02:29:36 +0000
commit6a2fe09387572e67602e84517d9a68063040209e (patch)
tree677b41cd38277f580dc81cd790ce7b8cebdc12d2 /src/expr.c
parent7ba5bc5bf20bbcd3720230106955800da59418b7 (diff)
downloadsqlite-6a2fe09387572e67602e84517d9a68063040209e.tar.gz
sqlite-6a2fe09387572e67602e84517d9a68063040209e.zip
Generalize the IS and IS NOT operators so that their right-hand side can be
an arbitrary expression and not simple the constant NULL. They work like = and <> except that NULL values compare equal to one another an unequal to everything else. FossilOrigin-Name: 98853f6104076c50ea92175e17a3254bfbbd4619
Diffstat (limited to 'src/expr.c')
-rw-r--r--src/expr.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/src/expr.c b/src/expr.c
index 50b24de41..998bf41a8 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -152,7 +152,7 @@ static char comparisonAffinity(Expr *pExpr){
char aff;
assert( pExpr->op==TK_EQ || pExpr->op==TK_IN || pExpr->op==TK_LT ||
pExpr->op==TK_GT || pExpr->op==TK_GE || pExpr->op==TK_LE ||
- pExpr->op==TK_NE );
+ pExpr->op==TK_NE || pExpr->op==TK_IS || pExpr->op==TK_ISNOT );
assert( pExpr->pLeft );
aff = sqlite3ExprAffinity(pExpr->pLeft);
if( pExpr->pRight ){
@@ -2244,6 +2244,19 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
testcase( regFree2==0 );
break;
}
+ case TK_IS:
+ case TK_ISNOT: {
+ testcase( op==TK_IS );
+ testcase( op==TK_ISNOT );
+ codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
+ pExpr->pRight, &r2, &regFree2);
+ op = (op==TK_IS) ? TK_EQ : TK_NE;
+ codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+ r1, r2, inReg, SQLITE_STOREP2 | SQLITE_NULLEQ);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
+ break;
+ }
case TK_AND:
case TK_OR:
case TK_PLUS:
@@ -3018,6 +3031,19 @@ void sqlite3ExprIfTrue(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( regFree2==0 );
break;
}
+ case TK_IS:
+ case TK_ISNOT: {
+ testcase( op==TK_IS );
+ testcase( op==TK_ISNOT );
+ codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
+ pExpr->pRight, &r2, &regFree2);
+ op = (op==TK_IS) ? TK_EQ : TK_NE;
+ codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+ r1, r2, dest, SQLITE_NULLEQ);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
+ break;
+ }
case TK_ISNULL:
case TK_NOTNULL: {
assert( TK_ISNULL==OP_IsNull );
@@ -3167,6 +3193,19 @@ void sqlite3ExprIfFalse(Parse *pParse, Expr *pExpr, int dest, int jumpIfNull){
testcase( regFree2==0 );
break;
}
+ case TK_IS:
+ case TK_ISNOT: {
+ testcase( op==TK_IS );
+ testcase( op==TK_ISNOT );
+ codeCompareOperands(pParse, pExpr->pLeft, &r1, &regFree1,
+ pExpr->pRight, &r2, &regFree2);
+ op = (pExpr->op==TK_IS) ? TK_NE : TK_EQ;
+ codeCompare(pParse, pExpr->pLeft, pExpr->pRight, op,
+ r1, r2, dest, SQLITE_NULLEQ);
+ testcase( regFree1==0 );
+ testcase( regFree2==0 );
+ break;
+ }
case TK_ISNULL:
case TK_NOTNULL: {
testcase( op==TK_ISNULL );