diff options
3 files changed, 61 insertions, 3 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java index e0f6e25..407ec52 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/BuiltinOperators.java @@ -485,6 +485,10 @@ public class BuiltinOperators return toValue(pattern.matcher(param1.getAsString()).matches()); } + public static Value notLike(Value param1, Pattern pattern) { + return not(like(param1, pattern)); + } + public static Value between(Value param1, Value param2, Value param3) { // null propagate any param. uses short circuit eval of params if(anyParamIsNull(param1, param2, param3)) { diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java b/src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java index 7bd7396..96deb27 100644 --- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java +++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java @@ -325,6 +325,11 @@ public class Expressionator return BuiltinOperators.like(param1, (Pattern)param2); } }, + NOT_LIKE("Not Like") { + @Override public Value eval(Value param1, Object param2, Object param3) { + return BuiltinOperators.notLike(param1, (Pattern)param2); + } + }, BETWEEN("Between") { @Override public Value eval(Value param1, Object param2, Object param3) { return BuiltinOperators.between(param1, (Value)param2, (Value)param3); @@ -371,7 +376,8 @@ public class Expressionator new OpType[]{BinaryOp.PLUS, BinaryOp.MINUS}, new OpType[]{BinaryOp.CONCAT}, new OpType[]{CompOp.LT, CompOp.GT, CompOp.NE, CompOp.LTE, CompOp.GTE, - CompOp.EQ, SpecOp.LIKE, SpecOp.IS_NULL, SpecOp.IS_NOT_NULL}, + CompOp.EQ, SpecOp.LIKE, SpecOp.NOT_LIKE, + SpecOp.IS_NULL, SpecOp.IS_NOT_NULL}, new OpType[]{UnaryOp.NOT}, new OpType[]{LogOp.AND}, new OpType[]{LogOp.OR}, @@ -846,6 +852,7 @@ public class Expressionator break; case LIKE: + case NOT_LIKE: Token t = buf.next(); if((t.getType() != TokenType.LITERAL) || (t.getValueType() != Value.Type.STRING)) { @@ -941,6 +948,9 @@ public class Expressionator } else if(isString(t, "in")) { buf.next(); return SpecOp.NOT_IN; + } else if(isString(t, "like")) { + buf.next(); + return SpecOp.NOT_LIKE; } return SpecOp.NOT; } diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java index 227ffdc..ef5cef3 100644 --- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java +++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java @@ -280,6 +280,7 @@ public class ExpressionatorTest extends TestCase { assertEquals(TRUE_NUM, eval("='blah'<'fuzz'")); assertEquals(FALSE_NUM, eval("=23>56")); + assertEquals(FALSE_NUM, eval("=23>=56")); assertEquals(TRUE_NUM, eval("=13.2<=45.8")); assertEquals(FALSE_NUM, eval("='blah'='fuzz'")); assertEquals(TRUE_NUM, eval("='blah'<>'fuzz'")); @@ -288,7 +289,11 @@ public class ExpressionatorTest extends TestCase assertEquals(FALSE_NUM, eval("='blah' Is Null")); assertEquals(TRUE_NUM, eval("='blah' Is Not Null")); + assertEquals(TRUE_NUM, eval("=Null Is Null")); + assertEquals(FALSE_NUM, eval("=Null Is Not Null")); + assertEquals(TRUE_NUM, eval("='blah' Between 'a' And 'z'")); + assertEquals(TRUE_NUM, eval("='blah' Between 'z' And 'a'")); assertEquals(FALSE_NUM, eval("='blah' Not Between 'a' And 'z'")); assertEquals(TRUE_NUM, eval("='blah' In ('foo','bar','blah')")); @@ -296,6 +301,7 @@ public class ExpressionatorTest extends TestCase assertEquals(TRUE_NUM, eval("=True Xor False")); assertEquals(TRUE_NUM, eval("=True Or False")); + assertEquals(TRUE_NUM, eval("=False Or True")); assertEquals(FALSE_NUM, eval("=True Imp False")); assertEquals(FALSE_NUM, eval("=True Eqv False")); assertEquals(TRUE_NUM, eval("=Not(True Eqv False)")); @@ -304,6 +310,45 @@ public class ExpressionatorTest extends TestCase public void testDateArith() throws Exception { assertEquals(new Date(1041508800000L), eval("=#01/02/2003# + #7:00:00#")); + assertEquals(new Date(1041458400000L), eval("=#01/02/2003# - #7:00:00#")); + assertEquals(new Date(1044680400000L), eval("=#01/02/2003# + '37'")); + assertEquals(new Date(1044680400000L), eval("='37' + #01/02/2003#")); + assertEquals(new Date(1041508800000L), eval("=#01/02/2003 7:00:00#")); + } + + public void testNull() throws Exception + { + assertNull(eval("=37 + Null")); + assertNull(eval("=37 - Null")); + assertNull(eval("=37 / Null")); + assertNull(eval("=37 * Null")); + assertNull(eval("=37 ^ Null")); + assertEquals("37", eval("=37 & Null")); + assertEquals("37", eval("=Null & 37")); + assertNull(eval("=37 Mod Null")); + assertNull(eval("=37 \\ Null")); + assertNull(eval("=-(Null)")); + assertNull(eval("=+(Null)")); + assertNull(eval("=Not Null")); + assertEquals(TRUE_NUM, eval("=37 Or Null")); + assertNull(eval("=Null Or 37")); + assertNull(eval("=37 And Null")); + assertNull(eval("=Null And 37")); + assertNull(eval("=37 Xor Null")); + assertNull(eval("=37 Imp Null")); + assertNull(eval("=Null Imp Null")); + assertEquals(TRUE_NUM, eval("=Null Imp 37")); + assertNull(eval("=37 Eqv Null")); + assertNull(eval("=37 < Null")); + assertNull(eval("=37 > Null")); + assertNull(eval("=37 = Null")); + assertNull(eval("=37 <> Null")); + assertNull(eval("=37 <= Null")); + assertNull(eval("=37 >= Null")); + + assertNull(eval("=37 Between Null And 54")); + assertEquals(FALSE_NUM, eval("=37 In (23, Null, 45)")); + assertNull(eval("=Null In (23, Null, 45)")); } public void testTrickyMathExpressions() throws Exception @@ -356,8 +401,7 @@ public class ExpressionatorTest extends TestCase "<THIS_COL> Like \"[abc*\""); assertFalse(evalCondition("Like \"[abc*\"", "afcd")); assertFalse(evalCondition("Like \"[abc*\"", "fcd")); - // FIXME, does access support "not like" - //assertTrue(evalCondition("Not Like \"[abc*\"", "fcd")); + assertTrue(evalCondition("Not Like \"[abc*\"", "fcd")); assertFalse(evalCondition("Like \"[abc*\"", "")); } |