Merge pull request #2502 from FOCONIS/fix-composite-id-in-select-distinct

Fix: composite id in select distinct queries
This commit is contained in:
Rob Bygrave
2022-01-26 22:22:18 +13:00
committed by GitHub
2 changed files with 52 additions and 2 deletions
@@ -568,8 +568,16 @@ final class CQueryBuilder {
if (countSingleAttribute) {
sb.append("r1.attribute_, count(*) from (select ");
if (distinct) {
sb.append("distinct t0.");
sb.append(request.descriptor().idProperty().dbColumn()).append(", ");
sb.append("distinct ");
BeanProperty idProp = request.descriptor().idProperty();
if (idProp.isEmbedded()) {
BeanProperty[] props = ((BeanPropertyAssocOne<?>) idProp).properties();
for (BeanProperty prop : props) {
sb.append("t0.").append(prop.dbColumn()).append(", ");
}
} else {
sb.append("t0.").append(idProp.dbColumn()).append(", ");
}
}
sb.append(select.getSelectSql()).append(" as attribute_");
} else {
@@ -1,8 +1,11 @@
package org.tests.compositekeys;
import io.ebean.BaseTestCase;
import io.ebean.CountDistinctOrder;
import io.ebean.DB;
import io.ebean.Query;
import io.ebean.annotation.Identity;
import io.ebean.annotation.Platform;
import io.ebeaninternal.api.SpiEbeanServer;
import io.ebeaninternal.server.deploy.BeanDescriptor;
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
@@ -16,6 +19,7 @@ import java.util.List;
import java.util.Set;
import static io.ebean.annotation.IdentityGenerated.BY_DEFAULT;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
@@ -82,6 +86,44 @@ public class TestOnCascadeDeleteChildrenWithCompositeKeys extends BaseTestCase {
beanProperty.findIdsByParentId(null, ids, null, null, true);
beanProperty.findIdsByParentId(1L, null, null, null, true);
}
/**
* Test makes select and a select distinct of entities with composite keys.
*/
@Test
public void testSelectDistinctCountWithCompositeKey() {
// first query with a simple findList
Query<UserRole> query1 = DB.find(UserRole.class);
query1.findList();
assertThat(query1.getGeneratedSql()).contains("select t0.user_id, t0.role_id, t0.user_id, t0.role_id from em_user_role t0");
// second query with count distinct
query1 = DB.find(UserRole.class);
query1.select("");
query1.fetch("user", "name");
query1.setDistinct(true).setCountDistinct(CountDistinctOrder.COUNT_DESC_ATTR_ASC).setMaxRows(20);
query1.findSingleAttributeList();
if (isH2() || isMariaDB() || isPostgres()) {
assertThat(query1.getGeneratedSql()).contains("select distinct r1.attribute_, count(*) from "
+ "(select distinct t0.user_id, t0.role_id, t1.name as attribute_ "
+ "from em_user_role t0 join em_user t1 on t1.id = t0.user_id) r1 "
+ "group by r1.attribute_ order by count(*) desc, r1.attribute_ limit 20");
} else if (isDb2()) {
assertThat(query1.getGeneratedSql()).contains("select distinct r1.attribute_, count(*) from "
+ "(select distinct t0.user_id, t0.role_id, t1.name as attribute_ "
+ "from em_user_role t0 join em_user t1 on t1.id = t0.user_id) r1 "
+ "group by r1.attribute_ order by count(*) desc, r1.attribute_ fetch next 20 rows only");
} else if (isSqlServer()) {
assertThat(query1.getGeneratedSql()).contains("select distinct top 20 r1.attribute_, count(*) "
+ "from (select distinct t0.user_id, t0.role_id, t1.name as attribute_ from em_user_role t0 "
+ "join em_user t1 on t1.id = t0.user_id) r1 group by r1.attribute_ order by count(*) desc, r1.attribute_");
} else {
// no Oracle test yet
}
}
@Identity(generated = BY_DEFAULT)
@Entity