From 711701932a2fbc11be0f36b59203cf87190591f3 Mon Sep 17 00:00:00 2001 From: rob bygrave Date: Thu, 11 May 2017 23:20:19 +1200 Subject: [PATCH] #1023 - Bug with findSingleAttributeList() when used against @ManyToOne / foreign key --- .../query/CQueryFetchSingleAttribute.java | 4 +-- .../server/query/CQueryPlan.java | 5 +-- .../server/query/SqlTreeNode.java | 4 +-- .../server/query/SqlTreeNodeBean.java | 16 +++++++--- .../server/query/SqlTreeNodeExtraJoin.java | 4 +-- .../query/SqlTreeNodeManyWhereJoin.java | 4 +-- .../query/other/TestQuerySingleAttribute.java | 31 +++++++++++++++++++ 7 files changed, 54 insertions(+), 14 deletions(-) diff --git a/src/main/java/io/ebeaninternal/server/query/CQueryFetchSingleAttribute.java b/src/main/java/io/ebeaninternal/server/query/CQueryFetchSingleAttribute.java index 85f0b45a3..91be22f35 100644 --- a/src/main/java/io/ebeaninternal/server/query/CQueryFetchSingleAttribute.java +++ b/src/main/java/io/ebeaninternal/server/query/CQueryFetchSingleAttribute.java @@ -54,7 +54,7 @@ class CQueryFetchSingleAttribute { private int rowCount; - private final ScalarType scalarType; + private final ScalarType scalarType; /** * Create the Sql select based on the request. @@ -65,7 +65,7 @@ class CQueryFetchSingleAttribute { this.sql = plan.getSql(); this.desc = request.getBeanDescriptor(); this.predicates = predicates; - this.scalarType = plan.getSingleProperty().getScalarType(); + this.scalarType = plan.getSingleAttributeScalarType(); query.setGeneratedSql(sql); } diff --git a/src/main/java/io/ebeaninternal/server/query/CQueryPlan.java b/src/main/java/io/ebeaninternal/server/query/CQueryPlan.java index 638795e3c..1e2d0f91f 100644 --- a/src/main/java/io/ebeaninternal/server/query/CQueryPlan.java +++ b/src/main/java/io/ebeaninternal/server/query/CQueryPlan.java @@ -11,6 +11,7 @@ import io.ebeaninternal.server.query.CQueryPlanStats.Snapshot; import io.ebeaninternal.server.type.DataBind; import io.ebeaninternal.server.type.DataReader; import io.ebeaninternal.server.type.RsetDataReader; +import io.ebeaninternal.server.type.ScalarType; import io.ebeaninternal.server.util.Md5; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -248,7 +249,7 @@ public class CQueryPlan { return stats.getLastQueryTime(); } - BeanProperty getSingleProperty() { - return sqlTree.getRootNode().getSingleProperty(); + ScalarType getSingleAttributeScalarType() { + return sqlTree.getRootNode().getSingleAttributeScalarType(); } } diff --git a/src/main/java/io/ebeaninternal/server/query/SqlTreeNode.java b/src/main/java/io/ebeaninternal/server/query/SqlTreeNode.java index 27e60cbc8..8406d1fe2 100644 --- a/src/main/java/io/ebeaninternal/server/query/SqlTreeNode.java +++ b/src/main/java/io/ebeaninternal/server/query/SqlTreeNode.java @@ -3,9 +3,9 @@ package io.ebeaninternal.server.query; import io.ebean.Version; import io.ebean.bean.EntityBean; import io.ebeaninternal.api.SpiQuery; -import io.ebeaninternal.server.deploy.BeanProperty; import io.ebeaninternal.server.deploy.DbReadContext; import io.ebeaninternal.server.deploy.DbSqlContext; +import io.ebeaninternal.server.type.ScalarType; import java.sql.SQLException; import java.util.List; @@ -81,6 +81,6 @@ interface SqlTreeNode { /** * Return the property for singleAttribute query. */ - BeanProperty getSingleProperty(); + ScalarType getSingleAttributeScalarType(); } diff --git a/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java b/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java index c601680b6..534004a3f 100644 --- a/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java +++ b/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeBean.java @@ -11,12 +11,14 @@ import io.ebeaninternal.api.SpiQuery.Mode; import io.ebeaninternal.server.deploy.BeanDescriptor; import io.ebeaninternal.server.deploy.BeanProperty; import io.ebeaninternal.server.deploy.BeanPropertyAssoc; +import io.ebeaninternal.server.deploy.BeanPropertyAssocOne; import io.ebeaninternal.server.deploy.BeanPropertyAssocMany; import io.ebeaninternal.server.deploy.DbReadContext; import io.ebeaninternal.server.deploy.DbSqlContext; import io.ebeaninternal.server.deploy.InheritInfo; import io.ebeaninternal.server.deploy.TableJoin; import io.ebeaninternal.server.deploy.id.IdBinder; +import io.ebeaninternal.server.type.ScalarType; import java.sql.SQLException; import java.sql.Timestamp; @@ -58,7 +60,7 @@ class SqlTreeNodeBean implements SqlTreeNode { * False if report bean and has no id property. */ protected final boolean readId; - + private final boolean disableLazyLoad; protected final InheritInfo inheritInfo; @@ -134,13 +136,19 @@ class SqlTreeNodeBean implements SqlTreeNode { } @Override - public BeanProperty getSingleProperty() { + public ScalarType getSingleAttributeScalarType() { if (properties == null || properties.length == 0) { // if we have no property ask first children (in a distinct select with join) // if we have also no children, NPE happens anyway. - return children[0].getSingleProperty(); + return children[0].getSingleAttributeScalarType(); } - return properties[0]; + if (properties[0] instanceof BeanPropertyAssocOne) { + BeanPropertyAssocOne assocOne = (BeanPropertyAssocOne)properties[0]; + if (assocOne.isAssocId()) { + return assocOne.getTargetDescriptor().getIdProperty().getScalarType(); + } + } + return properties[0].getScalarType(); } private Map createPathMap(String prefix, BeanDescriptor desc) { diff --git a/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeExtraJoin.java b/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeExtraJoin.java index 55c1628c6..1125f941a 100644 --- a/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeExtraJoin.java +++ b/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeExtraJoin.java @@ -3,12 +3,12 @@ package io.ebeaninternal.server.query; import io.ebean.Version; import io.ebean.bean.EntityBean; import io.ebeaninternal.api.SpiQuery; -import io.ebeaninternal.server.deploy.BeanProperty; import io.ebeaninternal.server.deploy.BeanPropertyAssoc; import io.ebeaninternal.server.deploy.BeanPropertyAssocMany; import io.ebeaninternal.server.deploy.DbReadContext; import io.ebeaninternal.server.deploy.DbSqlContext; import io.ebeaninternal.server.deploy.TableJoin; +import io.ebeaninternal.server.type.ScalarType; import java.sql.SQLException; import java.util.ArrayList; @@ -72,7 +72,7 @@ class SqlTreeNodeExtraJoin implements SqlTreeNode { } @Override - public BeanProperty getSingleProperty() { + public ScalarType getSingleAttributeScalarType() { throw new IllegalStateException("No expected"); } diff --git a/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyWhereJoin.java b/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyWhereJoin.java index bd7bf6e37..f91b5c988 100644 --- a/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyWhereJoin.java +++ b/src/main/java/io/ebeaninternal/server/query/SqlTreeNodeManyWhereJoin.java @@ -3,13 +3,13 @@ package io.ebeaninternal.server.query; import io.ebean.Version; import io.ebean.bean.EntityBean; import io.ebeaninternal.api.SpiQuery; -import io.ebeaninternal.server.deploy.BeanProperty; import io.ebeaninternal.server.deploy.BeanPropertyAssoc; import io.ebeaninternal.server.deploy.BeanPropertyAssocMany; import io.ebeaninternal.server.deploy.BeanPropertyAssocOne; import io.ebeaninternal.server.deploy.DbReadContext; import io.ebeaninternal.server.deploy.DbSqlContext; import io.ebeaninternal.server.deploy.TableJoin; +import io.ebeaninternal.server.type.ScalarType; import java.sql.SQLException; import java.util.List; @@ -41,7 +41,7 @@ class SqlTreeNodeManyWhereJoin implements SqlTreeNode { } @Override - public BeanProperty getSingleProperty() { + public ScalarType getSingleAttributeScalarType() { throw new IllegalStateException("No expected"); } diff --git a/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java b/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java index 00ac23671..cc869adf2 100644 --- a/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java +++ b/src/test/java/org/tests/query/other/TestQuerySingleAttribute.java @@ -299,4 +299,35 @@ public class TestQuerySingleAttribute extends BaseTestCase { + "join rawinherit_parent_rawinherit_data t1 on t0.id = t1.rawinherit_data_id " + "join parent t2 on t1.rawinherit_parent_id = t2.id"); } + + @Test + public void distinctWithOrderByPk() { + + ResetBasicData.reset(); + + Query query = Ebean.find(Contact.class) + .setDistinct(true) + .select("customer") + .orderBy().desc("customer"); + + query.findSingleAttributeList(); + + assertThat(sqlOf(query)).contains("select distinct t0.customer_id from contact t0 order by t0.customer_id desc"); + } + + @Test + public void distinctWithCascadedFetchOrderByPk() { + + ResetBasicData.reset(); + + Query query = Ebean.find(Contact.class) + .setDistinct(true) + .fetch("customer","billingAddress") + .orderBy().desc("customer.billingAddress"); + + query.findSingleAttributeList(); + + assertThat(sqlOf(query)).contains("select distinct t1.billing_address_id from contact t0 join o_customer t1 on t1.id = t0.customer_id order by t1.billing_address_id desc"); + } + }