Repository: cayenne Updated Branches: refs/heads/master 44bad6412 -> c21831862
CAY-2194 Function expressions support in Ordering Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/c2183186 Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/c2183186 Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/c2183186 Branch: refs/heads/master Commit: c21831862a47ea3e064e91e02184604db68b1df3 Parents: 44bad64 Author: Nikita Timofeev <stari...@gmail.com> Authored: Thu Jan 26 15:02:44 2017 +0300 Committer: Nikita Timofeev <stari...@gmail.com> Committed: Thu Jan 26 15:02:44 2017 +0300 ---------------------------------------------------------------------- .../translator/select/OrderingTranslator.java | 9 +++ .../java/org/apache/cayenne/query/Ordering.java | 9 +++ .../cayenne/access/DataContextOrderingIT.java | 5 +- .../translator/select/OrderingTranslatorIT.java | 25 +++++++ .../query/ObjectSelect_PrimitiveColumnsIT.java | 31 +++++--- .../org/apache/cayenne/query/OrderingTest.java | 76 ++++++++++++++++++++ 6 files changed, 142 insertions(+), 13 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2183186/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/OrderingTranslator.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/OrderingTranslator.java b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/OrderingTranslator.java index 7a7ba4f..4079b0a 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/OrderingTranslator.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/OrderingTranslator.java @@ -80,6 +80,8 @@ public class OrderingTranslator extends QueryAssemblerHelper { appendObjPath(exp); } else if (exp.getType() == Expression.DB_PATH) { appendDbPath(exp); + } else if (exp.getType() == Expression.FUNCTION_CALL) { + appendFunction(exp); } else { throw new CayenneRuntimeException("Unsupported ordering expression: " + exp); } @@ -107,6 +109,13 @@ public class OrderingTranslator extends QueryAssemblerHelper { } } + protected void appendFunction(Expression exp) { + QualifierTranslator qualifierTranslator = queryAssembler.getAdapter().getQualifierTranslator(queryAssembler); + qualifierTranslator.setQualifier(exp); + StringBuilder builder = qualifierTranslator.appendPart(new StringBuilder()); + out.append(builder.toString()); + } + /** * Returns the column expressions (not Expressions) used in the order by * clause. E.g., in the case of an case-insensitive order by, an element of http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2183186/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java b/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java index 9e26991..cb82a2a 100644 --- a/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java +++ b/cayenne-server/src/main/java/org/apache/cayenne/query/Ordering.java @@ -147,6 +147,15 @@ public class Ordering implements Comparator<Object>, Serializable, XMLSerializab return true; } + @Override + public int hashCode() { + int result = sortSpecString != null ? sortSpecString.hashCode() : 0; + result = 31 * result + (sortOrder != null ? sortOrder.hashCode() : 0); + result = 31 * result + (pathExceptionSuppressed ? 1 : 0); + result = 31 * result + (nullSortedFirst ? 1 : 0); + return result; + } + /** * Sets sortSpec to be an expression represented by string argument. * http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2183186/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextOrderingIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextOrderingIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextOrderingIT.java index a9f2039..68506d2 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextOrderingIT.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/access/DataContextOrderingIT.java @@ -118,10 +118,7 @@ public class DataContextOrderingIT extends ServerCase { assertEquals(2, list1.size()); } - /** - * For now Ordering doesn't support custom expression - */ - @Test(expected = CayenneRuntimeException.class) + @Test public void testCustomPropertySort() throws Exception { Calendar c = Calendar.getInstance(); http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2183186/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/OrderingTranslatorIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/OrderingTranslatorIT.java b/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/OrderingTranslatorIT.java index ba21af7..cca9c9b 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/OrderingTranslatorIT.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/access/translator/select/OrderingTranslatorIT.java @@ -23,8 +23,11 @@ import static org.junit.Assert.assertEquals; import java.util.Arrays; +import org.apache.cayenne.CayenneRuntimeException; import org.apache.cayenne.access.DataNode; import org.apache.cayenne.di.Inject; +import org.apache.cayenne.exp.ExpressionFactory; +import org.apache.cayenne.exp.FunctionExpressionFactory; import org.apache.cayenne.query.Ordering; import org.apache.cayenne.query.SelectQuery; import org.apache.cayenne.query.SortOrder; @@ -97,6 +100,28 @@ public class OrderingTranslatorIT extends ServerCase { doTestAppendPart("UPPER(ta.ARTIST_NAME), UPPER(ta.ESTIMATED_PRICE)", o1, o2); } + @Test + public void testAppendFunctionExpression1() throws Exception { + Ordering o1 = new Ordering(FunctionExpressionFactory.absExp("paintingArray.estimatedPrice")); + + doTestAppendPart("ABS(ta.ESTIMATED_PRICE)", o1); + } + + @Test + public void testAppendFunctionExpression2() throws Exception { + Ordering o1 = new Ordering(FunctionExpressionFactory.countExp(ExpressionFactory.pathExp("dateOfBirth")), SortOrder.ASCENDING_INSENSITIVE); + Ordering o2 = new Ordering(FunctionExpressionFactory.modExp("paintingArray.estimatedPrice", 3), SortOrder.DESCENDING); + + doTestAppendPart("UPPER(COUNT(ta.DATE_OF_BIRTH)), MOD(ta.ESTIMATED_PRICE, ?) DESC", o1, o2); + } + + @Test(expected = CayenneRuntimeException.class) + public void testAppendIllegalExpression() throws Exception { + Ordering o1 = new Ordering(ExpressionFactory.and(ExpressionFactory.expTrue(), ExpressionFactory.expFalse())); + // should throw exception + doTestAppendPart("TRUE AND FALSE", o1); + } + private void doTestAppendPart(String expectedSQL, Ordering... orderings) { SelectQuery<Artist> q = SelectQuery.query(Artist.class); http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2183186/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_PrimitiveColumnsIT.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_PrimitiveColumnsIT.java b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_PrimitiveColumnsIT.java index 14f0d71..15326e6 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_PrimitiveColumnsIT.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_PrimitiveColumnsIT.java @@ -54,9 +54,11 @@ public class ObjectSelect_PrimitiveColumnsIT extends ServerCase { @Inject private UnitDbAdapter unitDbAdapter; + private TableHelper tPrimitives; + @Before public void createTestRecords() throws Exception { - TableHelper tPrimitives = new TableHelper(dbHelper, "PRIMITIVES_TEST"); + tPrimitives = new TableHelper(dbHelper, "PRIMITIVES_TEST"); tPrimitives.setColumns("ID", "BOOLEAN_COLUMN", "INT_COLUMN"); for (int i = 1; i <= 20; i++) { tPrimitives.insert(i, (i % 2 == 0), i * 10); @@ -165,23 +167,34 @@ public class ObjectSelect_PrimitiveColumnsIT extends ServerCase { @Test public void testSum() throws Exception { - Property<Long> sumProp = Property.create(sumExp(PrimitivesTestEntity.INT_COLUMN.path()), Long.class); - - long sum = ObjectSelect.query(PrimitivesTestEntity.class) - .column(sumProp) + int sum = ObjectSelect.query(PrimitivesTestEntity.class) + .sum(PrimitivesTestEntity.INT_COLUMN) .selectOne(context); assertEquals(2100, sum); } @Test public void testAvg() throws Exception { - Property<Double> avgProp = Property.create(avgExp(PrimitivesTestEntity.INT_COLUMN.path()), Double.class); - - double avg = ObjectSelect.query(PrimitivesTestEntity.class) - .column(avgProp) + int avg = ObjectSelect.query(PrimitivesTestEntity.class) + .avg(PrimitivesTestEntity.INT_COLUMN) .selectOne(context); assertEquals(105.0, avg, 0.00001); } + @Test + public void testOrderByCount() throws Exception { + tPrimitives.insert(21, true, 210); + + List<Object[]> res = ObjectSelect + .columnQuery(PrimitivesTestEntity.class, PrimitivesTestEntity.BOOLEAN_COLUMN, PrimitivesTestEntity.INT_COLUMN.count()) + .orderBy(PrimitivesTestEntity.INT_COLUMN.count().asc()) + .select(context); + assertEquals(2, res.size()); + + assertEquals(false, res.get(0)[0]); + assertEquals(true, res.get(1)[0]); + assertEquals(10L, res.get(0)[1]); + assertEquals(11L, res.get(1)[1]); + } } http://git-wip-us.apache.org/repos/asf/cayenne/blob/c2183186/cayenne-server/src/test/java/org/apache/cayenne/query/OrderingTest.java ---------------------------------------------------------------------- diff --git a/cayenne-server/src/test/java/org/apache/cayenne/query/OrderingTest.java b/cayenne-server/src/test/java/org/apache/cayenne/query/OrderingTest.java index c6c7d55..66cb4a1 100644 --- a/cayenne-server/src/test/java/org/apache/cayenne/query/OrderingTest.java +++ b/cayenne-server/src/test/java/org/apache/cayenne/query/OrderingTest.java @@ -19,6 +19,8 @@ package org.apache.cayenne.query; +import org.apache.cayenne.exp.Expression; +import org.apache.cayenne.exp.FunctionExpressionFactory; import org.apache.cayenne.testdo.testmap.Painting; import org.apache.cayenne.unit.util.TstBean; import org.junit.Test; @@ -124,6 +126,19 @@ public class OrderingTest { } @Test + public void testOrderingWithExpression() { + Expression exp = FunctionExpressionFactory.absExp("x"); + Ordering ord = new Ordering(); + ord.setSortSpec(exp); + ord.setSortOrder(SortOrder.ASCENDING); + + Ordering ord2 = new Ordering(exp); + assertEquals(ord, ord2); + assertEquals(exp, ord2.getSortSpec()); + assertEquals(SortOrder.ASCENDING, ord2.getSortOrder()); + } + + @Test public void testCompare3() { Painting p1 = new Painting(); p1.setEstimatedPrice(new BigDecimal(1000.00)); @@ -268,6 +283,67 @@ public class OrderingTest { assertEquals(shouldBe5, orderedList.get(5)); } + @Test + public void testOrderListWithFunction() { + Collection<TstBean> set = new HashSet<>(6); + + TstBean shouldBe0 = new TstBean("", 0); + TstBean shouldBe1 = new TstBean("", -1); + TstBean shouldBe2 = new TstBean("", -2); + TstBean shouldBe3 = new TstBean("", 5); + TstBean shouldBe4 = new TstBean("", -6); + TstBean shouldBe5 = new TstBean("", -30); + + set.add(shouldBe4); + set.add(shouldBe2); + set.add(shouldBe1); + set.add(shouldBe5); + set.add(shouldBe0); + set.add(shouldBe3); + + List<TstBean> orderedList = new Ordering(FunctionExpressionFactory.absExp("integer"), SortOrder.ASCENDING).orderedList(set); + + assertEquals(shouldBe0, orderedList.get(0)); + assertEquals(shouldBe1, orderedList.get(1)); + assertEquals(shouldBe2, orderedList.get(2)); + assertEquals(shouldBe3, orderedList.get(3)); + assertEquals(shouldBe4, orderedList.get(4)); + assertEquals(shouldBe5, orderedList.get(5)); + } + + @Test + public void testOrderListWithFunction_Static() { + Collection<TstBean> set = new HashSet<>(6); + + TstBean shouldBe0 = new TstBean("cx", -2); + TstBean shouldBe1 = new TstBean("cf", -1); + TstBean shouldBe2 = new TstBean("basa", 2); + TstBean shouldBe3 = new TstBean("abcd", -1); + TstBean shouldBe4 = new TstBean("bdsasd", -2); + TstBean shouldBe5 = new TstBean("bdsadf", 1); + + set.add(shouldBe4); + set.add(shouldBe2); + set.add(shouldBe1); + set.add(shouldBe5); + set.add(shouldBe0); + set.add(shouldBe3); + + List<Ordering> orderings = asList( + new Ordering(FunctionExpressionFactory.lengthExp("string"), SortOrder.ASCENDING), + new Ordering(FunctionExpressionFactory.absExp("integer"), SortOrder.DESCENDING) + ); + + List<TstBean> orderedList = Ordering.orderedList(set, orderings); + + assertEquals(shouldBe0, orderedList.get(0)); + assertEquals(shouldBe1, orderedList.get(1)); + assertEquals(shouldBe2, orderedList.get(2)); + assertEquals(shouldBe3, orderedList.get(3)); + assertEquals(shouldBe4, orderedList.get(4)); + assertEquals(shouldBe5, orderedList.get(5)); + } + public static class B1 { private B2 b2;