You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2017/02/07 08:56:30 UTC
cayenne git commit: CAY-2221 Apply in-memory filtering to Collections
(include CAY-1356 case)
Repository: cayenne
Updated Branches:
refs/heads/master 323771a2e -> c2d815dd0
CAY-2221 Apply in-memory filtering to Collections (include CAY-1356 case)
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/c2d815dd
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/c2d815dd
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/c2d815dd
Branch: refs/heads/master
Commit: c2d815dd0f9b894e4b2b0b676c108260dcde0475
Parents: 323771a
Author: Nikita Timofeev <st...@gmail.com>
Authored: Tue Feb 7 11:53:54 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Tue Feb 7 11:53:54 2017 +0300
----------------------------------------------------------------------
.../apache/cayenne/exp/parser/ASTBetween.java | 21 +-
.../apache/cayenne/exp/parser/ASTDbPath.java | 2 +-
.../org/apache/cayenne/exp/parser/ASTEqual.java | 35 +--
.../org/apache/cayenne/exp/parser/ASTFalse.java | 12 +-
.../apache/cayenne/exp/parser/ASTGreater.java | 16 +-
.../cayenne/exp/parser/ASTGreaterOrEqual.java | 16 +-
.../org/apache/cayenne/exp/parser/ASTIn.java | 48 +---
.../org/apache/cayenne/exp/parser/ASTLess.java | 16 +-
.../cayenne/exp/parser/ASTLessOrEqual.java | 16 +-
.../org/apache/cayenne/exp/parser/ASTLike.java | 12 +-
.../cayenne/exp/parser/ASTLikeIgnoreCase.java | 12 +-
.../org/apache/cayenne/exp/parser/ASTNot.java | 3 +-
.../cayenne/exp/parser/ASTNotBetween.java | 23 +-
.../apache/cayenne/exp/parser/ASTNotEqual.java | 15 +-
.../org/apache/cayenne/exp/parser/ASTNotIn.java | 30 +-
.../apache/cayenne/exp/parser/ASTNotLike.java | 14 +-
.../exp/parser/ASTNotLikeIgnoreCase.java | 12 +-
.../apache/cayenne/exp/parser/ASTObjPath.java | 2 +-
.../org/apache/cayenne/exp/parser/ASTTrue.java | 12 +-
.../cayenne/exp/parser/ConditionNode.java | 41 +++
.../apache/cayenne/exp/parser/SimpleNode.java | 39 +--
.../apache/cayenne/exp/ExpressionFactoryIT.java | 9 +-
.../exp/parser/ASTLikeIgnoreCaseTest.java | 36 +++
.../exp/parser/ExpressionEvaluationIT.java | 274 +++++++++++++++++++
24 files changed, 508 insertions(+), 208 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTBetween.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTBetween.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTBetween.java
index 38d2cba..0d65c84 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTBetween.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTBetween.java
@@ -48,23 +48,22 @@ public class ASTBetween extends ConditionNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 3) {
- return Boolean.FALSE;
- }
+ protected int getRequiredChildrenCount() {
+ return 3;
+ }
- Object o1 = evaluateChild(0, o);
- Object o2 = evaluateChild(1, o);
- Object o3 = evaluateChild(2, o);
- Evaluator e = Evaluator.evaluator(o1);
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ Object o1 = evaluatedChildren[1];
+ Object o2 = evaluatedChildren[2];
+ Evaluator e = Evaluator.evaluator(o);
- Integer c1 = e.compare(o1, o2);
+ Integer c1 = e.compare(o, o1);
if (c1 == null) {
return Boolean.FALSE;
}
- Integer c2 = e.compare(o1, o3);
+ Integer c2 = e.compare(o, o2);
if (c2 == null) {
return Boolean.FALSE;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
index 4e1d3c9..f3f2f7b 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTDbPath.java
@@ -103,7 +103,7 @@ public class ASTDbPath extends ASTPath {
private Map<?, ?> toMap_AttchedObject_MultiStepPath(ObjectContext context, Persistent persistent) {
Iterator<CayenneMapEntry> pathComponents = Cayenne.getObjEntity(persistent).getDbEntity()
.resolvePathComponents(this);
- LinkedList<DbRelationship> reversedPathComponents = new LinkedList<DbRelationship>();
+ LinkedList<DbRelationship> reversedPathComponents = new LinkedList<>();
while (pathComponents.hasNext()) {
CayenneMapEntry component = pathComponents.next();
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTEqual.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTEqual.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTEqual.java
index e2194d0..3f313e5 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTEqual.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTEqual.java
@@ -19,7 +19,7 @@
package org.apache.cayenne.exp.parser;
-import java.util.List;
+import java.util.Collection;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ValueInjector;
@@ -59,16 +59,14 @@ public class ASTEqual extends ConditionNode implements ValueInjector {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
-
- Object o1 = evaluateChild(0, o);
- Object o2 = evaluateChild(1, o);
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
- return evaluateImpl(o1, o2);
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ Object o2 = evaluatedChildren[1];
+ return evaluateImpl(o, o2);
}
/**
@@ -83,20 +81,9 @@ public class ASTEqual extends ConditionNode implements ValueInjector {
if (o1 == null && o2 == null) {
return true;
} else if (o1 != null) {
-
- // Per CAY-419 we perform 'in' comparison if one object is a list,
- // and other is not
-
- if (o1 instanceof List && !(o2 instanceof List)) {
- for (Object element : ((List<?>) o1)) {
- if (element != null && Evaluator.evaluator(element).eq(element, o2)) {
- return true;
- }
- }
- return false;
- }
- if (o2 instanceof List && !(o1 instanceof List)) {
- for (Object element : ((List<?>) o2)) {
+ // Per CAY-419 we perform 'in' comparison if one object is a list, and other is not
+ if (o2 instanceof Collection) {
+ for (Object element : ((Collection<?>) o2)) {
if (element != null && Evaluator.evaluator(element).eq(element, o1)) {
return true;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTFalse.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTFalse.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTFalse.java
index a117cba..22145d0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTFalse.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTFalse.java
@@ -51,14 +51,18 @@ public class ASTFalse extends ConditionNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- return Boolean.FALSE;
+ protected int getRequiredChildrenCount() {
+ return 0;
+ }
+
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ return false;
}
@Override
protected String getExpressionOperator(int index) {
- throw new UnsupportedOperationException("No operator for '" + ExpressionParserTreeConstants.jjtNodeName[id]
- + "'");
+ throw new UnsupportedOperationException("No operator for '" + ExpressionParserTreeConstants.jjtNodeName[id] + "'");
}
@Override
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTGreater.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTGreater.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTGreater.java
index c7eb1f1..25f1af9 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTGreater.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTGreater.java
@@ -47,16 +47,14 @@ public class ASTGreater extends ConditionNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
-
- Object o1 = evaluateChild(0, o);
- Object o2 = evaluateChild(1, o);
- Integer c = Evaluator.evaluator(o1).compare(o1, o2);
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ Object o2 = evaluatedChildren[1];
+ Integer c = Evaluator.evaluator(o).compare(o, o2);
return c != null && c > 0 ? Boolean.TRUE : Boolean.FALSE;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTGreaterOrEqual.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTGreaterOrEqual.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTGreaterOrEqual.java
index a970c12..fb93fa8 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTGreaterOrEqual.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTGreaterOrEqual.java
@@ -49,16 +49,14 @@ public class ASTGreaterOrEqual extends ConditionNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
-
- Object o1 = evaluateChild(0, o);
- Object o2 = evaluateChild(1, o);
- Integer c = Evaluator.evaluator(o1).compare(o1, o2);
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ Object o2 = evaluatedChildren[1];
+ Integer c = Evaluator.evaluator(o).compare(o, o2);
return c != null && c >= 0 ? Boolean.TRUE : Boolean.FALSE;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTIn.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTIn.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTIn.java
index 44ced07..31a4ac36 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTIn.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTIn.java
@@ -19,8 +19,6 @@
package org.apache.cayenne.exp.parser;
-import java.util.Collection;
-
import org.apache.cayenne.exp.Expression;
import org.apache.commons.collections.Transformer;
@@ -50,45 +48,27 @@ public class ASTIn extends ConditionNode {
connectChildren();
}
- @SuppressWarnings("rawtypes")
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
-
- Object o1 = evaluateChild(0, o);
- // TODO: what if there's a NULL inside IN list?
- // e.g. ASTEqual evals as "NULL == NULL"
- if (o1 == null) {
- return Boolean.FALSE;
- }
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
- Object[] objects = (Object[]) evaluateChild(1, o);
- if (objects == null) {
- return Boolean.FALSE;
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ // TODO: what if there's a NULL inside IN list?
+ // e.g. ASTEqual evals as "NULL == NULL"
+ if (o == null || evaluatedChildren[1] == null) {
+ return false;
}
- int size = objects.length;
- for (int i = 0; i < size; i++) {
- if (objects[i] != null) {
- if (o1 instanceof Collection) {
- // handle the case where we have a collection of objects
- for (Object obj : (Collection) o1) {
- if (Evaluator.evaluator(obj).eq(obj, objects[i])) {
- return Boolean.TRUE;
- }
- }
- } else {
- if (Evaluator.evaluator(o1).eq(o1, objects[i])) {
- return Boolean.TRUE;
- }
- }
+ Object[] objects = (Object[]) evaluatedChildren[1];
+ for (Object object : objects) {
+ if (object != null && Evaluator.evaluator(o).eq(o, object)) {
+ return true;
}
}
- return Boolean.FALSE;
+ return false;
}
/**
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLess.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLess.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLess.java
index 5880f93..d8c75cc 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLess.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLess.java
@@ -49,16 +49,14 @@ public class ASTLess extends ConditionNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
-
- Object o1 = evaluateChild(0, o);
- Object o2 = evaluateChild(1, o);
- Integer c = Evaluator.evaluator(o1).compare(o1, o2);
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ Object o2 = evaluatedChildren[1];
+ Integer c = Evaluator.evaluator(o).compare(o, o2);
return c != null && c < 0 ? Boolean.TRUE : Boolean.FALSE;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLessOrEqual.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLessOrEqual.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLessOrEqual.java
index d686797..09d10cb 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLessOrEqual.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLessOrEqual.java
@@ -49,16 +49,14 @@ public class ASTLessOrEqual extends ConditionNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
-
- Object o1 = evaluateChild(0, o);
- Object o2 = evaluateChild(1, o);
- Integer c = Evaluator.evaluator(o1).compare(o1, o2);
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ Object o2 = evaluatedChildren[1];
+ Integer c = Evaluator.evaluator(o).compare(o, o2);
return c != null && c <= 0 ? Boolean.TRUE : Boolean.FALSE;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLike.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLike.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLike.java
index 31afa92..9d1eda6 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLike.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLike.java
@@ -56,13 +56,13 @@ public class ASTLike extends PatternMatchNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
- String s1 = ConversionUtil.toString(evaluateChild(0, o));
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ String s1 = ConversionUtil.toString(o);
if (s1 == null) {
return Boolean.FALSE;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLikeIgnoreCase.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLikeIgnoreCase.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLikeIgnoreCase.java
index c8be6a0..b0bd207 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLikeIgnoreCase.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTLikeIgnoreCase.java
@@ -57,13 +57,13 @@ public class ASTLikeIgnoreCase extends IgnoreCaseNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
- String s1 = ConversionUtil.toString(evaluateChild(0, o));
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ String s1 = ConversionUtil.toString(o);
if (s1 == null) {
return Boolean.FALSE;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNot.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNot.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNot.java
index 37d14b4..0c493e4 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNot.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNot.java
@@ -91,7 +91,6 @@ public class ASTNot extends AggregateConditionNode {
@Override
protected String getExpressionOperator(int index) {
- throw new UnsupportedOperationException("No operator for '" + ExpressionParserTreeConstants.jjtNodeName[id]
- + "'");
+ throw new UnsupportedOperationException("No operator for '" + ExpressionParserTreeConstants.jjtNodeName[id] + "'");
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotBetween.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotBetween.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotBetween.java
index 000e5ee..62743e3 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotBetween.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotBetween.java
@@ -43,23 +43,22 @@ public class ASTNotBetween extends ConditionNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 3) {
- return Boolean.FALSE;
- }
+ protected int getRequiredChildrenCount() {
+ return 3;
+ }
+
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ Object o1 = evaluatedChildren[1];
+ Object o2 = evaluatedChildren[2];
+ Evaluator e = Evaluator.evaluator(o);
- Object o1 = evaluateChild(0, o);
- Object o2 = evaluateChild(1, o);
- Object o3 = evaluateChild(2, o);
- Evaluator e = Evaluator.evaluator(o1);
-
- Integer c1 = e.compare(o1, o2);
+ Integer c1 = e.compare(o, o1);
if (c1 == null) {
return Boolean.FALSE;
}
- Integer c2 = e.compare(o1, o3);
+ Integer c2 = e.compare(o, o2);
if (c2 == null) {
return Boolean.FALSE;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotEqual.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotEqual.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotEqual.java
index 1ec687b..211b83e 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotEqual.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotEqual.java
@@ -46,15 +46,14 @@ public class ASTNotEqual extends ConditionNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
- Object o1 = evaluateChild(0, o);
- Object o2 = evaluateChild(1, o);
- return !ASTEqual.evaluateImpl(o1, o2);
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ Object o2 = evaluatedChildren[1];
+ return !ASTEqual.evaluateImpl(o, o2);
}
/**
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotIn.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotIn.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotIn.java
index ea82c38..09cda00 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotIn.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotIn.java
@@ -44,30 +44,24 @@ public class ASTNotIn extends ConditionNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
-
- Object o1 = evaluateChild(0, o);
- if (o1 == null) {
- return Boolean.FALSE;
- }
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
- Object[] objects = (Object[]) evaluateChild(1, o);
- if (objects == null) {
- return Boolean.FALSE;
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ if (o == null || evaluatedChildren[1] == null) {
+ return false;
}
- int size = objects.length;
- for (int i = 0; i < size; i++) {
- if (objects[i] != null && Evaluator.evaluator(o1).eq(o1, objects[i])) {
- return Boolean.FALSE;
+ Object[] objects = (Object[]) evaluatedChildren[1];
+ for (Object object : objects) {
+ if (object != null && Evaluator.evaluator(o).eq(o, object)) {
+ return false;
}
}
- return Boolean.TRUE;
+ return true;
}
/**
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotLike.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotLike.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotLike.java
index da0fd76..ab90bc6 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotLike.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotLike.java
@@ -50,15 +50,15 @@ public class ASTNotLike extends PatternMatchNode {
jjtAddChild(new ASTScalar(value), 1);
connectChildren();
}
-
+
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
- String s1 = ConversionUtil.toString(evaluateChild(0, o));
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ String s1 = ConversionUtil.toString(o);
if (s1 == null) {
return Boolean.FALSE;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotLikeIgnoreCase.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotLikeIgnoreCase.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotLikeIgnoreCase.java
index f6f6d11..b962fc3 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotLikeIgnoreCase.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTNotLikeIgnoreCase.java
@@ -53,13 +53,13 @@ public class ASTNotLikeIgnoreCase extends IgnoreCaseNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- int len = jjtGetNumChildren();
- if (len != 2) {
- return Boolean.FALSE;
- }
+ protected int getRequiredChildrenCount() {
+ return 2;
+ }
- String s1 = ConversionUtil.toString(evaluateChild(0, o));
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ String s1 = ConversionUtil.toString(o);
if (s1 == null) {
return Boolean.FALSE;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTObjPath.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTObjPath.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTObjPath.java
index 3628098..fa75195 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTObjPath.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTObjPath.java
@@ -95,7 +95,7 @@ public class ASTObjPath extends ASTPath {
}
void injectValue(Object source, Object value) {
- if (getPath().indexOf(ObjEntity.PATH_SEPARATOR) == -1) {
+ if (!getPath().contains(ObjEntity.PATH_SEPARATOR)) {
try {
if (source instanceof DataObject) {
((DataObject) source).writeProperty(getPath(), value);
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTTrue.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTTrue.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTTrue.java
index e41cf87..ae9de66 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTTrue.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ASTTrue.java
@@ -47,14 +47,18 @@ public class ASTTrue extends ConditionNode {
}
@Override
- protected Object evaluateNode(Object o) throws Exception {
- return Boolean.TRUE;
+ protected int getRequiredChildrenCount() {
+ return 0;
+ }
+
+ @Override
+ protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception {
+ return true;
}
@Override
protected String getExpressionOperator(int index) {
- throw new UnsupportedOperationException("No operator for '" + ExpressionParserTreeConstants.jjtNodeName[id]
- + "'");
+ throw new UnsupportedOperationException("No operator for '" + ExpressionParserTreeConstants.jjtNodeName[id] + "'");
}
@Override
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ConditionNode.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ConditionNode.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ConditionNode.java
index 7b5543f..7a05940 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ConditionNode.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/ConditionNode.java
@@ -20,6 +20,9 @@
package org.apache.cayenne.exp.parser;
+import java.util.Collection;
+import java.util.Map;
+
import org.apache.cayenne.exp.ExpressionException;
/**
@@ -46,4 +49,42 @@ public abstract class ConditionNode extends SimpleNode {
super.jjtSetParent(n);
}
+
+ @Override
+ protected Object evaluateNode(Object o) throws Exception {
+ int len = jjtGetNumChildren();
+ int requiredLen = getRequiredChildrenCount();
+ if (len != requiredLen) {
+ return Boolean.FALSE;
+ }
+
+ if(requiredLen == 0) {
+ return evaluateSubNode(null, null);
+ }
+
+ Object[] evaluatedChildren = new Object[requiredLen];
+ for(int i=0; i<requiredLen; i++) {
+ evaluatedChildren[i] = evaluateChild(i, o);
+ }
+
+ Object firstChild = evaluatedChildren[0];
+ // don't care here for keys
+ if(firstChild instanceof Map) {
+ firstChild = ((Map) firstChild).values();
+ }
+ if (firstChild instanceof Collection) {
+ for(Object c : (Collection)firstChild) {
+ if(evaluateSubNode(c, evaluatedChildren)) {
+ return Boolean.TRUE;
+ }
+ }
+ return Boolean.FALSE;
+ } else {
+ return evaluateSubNode(firstChild, evaluatedChildren);
+ }
+ }
+
+ abstract protected int getRequiredChildrenCount();
+
+ abstract protected boolean evaluateSubNode(Object o, Object[] evaluatedChildren) throws Exception;
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/SimpleNode.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/SimpleNode.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/SimpleNode.java
index cbe9e16..117fd12 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/SimpleNode.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/parser/SimpleNode.java
@@ -35,11 +35,10 @@ import org.apache.cayenne.exp.ExpressionException;
import org.apache.cayenne.util.Util;
/**
- * Superclass of AST* expressions that implements Node interface defined by
- * JavaCC framework.
+ * Superclass of AST* expressions that implements Node interface defined by JavaCC framework.
* <p>
- * Some parts of the parser are based on OGNL parser, copyright (c) 2002, Drew
- * Davidson and Luke Blanshard.
+ * Some parts of the parser are based on OGNL parser,
+ * copyright (c) 2002, Drew Davidson and Luke Blanshard.
* </p>
*
* @since 1.1
@@ -84,9 +83,7 @@ public abstract class SimpleNode extends Expression implements Node {
if (null != parameterAccumulator) {
parameterAccumulator.add(scalar);
out.append('?');
- out.append(Integer.toString(parameterAccumulator.size())); // parameters
- // start
- // at 1
+ out.append(Integer.toString(parameterAccumulator.size())); // parameters start at 1
return;
}
@@ -105,7 +102,7 @@ public abstract class SimpleNode extends Expression implements Node {
if (scalar instanceof Enum<?>) {
Enum<?> e = (Enum<?>) scalar;
out.append("enum:");
- out.append(e.getClass().getName() + "." + e.name());
+ out.append(e.getClass().getName()).append(".").append(e.name());
return;
}
@@ -131,8 +128,7 @@ public abstract class SimpleNode extends Expression implements Node {
out.append(quoteChar);
}
- // encode only ObjectId for Persistent, ensure that the order of keys is
- // predictable....
+ // encode only ObjectId for Persistent, ensure that the order of keys is predictable....
// TODO: should we use UUID here?
if (scalar instanceof Persistent) {
@@ -142,7 +138,7 @@ public abstract class SimpleNode extends Expression implements Node {
} else if (scalar instanceof Enum<?>) {
Enum<?> e = (Enum<?>) scalar;
out.append("enum:");
- out.append(e.getClass().getName() + "." + e.name());
+ out.append(e.getClass().getName()).append(".").append(e.name());
} else {
appendAsEscapedString(out, String.valueOf(scalar));
}
@@ -153,8 +149,7 @@ public abstract class SimpleNode extends Expression implements Node {
}
/**
- * Utility method that prints a string to the provided Appendable, escaping
- * special characters.
+ * Utility method that prints a string to the provided Appendable, escaping special characters.
*/
protected static void appendAsEscapedString(Appendable out, String source) throws IOException {
int len = source.length();
@@ -209,8 +204,7 @@ public abstract class SimpleNode extends Expression implements Node {
protected abstract String getExpressionOperator(int index);
/**
- * Returns operator for ebjql statements, which can differ for Cayenne
- * expression operator
+ * Returns operator for EJBQL statements, which can differ for Cayenne expression operator
*/
protected String getEJBQLExpressionOperator(int index) {
return getExpressionOperator(index);
@@ -317,10 +311,8 @@ public abstract class SimpleNode extends Expression implements Node {
public Object getOperand(int index) {
Node child = jjtGetChild(index);
- // unwrap ASTScalar nodes - this is likely a temporary thing to keep it
- // compatible
- // with QualifierTranslator. In the future we might want to keep scalar
- // nodes
+ // unwrap ASTScalar nodes - this is likely a temporary thing to keep it compatible
+ // with QualifierTranslator. In the future we might want to keep scalar nodes
// for the purpose of expression evaluation.
return unwrapChild(child);
}
@@ -399,9 +391,8 @@ public abstract class SimpleNode extends Expression implements Node {
protected void connectChildren() {
if (children != null) {
for (Node child : children) {
- // although nulls are expected to be wrapped in scalar, still
- // doing a
- // check here to make it more robust
+ // although nulls are expected to be wrapped in scalar,
+ // still doing a check here to make it more robust
if (child != null) {
child.jjtSetParent(this);
}
@@ -426,8 +417,8 @@ public abstract class SimpleNode extends Expression implements Node {
return evaluateNode(o);
} catch (Throwable th) {
String string = this.toString();
- throw new ExpressionException("Error evaluating expression '" + string + "'", string,
- Util.unwindException(th));
+ throw new ExpressionException("Error evaluating expression '%s'",
+ string, Util.unwindException(th), string);
}
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionFactoryIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionFactoryIT.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionFactoryIT.java
index 7fb78a9..c1b2ae2 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionFactoryIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/ExpressionFactoryIT.java
@@ -56,8 +56,9 @@ public class ExpressionFactoryIT extends ServerCase {
public void testCollectionMatch() {
Artist artist = context.newObject(Artist.class);
artist.setArtistName("artist");
- Painting p1 = context.newObject(Painting.class), p2 = context.newObject(Painting.class), p3 = context
- .newObject(Painting.class);
+ Painting p1 = context.newObject(Painting.class),
+ p2 = context.newObject(Painting.class),
+ p3 = context.newObject(Painting.class);
p1.setPaintingTitle("p1");
p2.setPaintingTitle("p2");
p3.setPaintingTitle("p3");
@@ -68,12 +69,12 @@ public class ExpressionFactoryIT extends ServerCase {
assertTrue(ExpressionFactory.matchExp("paintingArray", p1).match(artist));
assertFalse(ExpressionFactory.matchExp("paintingArray", p3).match(artist));
- assertFalse(ExpressionFactory.noMatchExp("paintingArray", p1).match(artist));
+ assertTrue(ExpressionFactory.noMatchExp("paintingArray", p1).match(artist)); // changed to align with SQL
assertTrue(ExpressionFactory.noMatchExp("paintingArray", p3).match(artist));
assertTrue(ExpressionFactory.matchExp("paintingArray.paintingTitle", "p1").match(artist));
assertFalse(ExpressionFactory.matchExp("paintingArray.paintingTitle", "p3").match(artist));
- assertFalse(ExpressionFactory.noMatchExp("paintingArray.paintingTitle", "p1").match(artist));
+ assertTrue(ExpressionFactory.noMatchExp("paintingArray.paintingTitle", "p1").match(artist)); // changed to align with SQL
assertTrue(ExpressionFactory.noMatchExp("paintingArray.paintingTitle", "p3").match(artist));
assertTrue(ExpressionFactory.inExp("paintingTitle", "p1").match(p1));
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTLikeIgnoreCaseTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTLikeIgnoreCaseTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTLikeIgnoreCaseTest.java
index 9453a2f..55946cf 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTLikeIgnoreCaseTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ASTLikeIgnoreCaseTest.java
@@ -18,12 +18,15 @@
****************************************************************/
package org.apache.cayenne.exp.parser;
+import java.util.Arrays;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Painting;
import org.junit.Test;
public class ASTLikeIgnoreCaseTest {
@@ -54,4 +57,37 @@ public class ASTLikeIgnoreCaseTest {
assertTrue("Failed: " + like, like.match(match2));
assertFalse("Failed: " + notLike, notLike.match(match2));
}
+
+ @Test
+ public void testEvaluateWithCollection() {
+ Expression like = new ASTLikeIgnoreCase(new ASTObjPath("paintingArray.paintingTitle"), "aBcD");
+ Expression notLike = new ASTNotLikeIgnoreCase(new ASTObjPath("paintingArray.paintingTitle"), "aBcD");
+
+ Artist noMatch1 = new Artist();
+ noMatch1.writePropertyDirectly("paintingArray",
+ Arrays.asList(createPainting("xyz"), createPainting("abc")));
+
+ assertFalse("Failed: " + like, like.match(noMatch1));
+ assertTrue("Failed: " + like, notLike.match(noMatch1));
+
+ Artist match1 = new Artist();
+ match1.writePropertyDirectly("paintingArray",
+ Arrays.asList(createPainting("AbCd"), createPainting("abcd")));
+
+ assertTrue("Failed: " + like, like.match(match1));
+ assertFalse("Failed: " + like, notLike.match(match1));
+
+ Artist match2 = new Artist();
+ match2.writePropertyDirectly("paintingArray",
+ Arrays.asList(createPainting("Xzy"), createPainting("abcd")));
+
+ assertTrue("Failed: " + like, like.match(match2));
+ assertTrue("Failed: " + like, notLike.match(match2));
+ }
+
+ private Painting createPainting(String name) {
+ Painting p = new Painting();
+ p.setPaintingTitle(name);
+ return p;
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2d815dd/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ExpressionEvaluationIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ExpressionEvaluationIT.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ExpressionEvaluationIT.java
new file mode 100644
index 0000000..e33dba3
--- /dev/null
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/parser/ExpressionEvaluationIT.java
@@ -0,0 +1,274 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.exp.parser;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.apache.cayenne.access.DataContext;
+import org.apache.cayenne.di.Inject;
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.Ordering;
+import org.apache.cayenne.test.jdbc.DBHelper;
+import org.apache.cayenne.test.jdbc.TableHelper;
+import org.apache.cayenne.testdo.testmap.Artist;
+import org.apache.cayenne.testdo.testmap.Painting;
+import org.apache.cayenne.unit.di.server.CayenneProjects;
+import org.apache.cayenne.unit.di.server.ServerCase;
+import org.apache.cayenne.unit.di.server.UseServerRuntime;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+/**
+ * Here we compare Expression evaluation in-memory vs execution in database.
+ * Results should be same for both cases.
+ * Here is primary collection of complex expressions:
+ * - To-Many relationships
+ * - Nulls
+ *
+ * @since 4.0
+ */
+@UseServerRuntime(CayenneProjects.TESTMAP_PROJECT)
+public class ExpressionEvaluationIT extends ServerCase {
+
+ @Inject
+ private DataContext context;
+
+ @Inject
+ private DBHelper dbHelper;
+
+ private TableHelper tArtist, tGallery, tPaintings;
+
+ @Before
+ public void createArtistsDataSet() throws Exception {
+ tArtist = new TableHelper(dbHelper, "ARTIST");
+ tArtist.setColumns("ARTIST_ID", "ARTIST_NAME", "DATE_OF_BIRTH");
+
+ long dateBase = System.currentTimeMillis();
+ for (int i = 1; i <= 6; i++) {
+ tArtist.insert(i, "artist" + i, new java.sql.Date(dateBase + 10000 * i));
+ }
+
+ tGallery = new TableHelper(dbHelper, "GALLERY");
+ tGallery.setColumns("GALLERY_ID", "GALLERY_NAME");
+ tGallery.insert(1, "tate modern");
+
+ tPaintings = new TableHelper(dbHelper, "PAINTING");
+ tPaintings.setColumns("PAINTING_ID", "PAINTING_TITLE", "ARTIST_ID", "GALLERY_ID", "ESTIMATED_PRICE");
+ for (int i = 1; i <= 10; i++) {
+ tPaintings.insert(i, "painting" + i, i % 5 + 1, 1, i * 100);
+ }
+
+ tPaintings.insert(11, "painting11", null, 1, 10000);
+ }
+
+ @Test
+ public void testSimpleLike() {
+ Expression exp = Artist.ARTIST_NAME
+ .like("artist%");
+
+ compareSqlAndEval(exp, 6);
+ }
+
+ @Test
+ public void testSimpleNotLike() {
+ Expression exp = Artist.ARTIST_NAME
+ .nlike("artist%");
+
+ compareSqlAndEval(exp, 0);
+ }
+
+ @Test
+ public void testSimpleEqual() {
+ Expression exp = Artist.ARTIST_NAME
+ .eq("artist2");
+
+ compareSqlAndEval(exp, 1);
+ }
+
+ @Test
+ public void testSimpleNotEqual() {
+ Expression exp = Artist.ARTIST_NAME
+ .ne("artist2");
+
+ compareSqlAndEval(exp, 5);
+ }
+
+ @Test
+ public void testLikeIgnoreCase() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE)
+ .likeIgnoreCase("painting%");
+
+ compareSqlAndEval(exp, 5);
+ }
+
+ @Test
+ public void testNotLikeIgnoreCase() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE)
+ .likeIgnoreCase("PaInTing%");
+
+ compareSqlAndEval(exp, 5);
+ }
+
+ @Test
+ public void testLike() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE)
+ .like("painting%");
+
+ compareSqlAndEval(exp, 5);
+ }
+
+ @Test
+ public void testNotLike() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE)
+ .like("painting%");
+
+ compareSqlAndEval(exp, 5);
+ }
+
+ @Test
+ public void testEqual() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE)
+ .eq("painting1");
+
+ compareSqlAndEval(exp, 1);
+ }
+
+ @Test
+ public void testNotEqual1() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE)
+ .ne("painting1");
+
+ compareSqlAndEval(exp, 5);
+ }
+
+ @Test
+ public void testNotEqual2() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE)
+ .ne("painting11");
+
+ compareSqlAndEval(exp, 5);
+ }
+
+ @Test
+ public void testNotEqual3() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.PAINTING_TITLE)
+ .ne("zyz");
+
+ compareSqlAndEval(exp, 5);
+ }
+
+ @Test
+ public void testBetween() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.ESTIMATED_PRICE)
+ .between(new BigDecimal(300), new BigDecimal(600));
+
+ compareSqlAndEval(exp, 4);
+ }
+
+ @Test
+ public void testNotBetween() {
+ Expression exp = ExpressionFactory.notBetweenExp(
+ "paintingArray.estimatedPrice",
+ new BigDecimal(300), new BigDecimal(600));
+
+ compareSqlAndEval(exp, 5);
+ }
+
+ @Test
+ public void testGreater() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.ESTIMATED_PRICE)
+ .gt(new BigDecimal(799));
+
+ compareSqlAndEval(exp, 3);
+ }
+
+ @Test
+ public void testGreaterEqual() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.ESTIMATED_PRICE)
+ .gte(new BigDecimal(800));
+
+ compareSqlAndEval(exp, 3);
+ }
+
+ @Test
+ public void testIn() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.ESTIMATED_PRICE)
+ .in(new BigDecimal(800), new BigDecimal(300), new BigDecimal(700));
+
+ compareSqlAndEval(exp, 2);
+ }
+
+ @Test
+ public void testNotIn() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.ESTIMATED_PRICE)
+ .nin(new BigDecimal(800), new BigDecimal(200), new BigDecimal(300), new BigDecimal(400), new BigDecimal(700));
+
+ compareSqlAndEval(exp, 3);
+ }
+
+ @Test
+ public void testLess() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.ESTIMATED_PRICE)
+ .lt(new BigDecimal(801));
+
+ compareSqlAndEval(exp, 5);
+ }
+
+ @Test
+ public void testLessOrEqual() {
+ Expression exp = Artist.PAINTING_ARRAY.dot(Painting.ESTIMATED_PRICE)
+ .lte(new BigDecimal(800));
+
+ compareSqlAndEval(exp, 5);
+ }
+
+ @Test
+ @Ignore("Null comparisons are partially broken for now")
+ public void testNull() throws Exception {
+ tArtist.deleteAll();
+ tArtist.insert(7, "artist7", null);
+
+ Expression expression = Artist.DATE_OF_BIRTH.gt(new java.sql.Date(System.currentTimeMillis()));
+ compareSqlAndEval(expression, 0);
+
+ Expression expression1 = expression.notExp();
+ compareSqlAndEval(expression1, 0); // this one will fail, in-memory filter will match one Artist
+ }
+
+ private void compareSqlAndEval(Expression exp, int expectedCount) {
+ // apply exp in SQL
+ Ordering ordering = new Ordering("db:ARTIST_ID");
+ List<Artist> filteredInSQL = ObjectSelect.query(Artist.class, exp).orderBy(ordering).select(context);
+ // apply exp to in-memory collection
+ List<Artist> filteredInMemory = exp.filterObjects(
+ ObjectSelect.query(Artist.class).prefetch(Artist.PAINTING_ARRAY.disjoint()).select(context)
+ );
+ ordering.orderList(filteredInMemory);
+
+ assertEquals(expectedCount, filteredInMemory.size());
+ assertEquals(filteredInSQL, filteredInMemory);
+ }
+}