This is an automated email from the ASF dual-hosted git repository.

ntimofeev pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git

commit 7411fdf400904ccb6ecb1c1b47ccd52e297a65dc
Author: Nikita Timofeev <stari...@gmail.com>
AuthorDate: Wed Sep 16 12:26:07 2020 +0300

    CAY-2673 Support ordering by aggregate functions
---
 .../access/translator/select/GroupByStage.java     | 11 ++++++
 .../access/translator/select/OrderingStage.java    | 17 +++------
 .../translator/select/ResultNodeDescriptor.java    |  6 ++-
 .../cayenne/query/ObjectSelect_AggregateIT.java    | 43 ++++++++++++++++++++--
 4 files changed, 61 insertions(+), 16 deletions(-)

diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/GroupByStage.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/GroupByStage.java
index 42be789..211a55a 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/GroupByStage.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/GroupByStage.java
@@ -19,6 +19,9 @@
 
 package org.apache.cayenne.access.translator.select;
 
+import org.apache.cayenne.exp.parser.ASTAggregateFunctionCall;
+import org.apache.cayenne.query.Ordering;
+
 /**
  * @since 4.2
  */
@@ -49,6 +52,14 @@ class GroupByStage implements TranslationStage {
             }
         }
 
+        if(context.getQuery().getOrderings() != null) {
+            for(Ordering ordering : context.getQuery().getOrderings()) {
+                if(ordering.getSortSpec() instanceof ASTAggregateFunctionCall) 
{
+                    return true;
+                }
+            }
+        }
+
         return false;
     }
 }
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/OrderingStage.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/OrderingStage.java
index 7cde628..d3085d6 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/OrderingStage.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/OrderingStage.java
@@ -55,10 +55,13 @@ class OrderingStage implements TranslationStage {
         }
 
         // If query is DISTINCT then we need to add all ORDER BY clauses as 
result columns
-        if(shouldAddToResult(context, exp)) {
+        if(!context.isDistinctSuppression()) {
             // TODO: need to check duplicates?
             // need UPPER() function here too, as some DB expect exactly the 
same expression in select and in ordering
-            context.addResultNode(nodeBuilder.build().deepCopy());
+            ResultNodeDescriptor descriptor = 
context.addResultNode(nodeBuilder.build().deepCopy());
+            if(exp instanceof ASTAggregateFunctionCall) {
+                descriptor.setAggregate(true);
+            }
         }
 
         OrderingNodeBuilder orderingNodeBuilder = order(nodeBuilder);
@@ -68,14 +71,4 @@ class OrderingStage implements TranslationStage {
         context.getSelectBuilder().orderBy(orderingNodeBuilder);
     }
 
-    private boolean shouldAddToResult(TranslatorContext context, Expression 
exp) {
-        if(context.isDistinctSuppression()) {
-            return false;
-        }
-        if(exp instanceof ASTAggregateFunctionCall) {
-            return false;
-        }
-        return true;
-    }
-
 }
diff --git 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/ResultNodeDescriptor.java
 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/ResultNodeDescriptor.java
index 4eb03d7..805210f 100644
--- 
a/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/ResultNodeDescriptor.java
+++ 
b/cayenne-server/src/main/java/org/apache/cayenne/access/translator/select/ResultNodeDescriptor.java
@@ -34,9 +34,9 @@ import org.apache.cayenne.map.DbAttribute;
 class ResultNodeDescriptor {
     private final Node node;
     private final boolean inDataRow;
-    private final boolean isAggregate;
     private final Property<?> property;
 
+    private boolean isAggregate;
     private String dataRowKey;
     private DbAttribute dbAttribute;
     private String javaType;
@@ -50,6 +50,10 @@ class ResultNodeDescriptor {
                 && property.getExpression() instanceof 
ASTAggregateFunctionCall;
     }
 
+    public void setAggregate(boolean aggregate) {
+        isAggregate = aggregate;
+    }
+
     public boolean isAggregate() {
         return isAggregate;
     }
diff --git 
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_AggregateIT.java
 
b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_AggregateIT.java
index f3dc231..6c0943d 100644
--- 
a/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_AggregateIT.java
+++ 
b/cayenne-server/src/test/java/org/apache/cayenne/query/ObjectSelect_AggregateIT.java
@@ -34,6 +34,7 @@ import org.apache.cayenne.exp.property.PropertyFactory;
 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;
@@ -79,11 +80,11 @@ public class ObjectSelect_AggregateIT extends ServerCase {
         tGallery.insert(1, "tate modern");
 
         TableHelper tPaintings = new TableHelper(dbHelper, "PAINTING");
-        tPaintings.setColumns("PAINTING_ID", "PAINTING_TITLE", "ARTIST_ID", 
"GALLERY_ID");
+        tPaintings.setColumns("PAINTING_ID", "PAINTING_TITLE", "ARTIST_ID", 
"GALLERY_ID", "ESTIMATED_PRICE");
         for (int i = 1; i <= 20; i++) {
-            tPaintings.insert(i, "painting" + i, i % 5 + 1, 1);
+            tPaintings.insert(i, "painting" + i, i % 5 + 1, 1, i * 10);
         }
-        tPaintings.insert(21, "painting21", 2, 1);
+        tPaintings.insert(21, "painting21", 2, 1, 1000);
     }
 
     @After
@@ -178,4 +179,40 @@ public class ObjectSelect_AggregateIT extends ServerCase {
         assertEquals("artist1", result[0]);
         assertEquals(4L, result[1]);
     }
+
+    @Test
+    public void testOrderByCount() {
+        List<Artist> artists = ObjectSelect.query(Artist.class)
+                .orderBy(Artist.PAINTING_ARRAY.outer().count().desc())
+                .prefetch(Artist.PAINTING_ARRAY.disjoint())
+                .select(context);
+
+        assertEquals(20, artists.size());
+
+        assertEquals(5, artists.get(0).getPaintingArray().size());
+        assertEquals("artist2", artists.get(0).getArtistName());
+        assertEquals(4, artists.get(1).getPaintingArray().size());
+        assertEquals(4, artists.get(2).getPaintingArray().size());
+
+        assertEquals(0, artists.get(17).getPaintingArray().size());
+        assertEquals(0, artists.get(18).getPaintingArray().size());
+        assertEquals(0, artists.get(19).getPaintingArray().size());
+    }
+
+    @Test
+    public void testOrderByAvg() {
+        List<Artist> artists = ObjectSelect.query(Artist.class)
+                
.orderBy(Artist.PAINTING_ARRAY.dot(Painting.ESTIMATED_PRICE).avg().asc())
+                .prefetch(Artist.PAINTING_ARRAY.disjoint())
+                .select(context);
+
+        assertEquals(5, artists.size());
+
+        assertEquals("artist3", artists.get(0).getArtistName());
+        assertEquals("artist4", artists.get(1).getArtistName());
+        assertEquals("artist5", artists.get(2).getArtistName());
+        assertEquals("artist1", artists.get(3).getArtistName());
+        assertEquals("artist2", artists.get(4).getArtistName());
+
+    }
 }
\ No newline at end of file

Reply via email to