aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/expr/Expression.java4
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/BaseEvalContext.java4
-rw-r--r--src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java37
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java2
-rw-r--r--src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java31
5 files changed, 62 insertions, 16 deletions
diff --git a/src/main/java/com/healthmarketscience/jackcess/expr/Expression.java b/src/main/java/com/healthmarketscience/jackcess/expr/Expression.java
index 09fd03b..963af7b 100644
--- a/src/main/java/com/healthmarketscience/jackcess/expr/Expression.java
+++ b/src/main/java/com/healthmarketscience/jackcess/expr/Expression.java
@@ -22,12 +22,14 @@ import java.util.Collection;
*
* @author James Ahlborn
*/
-public interface Expression
+public interface Expression
{
public Object eval(EvalContext ctx);
public String toDebugString();
+ public String toRawString();
+
public boolean isConstant();
public void collectIdentifiers(Collection<Identifier> identifiers);
diff --git a/src/main/java/com/healthmarketscience/jackcess/impl/BaseEvalContext.java b/src/main/java/com/healthmarketscience/jackcess/impl/BaseEvalContext.java
index 640be96..4566225 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/BaseEvalContext.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/BaseEvalContext.java
@@ -195,6 +195,10 @@ public abstract class BaseEvalContext implements EvalContext
return "<raw>{" + _exprStr + "}";
}
+ public String toRawString() {
+ return _exprStr;
+ }
+
public boolean isConstant() {
return getExpr().isConstant();
}
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 c9af948..04c8aa0 100644
--- a/src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java
+++ b/src/main/java/com/healthmarketscience/jackcess/impl/expr/Expressionator.java
@@ -427,7 +427,7 @@ public class Expressionator
// this is handled as a literal string value, not an expression. no
// need to memo-ize cause it's a simple literal value
- return new ExprWrapper(
+ return new ExprWrapper(exprStr,
new ELiteralValue(Value.Type.STRING, exprStr, null), resultType);
}
@@ -447,15 +447,15 @@ public class Expressionator
return (expr.isConstant() ?
// for now, just cache at top-level for speed (could in theory
// cache intermediate values?)
- new MemoizedExprWrapper(expr, resultType) :
- new ExprWrapper(expr, resultType));
+ new MemoizedExprWrapper(exprStr, expr, resultType) :
+ new ExprWrapper(exprStr, expr, resultType));
case FIELD_VALIDATOR:
case RECORD_VALIDATOR:
return (expr.isConstant() ?
// for now, just cache at top-level for speed (could in theory
// cache intermediate values?)
- new MemoizedCondExprWrapper(expr) :
- new CondExprWrapper(expr));
+ new MemoizedCondExprWrapper(exprStr, expr) :
+ new CondExprWrapper(exprStr, expr));
default:
throw new ParseException("unexpected expression type " + exprType);
}
@@ -910,7 +910,7 @@ public class Expressionator
t = buf.next();
}
if(!isDelim(t, OPEN_PAREN)) {
- throw new ParseException("Malformed In expression " + buf);
+ throw new ParseException("Malformed 'In' expression " + buf);
}
List<Expr> exprs = findParenExprs(buf, true);
@@ -2007,9 +2007,11 @@ public class Expressionator
*/
private static abstract class BaseExprWrapper implements Expression
{
+ private final String _rawExprStr;
private final Expr _expr;
- private BaseExprWrapper(Expr expr) {
+ private BaseExprWrapper(String rawExprStr, Expr expr) {
+ _rawExprStr = rawExprStr;
_expr = expr;
}
@@ -2017,6 +2019,10 @@ public class Expressionator
return _expr.toDebugString();
}
+ public String toRawString() {
+ return _rawExprStr;
+ }
+
public boolean isConstant() {
return _expr.isConstant();
}
@@ -2080,8 +2086,8 @@ public class Expressionator
{
private final Value.Type _resultType;
- private ExprWrapper(Expr expr, Value.Type resultType) {
- super(expr);
+ private ExprWrapper(String rawExprStr, Expr expr, Value.Type resultType) {
+ super(rawExprStr, expr);
_resultType = resultType;
}
@@ -2096,8 +2102,8 @@ public class Expressionator
*/
private static class CondExprWrapper extends BaseExprWrapper
{
- private CondExprWrapper(Expr expr) {
- super(expr);
+ private CondExprWrapper(String rawExprStr, Expr expr) {
+ super(rawExprStr, expr);
}
public Object eval(EvalContext ctx) {
@@ -2113,8 +2119,9 @@ public class Expressionator
{
private Object _val;
- private MemoizedExprWrapper(Expr expr, Value.Type resultType) {
- super(expr, resultType);
+ private MemoizedExprWrapper(String rawExprStr, Expr expr,
+ Value.Type resultType) {
+ super(rawExprStr, expr, resultType);
}
@Override
@@ -2134,8 +2141,8 @@ public class Expressionator
{
private Object _val;
- private MemoizedCondExprWrapper(Expr expr) {
- super(expr);
+ private MemoizedCondExprWrapper(String rawExprStr, Expr expr) {
+ super(rawExprStr, expr);
}
@Override
diff --git a/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java b/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java
index 0b02888..c95fbaf 100644
--- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/DefaultFunctionsTest.java
@@ -33,6 +33,8 @@ public class DefaultFunctionsTest extends TestCase
super(name);
}
+ // FIXME, test more number/string functions
+
public void testFuncs() throws Exception
{
assertEquals("foo", eval("=IIf(10 > 1, \"foo\", \"bar\")"));
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 f491526..6c525cc 100644
--- a/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java
+++ b/src/test/java/com/healthmarketscience/jackcess/impl/expr/ExpressionatorTest.java
@@ -31,6 +31,7 @@ import com.healthmarketscience.jackcess.expr.EvalContext;
import com.healthmarketscience.jackcess.expr.Expression;
import com.healthmarketscience.jackcess.expr.FunctionLookup;
import com.healthmarketscience.jackcess.expr.Identifier;
+import com.healthmarketscience.jackcess.expr.ParseException;
import com.healthmarketscience.jackcess.expr.TemporalConfig;
import com.healthmarketscience.jackcess.expr.Value;
import com.healthmarketscience.jackcess.impl.BaseEvalContext;
@@ -462,6 +463,35 @@ public class ExpressionatorTest extends TestCase
br.close();
}
+ public void testInvalidExpressions() throws Exception
+ {
+ doTestEvalFail("", "empty");
+ doTestEvalFail("=", "found?");
+ doTestEvalFail("=(34 + 5", "closing");
+ doTestEvalFail("=(34 + )", "found?");
+ doTestEvalFail("=(34 + [A].[B].[C].[D])", "object reference");
+ doTestEvalFail("=34 + 5,", "delimiter");
+ doTestEvalFail("=Foo()", "find function");
+ doTestEvalFail("=(/37)", "left expression");
+ doTestEvalFail("=(>37)", "left expression");
+ doTestEvalFail("=(And 37)", "left expression");
+ doTestEvalFail("=37 In 42", "'In' expression");
+ doTestEvalFail("=37 Between 42", "'Between' expression");
+ doTestEvalFail("=(3 + 5) Rnd()", "multiple expressions");
+ // doTestEvalFail("=Blah", "");
+ }
+
+ private static void doTestEvalFail(String exprStr, String msgStr) {
+ try {
+ eval(exprStr);
+ fail("ParseException should have been thrown");
+ } catch(ParseException pe) {
+ // success
+ System.out.println("FOO " + pe);
+ assertTrue(pe.getMessage().contains(msgStr));
+ }
+ }
+
private static void validateExpr(String exprStr, String debugStr) {
validateExpr(exprStr, debugStr, exprStr);
}
@@ -479,6 +509,7 @@ public class ExpressionatorTest extends TestCase
assertEquals(debugStr, foundDebugStr);
}
assertEquals(cleanStr, expr.toString());
+ assertEquals(exprStr, expr.toRawString());
}
static Object eval(String exprStr) {