mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
FIX: SubQuery with fetch-path does not work correctly
This commit is contained in:
@@ -311,7 +311,7 @@ public final class SqlTreeBuilder {
|
||||
|
||||
} else {
|
||||
// do not read Id on child beans (e.g. when used with fetch())
|
||||
boolean withId = isNotSingleAttribute();
|
||||
boolean withId = isNotSingleAttribute() && !subQuery;
|
||||
return new SqlTreeNodeBean(prefix, prop, props, myList, withId, temporalMode, disableLazyLoad);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,7 +616,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
* Limit the number of fetch joins to Many properties, mark as query joins as needed.
|
||||
*/
|
||||
private void markQueryJoins() {
|
||||
detail.markQueryJoins(beanDescriptor, lazyLoadManyPath, isAllowOneManyFetch(), type != Type.ATTRIBUTE);
|
||||
detail.markQueryJoins(beanDescriptor, lazyLoadManyPath, isAllowOneManyFetch(), type != Type.ATTRIBUTE && type != Type.SUBQUERY);
|
||||
}
|
||||
|
||||
private boolean isAllowOneManyFetch() {
|
||||
@@ -629,7 +629,7 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
|
||||
@Override
|
||||
public void setDefaultSelectClause() {
|
||||
if (type != Type.ATTRIBUTE) {
|
||||
if (type != Type.ATTRIBUTE && type != Type.SUBQUERY) {
|
||||
detail.setDefaultSelectClause(beanDescriptor);
|
||||
} else if (!detail.hasSelectClause()) {
|
||||
// explicit empty select when single attribute query on non-root fetch path
|
||||
|
||||
@@ -6,6 +6,8 @@ import io.ebean.Query;
|
||||
import org.junit.Test;
|
||||
import org.tests.model.basic.CKeyParent;
|
||||
import org.tests.model.basic.Order;
|
||||
import org.tests.model.basic.OrderDetail;
|
||||
import org.tests.model.basic.OrderShipment;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.tests.model.basic.Vehicle;
|
||||
import org.tests.model.basic.VehicleDriver;
|
||||
@@ -47,6 +49,75 @@ public class TestSubQuery extends BaseTestCase {
|
||||
DB.find(Order.class).where().isIn("id", sq).findList();
|
||||
}
|
||||
|
||||
/**
|
||||
* Testcase, that discovered, that DefaultOrmQuery.setDefaultSelectClause is set on subQueries with fetch path.
|
||||
* Also checks, that SqlTreeBuilder does not read id on Many2One props.
|
||||
*/
|
||||
@Test
|
||||
public void test_IsInWithFetchSubQuery1() {
|
||||
|
||||
List<Integer> productIds = new ArrayList<>();
|
||||
productIds.add(3);
|
||||
|
||||
Query<OrderDetail> sq = DB.createQuery(OrderDetail.class).fetch("order", "id").where()
|
||||
.isIn("product.id", productIds).query();
|
||||
|
||||
// execute the subQuery as copy (generatedSQL must be part of original query)
|
||||
Query<OrderDetail> debugSq = sq.copy();
|
||||
debugSq.findSingleAttribute();
|
||||
assertThat(debugSq.getGeneratedSql()).isEqualTo(
|
||||
"select t1.id from o_order_detail t0 join o_order t1 on t1.id = t0.order_id where t0.product_id in (?)");
|
||||
|
||||
Query<Order> query = DB.find(Order.class).select("shipDate").where().isIn("id", sq).query();
|
||||
query.findSingleAttribute();
|
||||
|
||||
assertThat(query.getGeneratedSql())
|
||||
.isEqualTo("select t0.ship_date from o_order t0 where (t0.id) in (" + debugSq.getGeneratedSql() + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Test checks, that DefaultOrmQuery.markQueryJoins handles subQuery correct.
|
||||
*/
|
||||
@Test
|
||||
public void test_IsInWithFetchSubQuery2() {
|
||||
|
||||
Query<OrderDetail> sq = DB.createQuery(OrderDetail.class).fetch("order.customer", "anniversary").where()
|
||||
.eq("order.customer.name", "Roland")
|
||||
.query().setDistinct(true);
|
||||
|
||||
// execute the subQuery as copy (generatedSQL must be part of original query)
|
||||
Query<OrderDetail> debugSq = sq.copy();
|
||||
debugSq.findSingleAttribute();
|
||||
|
||||
Query<Order> query = DB.find(Order.class).select("status").where().isIn("shipDate", sq).query();
|
||||
query.findSingleAttribute();
|
||||
assertThat(query.getGeneratedSql())
|
||||
.isEqualTo("select t0.status from o_order t0 where (t0.ship_date) in (" + debugSq.getGeneratedSql() + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks, that SqlTreeBuilder does not read id on One2Many props.
|
||||
*/
|
||||
@Test
|
||||
public void test_IsInWithFetchSubQuery3() {
|
||||
|
||||
List<Integer> productIds = new ArrayList<>();
|
||||
productIds.add(3);
|
||||
|
||||
Query<OrderDetail> sq = DB.createQuery(OrderDetail.class).fetch("order.shipments", "id").where()
|
||||
.isIn("product.id", productIds).query();
|
||||
|
||||
// execute the subQuery as copy (generatedSQL must be part of original query)
|
||||
Query<OrderDetail> debugSq = sq.copy();
|
||||
debugSq.findSingleAttribute();
|
||||
|
||||
Query<OrderShipment> query = DB.find(OrderShipment.class).select("shipTime").where().isIn("id", sq).query();
|
||||
query.findSingleAttribute();
|
||||
|
||||
assertThat(query.getGeneratedSql())
|
||||
.isEqualTo("select t0.ship_time from or_order_ship t0 where (t0.id) in (" + debugSq.getGeneratedSql() + ")");
|
||||
}
|
||||
|
||||
public void testCompositeKey() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user