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/01/26 08:15:07 UTC
cayenne git commit: CAY-2211 shortcuts for SQL functions in Property
class
Repository: cayenne
Updated Branches:
refs/heads/master 3f8a8f196 -> 44bad6412
CAY-2211 shortcuts for SQL functions in Property class
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/44bad641
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/44bad641
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/44bad641
Branch: refs/heads/master
Commit: 44bad641295010807ecd47e6fe5cb7d904f8177a
Parents: 3f8a8f1
Author: Nikita Timofeev <st...@gmail.com>
Authored: Thu Jan 26 11:13:38 2017 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Thu Jan 26 11:13:38 2017 +0300
----------------------------------------------------------------------
.../apache/cayenne/exp/ExpressionFactory.java | 9 +
.../cayenne/exp/FunctionExpressionFactory.java | 42 ++-
.../java/org/apache/cayenne/exp/Property.java | 168 ++++++++++-
.../org/apache/cayenne/exp/PropertyTest.java | 279 ++++++++++++++++---
.../apache/cayenne/query/ColumnSelectIT.java | 18 +-
5 files changed, 450 insertions(+), 66 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44bad641/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
index 8d132a9..e9fa6b0 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/ExpressionFactory.java
@@ -52,6 +52,7 @@ import org.apache.cayenne.exp.parser.ASTNotLikeIgnoreCase;
import org.apache.cayenne.exp.parser.ASTObjPath;
import org.apache.cayenne.exp.parser.ASTOr;
import org.apache.cayenne.exp.parser.ASTPath;
+import org.apache.cayenne.exp.parser.ASTScalar;
import org.apache.cayenne.exp.parser.ASTSubtract;
import org.apache.cayenne.exp.parser.ASTTrue;
import org.apache.cayenne.exp.parser.ExpressionParser;
@@ -1295,6 +1296,14 @@ public class ExpressionFactory {
}
/**
+ * Wrap value into ASTScalar
+ * @since 4.0
+ */
+ static Expression wrapScalarValue(Object value) {
+ return new ASTScalar(value);
+ }
+
+ /**
* Parses string, converting it to Expression. If string does not represent
* a semantically correct expression, an ExpressionException is thrown.
*
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44bad641/cayenne-server/src/main/java/org/apache/cayenne/exp/FunctionExpressionFactory.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/FunctionExpressionFactory.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/FunctionExpressionFactory.java
index 89a8893..e4cbf07 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/FunctionExpressionFactory.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/FunctionExpressionFactory.java
@@ -243,17 +243,24 @@ public class FunctionExpressionFactory {
}
/**
+ * <p>
* Factory method for expression to call CONCAT(string1, string2, ...) function
- * Can be used like:
+ * </p>
+ * <p>
+ * Can be used like: <pre>
* Expression concat = concatExp(SomeClass.POPERTY_1.getPath(), SomeClass.PROPERTY_2.getPath());
- *
+ * </pre>
+ * </p>
+ * <p>
* SQL generation note:
- * - if DB supports CONCAT function with vararg then it will be used
- * - if DB supports CONCAT function with two args but also supports concat operator, then operator (eg ||) will be used
- * - if DB supports only CONCAT function with two args then it will be used what can lead to SQL exception if
+ * <ul>
+ * <li> if DB supports CONCAT function with vararg then it will be used
+ * <li> if DB supports CONCAT function with two args but also supports concat operator, then operator (eg ||) will be used
+ * <li> if DB supports only CONCAT function with two args then it will be used what can lead to SQL exception if
* used with more than two arguments
- *
- * Currently only known DB with limited concatenation functionality is Openbase.
+ * </ul>
+ * </p>
+ * <p>Currently only known DB with limited concatenation functionality is Openbase.</p>
*
* @param expressions array of expressions
* @return CONCAT() call expression
@@ -267,17 +274,24 @@ public class FunctionExpressionFactory {
}
/**
+ * <p>
* Factory method for expression to call CONCAT(string1, string2, ...) function
- * Can be used like:
+ * </p>
+ * <p>
+ * Can be used like:<pre>
* Expression concat = concatExp("property1", "property2");
- *
+ * </pre>
+ * </p>
+ * <p>
* SQL generation note:
- * - if DB supports CONCAT function with vararg then it will be used
- * - if DB supports CONCAT function with two args but also supports concat operator, then operator (eg ||) will be used
- * - if DB supports only CONCAT function with two args then it will be used what can lead to SQL exception if
+ * <ul>
+ * <li> if DB supports CONCAT function with vararg then it will be used
+ * <li> if DB supports CONCAT function with two args but also supports concat operator, then operator (eg ||) will be used
+ * <li> if DB supports only CONCAT function with two args then it will be used what can lead to SQL exception if
* used with more than two arguments
- *
- * Currently only known DB with limited concatenation functionality is Openbase.
+ * </ul>
+ * </p>
+ * <p>Currently only Openbase DB has limited concatenation functionality.</p>
*
* @param paths array of paths
* @return CONCAT() call expression
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44bad641/cayenne-server/src/main/java/org/apache/cayenne/exp/Property.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/exp/Property.java b/cayenne-server/src/main/java/org/apache/cayenne/exp/Property.java
index f1bb1ce..59eb17d 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/exp/Property.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/exp/Property.java
@@ -30,14 +30,16 @@ import java.util.List;
/**
* <p>
- * A property in a DataObject.
+ * A property in a {@link org.apache.cayenne.DataObject}.
* </p>
* <p>
- * Used to construct Expressions quickly and with type-safety, and to construct Orderings
+ * Used to construct Expressions quickly and with type-safety, and to construct Orderings.
* </p>
* <p>
- * Instances of this class are immutable
- * Construct via factory methods Property.create(..)
+ * Instances of this class are immutable.
+ * </p>
+ * <p>
+ * Must be created via factory methods {@link Property#create(String, Class) Property.create(..)}
* </p>
*
* @param <E> The type this property returns.
@@ -50,6 +52,17 @@ import java.util.List;
*/
public class Property<E> {
+ /**
+ * <p>Property that can be used in COUNT(*) queries</p>
+ * <p>
+ * <pre>{@code
+ * List<Object[]> result = ObjectSelect
+ * .columnQuery(Artist.class, Property.COUNT, Artist.ARTIST_NAME)
+ * .having(Property.COUNT.gt(1L))
+ * .select(context);
+ * }</pre>
+ * </p>
+ */
public static final Property<Long> COUNT = Property.create(FunctionExpressionFactory.countExp(), Long.class);
/**
@@ -59,13 +72,11 @@ public class Property<E> {
/**
* Expression provider for the property
- * @since 4.0
*/
private final ExpressionProvider expressionProvider;
/**
* Explicit type of the property
- * @since 4.0
*/
private final Class<? super E> type;
@@ -106,7 +117,6 @@ public class Property<E> {
* @param name of the property (will be used as alias for the expression)
* @param expression expression for property
* @param type of the property
- * @since 4.0
*
* @see Property#create(String, Expression, Class)
*/
@@ -129,7 +139,6 @@ public class Property<E> {
}
/**
- * @since 4.0
* @return alias for this property
*/
public String getAlias() {
@@ -149,7 +158,7 @@ public class Property<E> {
}
/**
- * @since 4.0
+ * @return expression that represents this Property
*/
public Expression getExpression() {
return expressionProvider.get();
@@ -635,26 +644,146 @@ public class Property<E> {
}
}
+ /**
+ * @see FunctionExpressionFactory#countExp(Expression)
+ */
public Property<Long> count() {
return create(FunctionExpressionFactory.countExp(getExpression()), Long.class);
}
+ /**
+ * @see FunctionExpressionFactory#maxExp(Expression)
+ */
public Property<E> max() {
return create(FunctionExpressionFactory.maxExp(getExpression()), getType());
}
+ /**
+ * @see FunctionExpressionFactory#minExp(Expression)
+ */
public Property<E> min() {
return create(FunctionExpressionFactory.minExp(getExpression()), getType());
}
+ /**
+ * @see FunctionExpressionFactory#avgExp(Expression)
+ */
public Property<E> avg() {
return create(FunctionExpressionFactory.avgExp(getExpression()), getType());
}
+ /**
+ * @see FunctionExpressionFactory#sumExp(Expression)
+ */
public Property<E> sum() {
return create(FunctionExpressionFactory.sumExp(getExpression()), getType());
}
+ /**
+ * @see FunctionExpressionFactory#modExp(Expression, Number)
+ */
+ public Property<E> mod(Number number) {
+ return create(FunctionExpressionFactory.modExp(getExpression(), number), getType());
+ }
+
+ /**
+ * @see FunctionExpressionFactory#absExp(Expression)
+ */
+ public Property<E> abs() {
+ return create(FunctionExpressionFactory.absExp(getExpression()), getType());
+ }
+
+ /**
+ * @see FunctionExpressionFactory#sqrtExp(Expression)
+ */
+ public Property<E> sqrt() {
+ return create(FunctionExpressionFactory.sqrtExp(getExpression()), getType());
+ }
+
+ /**
+ * @see FunctionExpressionFactory#lengthExp(Expression)
+ */
+ public Property<Integer> length() {
+ return create(FunctionExpressionFactory.lengthExp(getExpression()), Integer.class);
+ }
+
+ /**
+ * @see FunctionExpressionFactory#locateExp(String, Expression)
+ */
+ public Property<Integer> locate(String string) {
+ return create(FunctionExpressionFactory.locateExp(ExpressionFactory.wrapScalarValue(string), getExpression()), Integer.class);
+ }
+
+ /**
+ * @see FunctionExpressionFactory#locateExp(Expression, Expression)
+ */
+ public Property<Integer> locate(Property<? extends String> property) {
+ return create(FunctionExpressionFactory.locateExp(property.getExpression(), getExpression()), Integer.class);
+ }
+
+ /**
+ * @see FunctionExpressionFactory#trimExp(Expression)
+ */
+ public Property<String> trim() {
+ return create(FunctionExpressionFactory.trimExp(getExpression()), String.class);
+ }
+
+ /**
+ * @see FunctionExpressionFactory#upperExp(Expression)
+ */
+ public Property<String> upper() {
+ return create(FunctionExpressionFactory.upperExp(getExpression()), String.class);
+ }
+
+ /**
+ * @see FunctionExpressionFactory#lowerExp(Expression)
+ */
+ public Property<String> lower() {
+ return create(FunctionExpressionFactory.lowerExp(getExpression()), String.class);
+ }
+
+ /**
+ * <p>Arguments will be converted as follows:
+ * <ul>
+ * <li>if argument is a {@link Property} than its expression will be used</li>
+ * <li>if argument is a {@link Expression} than it will be used as is </li>
+ * <li>all other values will be converted to String</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Usage:
+ * <pre>{@code
+ * Property<String> fullName = Artist.FIRST_NAME.concat(" ", Artist.SECOND_NAME);
+ * }</pre>
+ * </p>
+ * @see FunctionExpressionFactory#concatExp(Expression...)
+ */
+ public Property<String> concat(Object... args) {
+ Expression[] exp = new Expression[args.length + 1];
+ int i = 0;
+ exp[i++] = getExpression();
+ for(Object arg : args) {
+ if(arg instanceof Property) {
+ exp[i++] = ((Property) arg).getExpression();
+ } else if(arg instanceof Expression) {
+ exp[i++] = (Expression) arg;
+ } else if(arg != null) {
+ exp[i++] = ExpressionFactory.wrapScalarValue(arg.toString());
+ }
+ }
+ return create(FunctionExpressionFactory.concatExp(exp), String.class);
+ }
+
+ /**
+ * @see FunctionExpressionFactory#substringExp(Expression, int, int)
+ */
+ public Property<String> substring(int offset, int length) {
+ return create(FunctionExpressionFactory.substringExp(getExpression(), offset, length), String.class);
+ }
+
+ /**
+ * Creates alias with different name for this property
+ */
public Property<E> alias(String alias) {
return new Property<>(alias, this.getExpression(), this.getType());
}
@@ -663,18 +792,39 @@ public class Property<E> {
return type;
}
+ /**
+ * Creates property with name and type
+ * @see Property#create(Expression, Class)
+ * @see Property#create(String, Expression, Class)
+ */
public static <T> Property<T> create(String name, Class<? super T> type) {
return new Property<>(name, type);
}
+ /**
+ * Creates property with expression and type
+ * @see Property#create(String, Class)
+ * @see Property#create(String, Expression, Class)
+ */
public static <T> Property<T> create(Expression expression, Class<? super T> type) {
return new Property<>(null, expression, type);
}
+ /**
+ * Creates property with name, expression and type
+ * @see Property#create(String, Class)
+ * @see Property#create(Expression, Class)
+ */
public static <T> Property<T> create(String name, Expression expression, Class<? super T> type) {
return new Property<>(name, expression, type);
}
+ /**
+ * Since Expression is mutable we need to provide clean Expression for every getter call.
+ * So to keep Property itself immutable we use ExpressionProvider.
+ * @see Property#Property(String, Class)
+ * @see Property#Property(String, Expression, Class)
+ */
private interface ExpressionProvider {
Expression get();
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44bad641/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java b/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
index a489d37..83b5868 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/exp/PropertyTest.java
@@ -26,7 +26,23 @@ import static org.junit.Assert.assertTrue;
import java.util.Arrays;
import java.util.List;
+import org.apache.cayenne.exp.parser.ASTAbs;
+import org.apache.cayenne.exp.parser.ASTAvg;
+import org.apache.cayenne.exp.parser.ASTConcat;
+import org.apache.cayenne.exp.parser.ASTCount;
+import org.apache.cayenne.exp.parser.ASTLength;
+import org.apache.cayenne.exp.parser.ASTLocate;
+import org.apache.cayenne.exp.parser.ASTLower;
+import org.apache.cayenne.exp.parser.ASTMax;
+import org.apache.cayenne.exp.parser.ASTMin;
+import org.apache.cayenne.exp.parser.ASTMod;
import org.apache.cayenne.exp.parser.ASTObjPath;
+import org.apache.cayenne.exp.parser.ASTScalar;
+import org.apache.cayenne.exp.parser.ASTSqrt;
+import org.apache.cayenne.exp.parser.ASTSubstring;
+import org.apache.cayenne.exp.parser.ASTSum;
+import org.apache.cayenne.exp.parser.ASTTrim;
+import org.apache.cayenne.exp.parser.ASTUpper;
import org.apache.cayenne.exp.parser.PatternMatchNode;
import org.apache.cayenne.reflect.TstJavaBean;
import org.junit.Test;
@@ -35,14 +51,14 @@ public class PropertyTest {
@Test
public void testPath() {
- Property<String> p = new Property<>("x.y");
+ Property<String> p = Property.create("x.y", String.class);
Expression pp = p.path();
assertEquals(ExpressionFactory.exp("x.y"), pp);
}
@Test
public void testIn() {
- Property<String> p = new Property<>("x.y");
+ Property<String> p = Property.create("x.y", String.class);
Expression e1 = p.in("a");
assertEquals("x.y in (\"a\")", e1.toString());
@@ -58,7 +74,7 @@ public class PropertyTest {
public void testGetFrom() {
TstJavaBean bean = new TstJavaBean();
bean.setIntField(7);
- Property<Integer> INT_FIELD = new Property<>("intField");
+ Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
assertEquals(Integer.valueOf(7), INT_FIELD.getFrom(bean));
}
@@ -68,7 +84,7 @@ public class PropertyTest {
TstJavaBean nestedBean = new TstJavaBean();
nestedBean.setIntField(7);
bean.setObjectField(nestedBean);
- Property<Integer> OBJECT_FIELD_INT_FIELD = new Property<>("objectField.intField");
+ Property<Integer> OBJECT_FIELD_INT_FIELD = Property.create("objectField.intField", Integer.class);
assertEquals(Integer.valueOf(7), OBJECT_FIELD_INT_FIELD.getFrom(bean));
}
@@ -76,7 +92,7 @@ public class PropertyTest {
public void testGetFromNestedNull() {
TstJavaBean bean = new TstJavaBean();
bean.setObjectField(null);
- Property<Integer> OBJECT_FIELD_INT_FIELD = new Property<>("objectField.intField");
+ Property<Integer> OBJECT_FIELD_INT_FIELD = Property.create("objectField.intField", Integer.class);
assertNull(OBJECT_FIELD_INT_FIELD.getFrom(bean));
}
@@ -90,14 +106,14 @@ public class PropertyTest {
List<TstJavaBean> beans = Arrays.asList(bean, bean2);
- Property<Integer> INT_FIELD = new Property<>("intField");
+ Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
assertEquals(Arrays.asList(7, 8), INT_FIELD.getFromAll(beans));
}
@Test
public void testSetIn() {
TstJavaBean bean = new TstJavaBean();
- Property<Integer> INT_FIELD = new Property<>("intField");
+ Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
INT_FIELD.setIn(bean, 7);
assertEquals(7, bean.getIntField());
}
@@ -107,7 +123,7 @@ public class PropertyTest {
TstJavaBean bean = new TstJavaBean();
bean.setObjectField(new TstJavaBean());
- Property<Integer> OBJECT_FIELD_INT_FIELD = new Property<>("objectField.intField");
+ Property<Integer> OBJECT_FIELD_INT_FIELD = Property.create("objectField.intField", Integer.class);
OBJECT_FIELD_INT_FIELD.setIn(bean, 7);
assertEquals(7, ((TstJavaBean) bean.getObjectField()).getIntField());
@@ -117,7 +133,7 @@ public class PropertyTest {
public void testSetInNestedNull() {
TstJavaBean bean = new TstJavaBean();
bean.setObjectField(null);
- Property<Integer> OBJECT_FIELD_INT_FIELD = new Property<>("objectField.intField");
+ Property<Integer> OBJECT_FIELD_INT_FIELD = Property.create("objectField.intField", Integer.class);
OBJECT_FIELD_INT_FIELD.setIn(bean, 7);
}
@@ -127,7 +143,7 @@ public class PropertyTest {
TstJavaBean bean2 = new TstJavaBean();
List<TstJavaBean> beans = Arrays.asList(bean, bean2);
- Property<Integer> INT_FIELD = new Property<>("intField");
+ Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
INT_FIELD.setInAll(beans, 7);
assertEquals(7, bean.getIntField());
assertEquals(7, bean2.getIntField());
@@ -135,8 +151,8 @@ public class PropertyTest {
@Test
public void testEqualsWithName() {
- Property<Integer> INT_FIELD = new Property<>("intField");
- Property<Integer> INT_FIELD2 = new Property<>("intField");
+ Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
+ Property<Integer> INT_FIELD2 = Property.create("intField", Integer.class);
assertTrue(INT_FIELD != INT_FIELD2);
assertTrue(INT_FIELD.equals(INT_FIELD2));
@@ -144,9 +160,9 @@ public class PropertyTest {
@Test
public void testHashCodeWithName() {
- Property<Integer> INT_FIELD = new Property<>("intField");
- Property<Integer> INT_FIELD2 = new Property<>("intField");
- Property<Long> LONG_FIELD = new Property<>("longField");
+ Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
+ Property<Integer> INT_FIELD2 = Property.create("intField", Integer.class);
+ Property<Long> LONG_FIELD = Property.create("longField", Long.class);
assertTrue(INT_FIELD.hashCode() == INT_FIELD2.hashCode());
assertTrue(INT_FIELD.hashCode() != LONG_FIELD.hashCode());
@@ -154,8 +170,8 @@ public class PropertyTest {
@Test
public void testEqualsWithNameAndType() {
- Property<Integer> INT_FIELD = new Property<>("intField", Integer.class);
- Property<Integer> INT_FIELD2 = new Property<>("intField", Integer.class);
+ Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
+ Property<Integer> INT_FIELD2 = Property.create("intField", Integer.class);
assertTrue(INT_FIELD != INT_FIELD2);
assertTrue(INT_FIELD.equals(INT_FIELD2));
@@ -163,9 +179,9 @@ public class PropertyTest {
@Test
public void testHashCodeWithNameAndType() {
- Property<Integer> INT_FIELD = new Property<>("intField", Integer.class);
- Property<Integer> INT_FIELD2 = new Property<>("intField", Integer.class);
- Property<Long> LONG_FIELD = new Property<>("longField", Long.class);
+ Property<Integer> INT_FIELD = Property.create("intField", Integer.class);
+ Property<Integer> INT_FIELD2 = Property.create("intField", Integer.class);
+ Property<Long> LONG_FIELD = Property.create("longField", Long.class);
assertTrue(INT_FIELD.hashCode() == INT_FIELD2.hashCode());
assertTrue(INT_FIELD.hashCode() != LONG_FIELD.hashCode());
@@ -192,33 +208,33 @@ public class PropertyTest {
@Test
public void testOuter() {
- Property<String> inner = new Property<>("xyz");
+ Property<String> inner = Property.create("xyz", String.class);
assertEquals("xyz+", inner.outer().getName());
- Property<String> inner1 = new Property<>("xyz.xxx");
+ Property<String> inner1 = Property.create("xyz.xxx", String.class);
assertEquals("xyz.xxx+", inner1.outer().getName());
- Property<String> outer = new Property<>("xyz+");
+ Property<String> outer = Property.create("xyz+", String.class);
assertEquals("xyz+", outer.outer().getName());
}
@Test
public void testLike() {
- Property<String> p = new Property<>("prop");
+ Property<String> p = Property.create("prop", String.class);
Expression e = p.like("abc");
assertEquals("prop like \"abc\"", e.toString());
}
@Test
public void testLikeIgnoreCase() {
- Property<String> p = new Property<>("prop");
+ Property<String> p = Property.create("prop", String.class);
Expression e = p.likeIgnoreCase("abc");
assertEquals("prop likeIgnoreCase \"abc\"", e.toString());
}
@Test
public void testLike_NoEscape() {
- Property<String> p = new Property<>("prop");
+ Property<String> p = Property.create("prop", String.class);
Expression e = p.like("ab%c");
assertEquals("prop like \"ab%c\"", e.toString());
assertEquals(0, ((PatternMatchNode) e).getEscapeChar());
@@ -226,7 +242,7 @@ public class PropertyTest {
@Test
public void testContains() {
- Property<String> p = new Property<>("prop");
+ Property<String> p = Property.create("prop", String.class);
Expression e = p.contains("abc");
assertEquals("prop like \"%abc%\"", e.toString());
assertEquals(0, ((PatternMatchNode) e).getEscapeChar());
@@ -234,7 +250,7 @@ public class PropertyTest {
@Test
public void testStartsWith() {
- Property<String> p = new Property<>("prop");
+ Property<String> p = Property.create("prop", String.class);
Expression e = p.startsWith("abc");
assertEquals("prop like \"abc%\"", e.toString());
assertEquals(0, ((PatternMatchNode) e).getEscapeChar());
@@ -242,7 +258,7 @@ public class PropertyTest {
@Test
public void testEndsWith() {
- Property<String> p = new Property<>("prop");
+ Property<String> p = Property.create("prop", String.class);
Expression e = p.endsWith("abc");
assertEquals("prop like \"%abc\"", e.toString());
assertEquals(0, ((PatternMatchNode) e).getEscapeChar());
@@ -250,7 +266,7 @@ public class PropertyTest {
@Test
public void testContains_Escape1() {
- Property<String> p = new Property<>("prop");
+ Property<String> p = Property.create("prop", String.class);
Expression e = p.contains("a%bc");
assertEquals("prop like \"%a!%bc%\"", e.toString());
assertEquals('!', ((PatternMatchNode) e).getEscapeChar());
@@ -258,7 +274,7 @@ public class PropertyTest {
@Test
public void testContains_Escape2() {
- Property<String> p = new Property<>("prop");
+ Property<String> p = Property.create("prop", String.class);
Expression e = p.contains("a_!bc");
assertEquals("prop like \"%a#_!bc%\"", e.toString());
assertEquals('#', ((PatternMatchNode) e).getEscapeChar());
@@ -271,4 +287,205 @@ public class PropertyTest {
Expression ex = p.getExpression();
assertEquals("test.path", ex.toString());
}
+
+ @SuppressWarnings("deprecation")
+ @Test
+ public void testDeprecatedConstruct() {
+ Property<String> p = new Property<>("p");
+ assertNull(p.getType());
+ assertEquals("p", p.getName());
+ assertEquals(new ASTObjPath("p"), p.getExpression());
+ }
+
+ @Test
+ public void testCreationWithName() {
+ Property<String> p1 = new Property<>("p1", String.class);
+ assertEquals(String.class, p1.getType());
+ assertEquals("p1", p1.getName());
+ assertEquals(new ASTObjPath("p1"), p1.getExpression());
+
+ Property<String> p2 = Property.create("p1", String.class);
+ assertEquals(p1, p2);
+ }
+
+ @Test
+ public void testCreationWithExp() {
+ Expression exp = FunctionExpressionFactory.currentTime();
+
+ Property<String> p1 = new Property<>(null, exp, String.class);
+ assertEquals(String.class, p1.getType());
+ assertEquals(null, p1.getName());
+ assertEquals(exp, p1.getExpression());
+
+ Property<String> p2 = Property.create(exp, String.class);
+ assertEquals(p1, p2);
+ }
+
+ @Test
+ public void testCreationWithNameAndExp() {
+ Expression exp = FunctionExpressionFactory.currentTime();
+
+ Property<String> p1 = new Property<>("p1", exp, String.class);
+ assertEquals(String.class, p1.getType());
+ assertEquals("p1", p1.getName());
+ assertEquals(exp, p1.getExpression());
+
+ Property<String> p2 = Property.create("p1", exp, String.class);
+ assertEquals(p1, p2);
+ }
+
+ @Test
+ public void testAlias() {
+ Expression exp = FunctionExpressionFactory.currentTime();
+
+ Property<String> p1 = new Property<>("p1", exp, String.class);
+ assertEquals(String.class, p1.getType());
+ assertEquals("p1", p1.getName());
+ assertEquals(exp, p1.getExpression());
+
+ Property<String> p2 = p1.alias("p2");
+ assertEquals(String.class, p2.getType());
+ assertEquals("p2", p2.getName());
+ assertEquals(exp, p2.getExpression());
+ }
+
+ @Test
+ public void testCount() {
+ Property<String> p = Property.create("test", String.class);
+ Property<Long> newProp = p.count();
+ assertTrue(newProp.getExpression() instanceof ASTCount);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testMin() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> newProp = p.min();
+ assertTrue(newProp.getExpression() instanceof ASTMin);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testMax() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> newProp = p.max();
+ assertTrue(newProp.getExpression() instanceof ASTMax);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testSum() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> newProp = p.sum();
+ assertTrue(newProp.getExpression() instanceof ASTSum);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testAvg() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> newProp = p.avg();
+ assertTrue(newProp.getExpression() instanceof ASTAvg);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testAbs() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> newProp = p.abs();
+ assertTrue(newProp.getExpression() instanceof ASTAbs);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testMod() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> newProp = p.mod(3.0);
+ assertTrue(newProp.getExpression() instanceof ASTMod);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ assertEquals(3.0, newProp.getExpression().getOperand(1));
+ }
+
+ @Test
+ public void testSqrt() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> newProp = p.sqrt();
+ assertTrue(newProp.getExpression() instanceof ASTSqrt);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testLength() {
+ Property<String> p = Property.create("test", String.class);
+ Property<Integer> newProp = p.length();
+ assertTrue(newProp.getExpression() instanceof ASTLength);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testLocateString() {
+ Property<String> p = Property.create("test", String.class);
+ Property<Integer> newProp = p.locate("test");
+ assertTrue(newProp.getExpression() instanceof ASTLocate);
+ assertEquals("test", newProp.getExpression().getOperand(0));
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(1));
+ }
+
+ @Test
+ public void testLocateProperty() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> p2 = Property.create("test2", String.class);
+ Property<Integer> newProp = p.locate(p2);
+ assertTrue(newProp.getExpression() instanceof ASTLocate);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(1));
+ assertEquals(p2.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testSustring() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> newProp = p.substring(1, 2);
+ assertTrue(newProp.getExpression() instanceof ASTSubstring);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ assertEquals(1, newProp.getExpression().getOperand(1));
+ assertEquals(2, newProp.getExpression().getOperand(2));
+ }
+
+ @Test
+ public void testTrim() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> newProp = p.trim();
+ assertTrue(newProp.getExpression() instanceof ASTTrim);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testLower() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> newProp = p.lower();
+ assertTrue(newProp.getExpression() instanceof ASTLower);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testUpper() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> newProp = p.upper();
+ assertTrue(newProp.getExpression() instanceof ASTUpper);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ }
+
+ @Test
+ public void testConcat() {
+ Property<String> p = Property.create("test", String.class);
+ Property<String> p2 = Property.create("concat", String.class);
+ Expression exp = new ASTScalar(3);
+
+ Property<String> newProp = p.concat("string", exp, p2);
+ assertTrue(newProp.getExpression() instanceof ASTConcat);
+ assertEquals(p.getExpression(), newProp.getExpression().getOperand(0));
+ assertEquals("string", newProp.getExpression().getOperand(1));
+ assertEquals(3, newProp.getExpression().getOperand(2)); // getOperand unwrapping ASTScalar
+ assertEquals(p2.getExpression(), newProp.getExpression().getOperand(3));
+ }
}
http://git-wip-us.apache.org/repos/asf/cayenne/blob/44bad641/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
index 613b659..4319398 100644
--- a/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
+++ b/cayenne-server/src/test/java/org/apache/cayenne/query/ColumnSelectIT.java
@@ -117,7 +117,7 @@ public class ColumnSelectIT extends ServerCase {
@Test(expected = Exception.class)
public void testHavingOnNonGroupByColumn() throws Exception {
- Property<String> nameSubstr = Property.create(substringExp(Artist.ARTIST_NAME.path(), 1, 6), String.class);
+ Property<String> nameSubstr = Artist.ARTIST_NAME.substring(1, 6);
Object[] q = ObjectSelect.columnQuery(Artist.class, nameSubstr, Property.COUNT)
.having(Artist.ARTIST_NAME.like("artist%"))
@@ -139,10 +139,10 @@ public class ColumnSelectIT extends ServerCase {
@Test
public void testSelectHavingWithExpressionAlias() throws Exception {
- Property<String> nameSubstr = Property.create("name_substr", substringExp(Artist.ARTIST_NAME.path(), 1, 6), String.class);
Object[] q = null;
try {
- q = ObjectSelect.columnQuery(Artist.class, nameSubstr, Property.COUNT)
+ q = ObjectSelect
+ .columnQuery(Artist.class, Artist.ARTIST_NAME.substring(1, 6).alias("name_substr"), Property.COUNT)
.having(Property.COUNT.gt(10L))
.selectOne(context);
} catch (CayenneRuntimeException ex) {
@@ -160,10 +160,9 @@ public class ColumnSelectIT extends ServerCase {
@Test
public void testSelectHavingWithExpressionNoAlias() throws Exception {
- Property<String> nameSubstr = Property.create(substringExp(Artist.ARTIST_NAME.path(), 1, 6), String.class);
Object[] q = null;
try {
- q = ObjectSelect.columnQuery(Artist.class, nameSubstr, Property.COUNT)
+ q = ObjectSelect.columnQuery(Artist.class, Artist.ARTIST_NAME.substring(1, 6), Property.COUNT)
.having(Property.COUNT.gt(10L))
.selectOne(context);
} catch (CayenneRuntimeException ex) {
@@ -179,13 +178,10 @@ public class ColumnSelectIT extends ServerCase {
@Test
public void testSelectWhereAndHaving() throws Exception {
- Property<String> nameFirstLetter = Property.create(substringExp(Artist.ARTIST_NAME.path(), 1, 1), String.class);
- Property<String> nameSubstr = Property.create("name_substr", substringExp(Artist.ARTIST_NAME.path(), 1, 6), String.class);
-
Object[] q = null;
try {
- q = ObjectSelect.columnQuery(Artist.class, nameSubstr, Property.COUNT)
- .where(nameFirstLetter.eq("a"))
+ q = ObjectSelect.columnQuery(Artist.class, Artist.ARTIST_NAME.substring(1, 6).alias("name_substr"), Property.COUNT)
+ .where(Artist.ARTIST_NAME.substring(1, 1).eq("a"))
.having(Property.COUNT.gt(10L))
.selectOne(context);
} catch (CayenneRuntimeException ex) {
@@ -336,7 +332,5 @@ public class ColumnSelectIT extends ServerCase {
.count(Artist.DATE_OF_BIRTH)
.selectOne(context);
assertEquals(count2, count3);
-
-
}
}