#832 - Refactor: Change generated SQL to use "left join" rather than "left outer join" - change tests

This commit is contained in:
Rob Bygrave
2016-10-15 14:37:36 +13:00
parent 9158f46bb3
commit c3f43d503f
28 changed files with 380 additions and 379 deletions
@@ -103,7 +103,7 @@ public class EbeanServer_eqlTest extends BaseTestCase {
query.setUseCache(false);
query.findUnique();
assertThat(query.getGeneratedSql()).contains("from o_customer t0 left outer join contact t1 on t1.customer_id = t0.id ");
assertThat(query.getGeneratedSql()).contains("from o_customer t0 left join contact t1 on t1.customer_id = t0.id ");
}
@Test
@@ -118,6 +118,6 @@ public class EbeanServer_eqlTest extends BaseTestCase {
query.setUseCache(false);
query.findUnique();
assertThat(query.getGeneratedSql()).contains("from o_customer t0 left outer join contact t1 on t1.customer_id = t0.id ");
assertThat(query.getGeneratedSql()).contains("from o_customer t0 left join contact t1 on t1.customer_id = t0.id ");
}
}
@@ -53,7 +53,7 @@ public class UpdateQueryTest extends BaseTestCase {
query.update();
assertThat(sqlOf(query)).contains("update o_customer set status=?, updtime=? where id in (select t0.id from o_customer t0 left outer join o_address t1 on t1.id = t0.billing_address_id where t0.status = ? and t1.country_code = ? and t0.id > ? )");
assertThat(sqlOf(query)).contains("update o_customer set status=?, updtime=? where id in (select t0.id from o_customer t0 left join o_address t1 on t1.id = t0.billing_address_id where t0.status = ? and t1.country_code = ? and t0.id > ? )");
}
@Test
@@ -124,7 +124,7 @@ public class TestLimitQuery extends BaseTestCase {
query.findList();
sql = query.getGeneratedSql();
hasDetailsJoin = sql.contains("left outer join o_order_detail");
hasDetailsJoin = sql.contains("left join o_order_detail");
hasLimit = sql.contains("limit 10");
hasSelectedDetails = sql.contains("od.id");
hasDistinct = sql.contains("select distinct");
@@ -35,7 +35,7 @@ public class TestQueryJoinToAssocOne extends BaseTestCase {
String secondaryQuery = trimSql(loggedSql.get(1), 1);
assertThat(secondaryQuery).contains("select t0.order_id, t0.id,");
assertThat(secondaryQuery).contains(" from o_order_detail t0 left outer join o_product t1");
assertThat(secondaryQuery).contains(" from o_order_detail t0 left join o_product t1");
assertThat(secondaryQuery).contains(" (t0.order_id) in (?");
assertThat(secondaryQuery).contains(" order by t0.order_id, t0.id");
}
@@ -62,7 +62,7 @@ public class TestQueryJoinToAssocOne extends BaseTestCase {
String secondaryQuery = trimSql(loggedSql.get(1), 1);
assertThat(secondaryQuery).contains("select t0.order_id, t0.id,");
assertThat(secondaryQuery).contains(" from o_order_detail t0 left outer join o_product t1");
assertThat(secondaryQuery).contains(" from o_order_detail t0 left join o_product t1");
assertThat(secondaryQuery).contains(" (t0.order_id) in (?");
assertThat(secondaryQuery).contains(" order by t0.order_id, t0.id");
}
@@ -102,7 +102,7 @@ public class TestQueryJoinToAssocOne extends BaseTestCase {
String secondaryQuery = trimSql(loggedSql.get(1), 1);
assertThat(secondaryQuery).contains("select t0.order_id, t0.id,");
assertThat(secondaryQuery).contains(" from o_order_detail t0 left outer join o_product t1");
assertThat(secondaryQuery).contains(" from o_order_detail t0 left join o_product t1");
assertThat(secondaryQuery).contains(" (t0.order_id) in (?");
assertThat(secondaryQuery).contains(" order by t0.order_id, t0.id");
}
@@ -138,6 +138,6 @@ public class TestQueryJoinToAssocOne extends BaseTestCase {
String originQuery = trimSql(loggedSql.get(0), 5);
assertThat(originQuery).contains("select t0.id, t0.status, t0.ship_date, t1.id, t1.order_qty, t1.unit_price");
assertThat(originQuery).contains(" from o_order t0 left outer join o_order_detail t1 ");
assertThat(originQuery).contains(" from o_order t0 left join o_order_detail t1 ");
}
}
@@ -141,11 +141,11 @@ public class TestSecondaryQueries extends BaseTestCase {
// select t0.id c0, t0.name c1, t0.status c2,
// t1.id c3, t1.first_name c4, t1.last_name c5, t1.phone c6, t1.mobile c7, t1.email c8, t1.cretime c9, t1.updtime c10, t1.customer_id c11, t1.group_id c12
// from o_customer t0
// left outer join contact t1 on t1.customer_id = t0.id
// left join contact t1 on t1.customer_id = t0.id
// where t0.id = ? order by t0.id; --bind(1)
Assert.assertTrue(custSecondarySql.contains("from o_customer t0 "));
Assert.assertTrue(custSecondarySql.contains("left outer join contact t1 on t1.customer_id = t0.id "));
Assert.assertTrue(custSecondarySql.contains("left join contact t1 on t1.customer_id = t0.id "));
Assert.assertTrue(custSecondarySql.contains("where t0.id "));
@@ -32,7 +32,7 @@ public class TestDeleteByQuery extends BaseTestCase {
List<String> loggedSql = LoggedSqlCollector.stop();
assertThat(loggedSql).hasSize(1);
assertThat(trimSql(loggedSql.get(0), 1)).contains("delete from contact where id in (select t0.id from contact t0 left outer join");
assertThat(trimSql(loggedSql.get(0), 1)).contains("delete from contact where id in (select t0.id from contact t0 left join");
Query<Contact> query2 = server.find(Contact.class).where().eq("firstName", "NotARealFirstName").query();
@@ -117,7 +117,7 @@ public class TestInheritInsert extends BaseTestCase {
Car result = query.findUnique();
assertThat(query.getGeneratedSql()).contains("order by t0.id, t2.location_code");
assertThat(query.getGeneratedSql()).contains("left outer join car_fuse t2 on t2.id = t1.fuse_id");
assertThat(query.getGeneratedSql()).contains("left join car_fuse t2 on t2.id = t1.fuse_id");
assertNotNull(result);
}
@@ -9,6 +9,8 @@ import com.avaje.ebean.Query;
import java.util.Random;
import static org.assertj.core.api.Assertions.assertThat;
public class TestMediaInheritanceJoinToMany extends BaseTestCase {
@Test
@@ -30,14 +32,14 @@ public class TestMediaInheritanceJoinToMany extends BaseTestCase {
// select t0.id c0, t0.name c1, t1.type c2, t1.id c3, t1.url c4, t1.note c5
// from profile t0
// left outer join media t1 on t1.id = t0.picture_id and t1.type = 'Picture'
// left join media t1 on t1.id = t0.picture_id and t1.type = 'Picture'
// where t0.name = ? ; --bind(nopic)
// specifically t1.type = 'Picture' ... on on the join and not in the where
String generatedSql = query.getGeneratedSql();
Assert.assertTrue(generatedSql.contains("from mprofile t0 left outer join mmedia t1 on t1.id = t0.picture_id and t1.type = 'Picture' "));
Assert.assertTrue(generatedSql.contains("where t0.name = ? "));
assertThat(generatedSql).contains("from mprofile t0 left join mmedia t1 on t1.id = t0.picture_id and t1.type = 'Picture' ");
assertThat(generatedSql).contains("where t0.name = ? ");
}
@@ -31,7 +31,7 @@ public class TestOneToOneOptionalRelationship extends BaseTestCase {
String sql = trimSql(loggedSql.get(0), 1);
Assert.assertTrue(sql.contains("select t0.id, t0.name"));
Assert.assertTrue(sql.contains(" from oto_account t0 left outer join oto_user t1 on t1.account_id = t0.id where t0.id = ?"));
Assert.assertTrue(sql.contains(" from oto_account t0 left join oto_user t1 on t1.account_id = t0.id where t0.id = ?"));
}
@@ -66,7 +66,7 @@ public class TestOneToOneOptionalRelationship extends BaseTestCase {
String sql = trimSql(loggedSql.get(0), 1);
Assert.assertTrue(sql.contains("select t0.id, t0.name"));
Assert.assertTrue(sql.contains(" from oto_account t0 left outer join oto_user t1 on t1.account_id = t0.id where t0.id = ?"));
Assert.assertTrue(sql.contains(" from oto_account t0 left join oto_user t1 on t1.account_id = t0.id where t0.id = ?"));
String lazyLoadSql = trimSql(loggedSql.get(1), 5);
Assert.assertTrue(lazyLoadSql.contains("select t0.id, t0.name, t0.version, t0.when_created, t0.when_modified, t0.account_id from oto_user t0 where t0.id = ?"));
@@ -104,6 +104,6 @@ public class TestOneToOneOptionalRelationship extends BaseTestCase {
String sql = trimSql(loggedSql.get(0), 1);
Assert.assertTrue(sql.contains("select t0.id, t0.name"));
Assert.assertTrue(sql.contains(" from oto_account t0 left outer join oto_user t1 on t1.account_id = t0.id where t0.id = ?"));
Assert.assertTrue(sql.contains(" from oto_account t0 left join oto_user t1 on t1.account_id = t0.id where t0.id = ?"));
}
}
@@ -22,7 +22,7 @@ public class TestPview extends BaseTestCase {
query.findList();
String generatedSql = sqlOf(query, 1);
Assert.assertTrue(generatedSql.contains("select distinct t0.amount, t1.value from paggview t0 join pp u1 on u1.id = t0.pview_id join pp_to_ww u2z_ on u2z_.pp_id = u1.id join wview u2 on u2.id = u2z_.ww_id left outer join pp t1 on t1.id = t0.pview_id where u2.id = ? order by t1.value"));
Assert.assertTrue(generatedSql.contains("select distinct t0.amount, t1.value from paggview t0 join pp u1 on u1.id = t0.pview_id join pp_to_ww u2z_ on u2z_.pp_id = u1.id join wview u2 on u2.id = u2z_.ww_id left join pp t1 on t1.id = t0.pview_id where u2.id = ? order by t1.value"));
}
@@ -65,6 +65,6 @@ public class TestViewBaseEntity extends BaseTestCase {
assertThat(details).isNotEmpty();
}
assertThat(query.getGeneratedSql()).contains("from order_agg_vw t0 left outer join o_order t1 on t1.id = t0.order_id left outer join o_customer t3 on t3.id = t1.kcustomer_id left outer join o_order_detail t2 on t2.order_id = t1.id where t2.id > 0 and t0.order_total > ?");
assertThat(query.getGeneratedSql()).contains("from order_agg_vw t0 left join o_order t1 on t1.id = t0.order_id left join o_customer t3 on t3.id = t1.kcustomer_id left join o_order_detail t2 on t2.order_id = t1.id where t2.id > 0 and t0.order_total > ?");
}
}
@@ -48,7 +48,7 @@ public class TestImplicitJoinOnParentRelationship extends BaseTestCase {
query.findList();
String expectedSql = "select distinct t0.id, t0.name from o_customer t0 left outer join o_order u1 on u1.kcustomer_id = t0.id left outer join o_order_detail u2 on u2.order_id = u1.id left outer join o_product u3 on u3.id = u2.product_id where (u3.name = ? or t0.id = ? ) ";
String expectedSql = "select distinct t0.id, t0.name from o_customer t0 left join o_order u1 on u1.kcustomer_id = t0.id left join o_order_detail u2 on u2.order_id = u1.id left join o_product u3 on u3.id = u2.product_id where (u3.name = ? or t0.id = ? ) ";
Assert.assertEquals(expectedSql, sqlOf(query, 1));
}
@@ -64,7 +64,7 @@ public class TestImplicitJoinOnParentRelationship extends BaseTestCase {
query.findList();
String expectedSql = "select distinct t0.id, t0.name from o_customer t0 left outer join o_order u1 on u1.kcustomer_id = t0.id left outer join o_order_detail u2 on u2.order_id = u1.id left outer join o_product u3 on u3.id = u2.product_id where (u3.name = ? or t0.id = ? ) ";
String expectedSql = "select distinct t0.id, t0.name from o_customer t0 left join o_order u1 on u1.kcustomer_id = t0.id left join o_order_detail u2 on u2.order_id = u1.id left join o_product u3 on u3.id = u2.product_id where (u3.name = ? or t0.id = ? ) ";
Assert.assertEquals(expectedSql, sqlOf(query, 1));
}
}
@@ -13,14 +13,14 @@ public class TestJoinOptOneCascade extends BaseTestCase {
@Test
public void test() {
// the left outer join cascades to the join for c
// the left join cascades to the join for c
Query<EOptOneA> query = Ebean.find(EOptOneA.class).fetch("b").fetch("b.c");
query.findList();
String sql = query.getGeneratedSql();
Assert.assertTrue(sql.contains("left outer join eopt_one_b "));
Assert.assertTrue(sql.contains("left outer join eopt_one_c "));
Assert.assertTrue(sql.contains("left join eopt_one_b "));
Assert.assertTrue(sql.contains("left join eopt_one_c "));
}
}
@@ -60,14 +60,14 @@ public class TestManyWhereJoin extends BaseTestCase {
// select distinct t0.id c0, t0.status c1,
// t1.id c2, t1.status c3, t1.order_date c4, t1.ship_date c5, t2.name c6, t1.cretime c7, t1.updtime c8, t1.kcustomer_id c9, t0.id
// from o_customer t0
// left outer join o_order t1 on t1.kcustomer_id = t0.id
// left outer join o_customer t2 on t2.id = t1.kcustomer_id
// left join o_order t1 on t1.kcustomer_id = t0.id
// left join o_customer t2 on t2.id = t1.kcustomer_id
// join o_order u1 on u1.kcustomer_id = t0.id
// where t1.order_date is not null and u1.status = ?
// order by t0.id; --bind(NEW)
Assert.assertTrue(sql.contains("select distinct t0.id, t0.status, t1.id, t1.status,"));
Assert.assertTrue(sql.contains("left outer join o_order t1 on "));
Assert.assertTrue(sql.contains("left join o_order t1 on "));
Assert.assertTrue(sql.contains("join o_order u1 on "));
Assert.assertTrue(sql.contains(" u1.status = ?"));
}
@@ -150,7 +150,7 @@ public class TestManyWhereJoin extends BaseTestCase {
// t1.id c8, t1.order_qty c9, t1.ship_qty c10, t1.unit_price c11, t1.cretime c12, t1.updtime c13, t1.order_id c14, t1.product_id c15, t0.cretime, t0.id, t1.id, t1.order_qty, t1.cretime
// from o_order t0
// join o_customer t2 on t2.id = t0.kcustomer_id
// left outer join o_order_detail t1 on t1.order_id = t0.id
// left join o_order_detail t1 on t1.order_id = t0.id
// join o_order_detail u1 on u1.order_id = t0.id
// where t1.id > 0 and u1.product_id = ?
// order by t0.cretime, t0.id, t1.id asc, t1.order_qty asc, t1.cretime desc; --bind(1)
@@ -160,6 +160,6 @@ public class TestManyWhereJoin extends BaseTestCase {
Assert.assertTrue(sql.contains(" u1.product_id = ?"));
// additional join for fetching the many details
Assert.assertTrue(sql.contains(" left outer join o_order_detail t1 on t1.order_id = t0.id"));
Assert.assertTrue(sql.contains(" left join o_order_detail t1 on t1.order_id = t0.id"));
}
}
@@ -61,7 +61,7 @@ public class TestManyWhereJoinM2M extends BaseTestCase {
String sql = query.getGeneratedSql();
Assert.assertTrue(sql.contains("select distinct"));
Assert.assertTrue(sql.contains("left outer join mrole "));
Assert.assertTrue(sql.contains("left join mrole "));
Assert.assertTrue(sql.contains("join mrole "));
Assert.assertTrue(sql.contains(".role_name = ?"));
@@ -33,15 +33,15 @@ public class TestQueryFetchManyTwoDeep extends BaseTestCase {
List<Customer> list = query.findList();
Assert.assertTrue("has rows", !list.isEmpty());
Assert.assertTrue(query.getGeneratedSql().contains("from o_customer t0 "));
Assert.assertTrue(query.getGeneratedSql().contains("left outer join o_order t1 on t1.kcustomer_id = t0.id"));
Assert.assertTrue(query.getGeneratedSql().contains("left outer join o_customer t2 on t2.id = t1.kcustomer_id"));
Assert.assertTrue(query.getGeneratedSql().contains("left join o_order t1 on t1.kcustomer_id = t0.id"));
Assert.assertTrue(query.getGeneratedSql().contains("left join o_customer t2 on t2.id = t1.kcustomer_id"));
Assert.assertFalse(query.getGeneratedSql().contains("join or_order_ship"));
//select t0.id c0, t0.status c1, t0.name c2, t0.smallnote c3, t0.anniversary c4, t0.cretime c5, t0.updtime c6, t0.billing_address_id c7, t0.shipping_address_id c8, t1.id c9, t1.status c10, t1.order_date c11, t1.ship_date c12,
// t2.name c13, t1.cretime c14, t1.updtime c15, t1.kcustomer_id c16
// from o_customer t0
// left outer join o_order t1 on t1.kcustomer_id = t0.id
// left outer join o_customer t2 on t2.id = t1.kcustomer_id
// left join o_order t1 on t1.kcustomer_id = t0.id
// left join o_customer t2 on t2.id = t1.kcustomer_id
// where t1.order_date is not null order by t0.id; --bind()
@@ -77,16 +77,16 @@ public class TestQueryFetchManyTwoDeep extends BaseTestCase {
// select ...
// from or_order_ship t0
// left outer join o_order t1 on t1.id = t0.order_id
// left outer join o_customer t3 on t3.id = t1.kcustomer_id
// left outer join o_order_detail t2 on t2.order_id = t1.id
// left join o_order t1 on t1.id = t0.order_id
// left join o_customer t3 on t3.id = t1.kcustomer_id
// left join o_order_detail t2 on t2.order_id = t1.id
// where t2.id > 0 ; --bind()
Assert.assertTrue(generatedSql.contains("from or_order_ship t0"));
// Relationship from OrderShipment to Order is optional so outer join here
Assert.assertTrue(generatedSql.contains("left outer join o_order t1 on t1.id = t0.order_id"));
Assert.assertTrue(generatedSql.contains("left outer join o_customer t3 on t3.id = t1.kcustomer_id"));
Assert.assertTrue(generatedSql.contains("left outer join o_order_detail t2 on t2.order_id = t1.id"));
Assert.assertTrue(generatedSql.contains("left join o_order t1 on t1.id = t0.order_id"));
Assert.assertTrue(generatedSql.contains("left join o_customer t3 on t3.id = t1.kcustomer_id"));
Assert.assertTrue(generatedSql.contains("left join o_order_detail t2 on t2.order_id = t1.id"));
// If OrderShipment to Order is not optional you get inner joins up to o_order_detail (which is a many)
@@ -95,7 +95,7 @@ public class TestQueryFetchManyTwoDeep extends BaseTestCase {
// from or_order_ship t0
// join o_order t1 on t1.id = t0.order_id
// join o_customer t3 on t3.id = t1.kcustomer_id
// left outer join o_order_detail t2 on t2.order_id = t1.id
// left join o_order_detail t2 on t2.order_id = t1.id
// where t2.id > 0 ; --bind()
}
@@ -119,15 +119,15 @@ public class TestQueryFetchManyTwoDeep extends BaseTestCase {
// select ...
// from contact t0
// join o_customer t1 on t1.id = t0.customer_id
// left outer join o_order t2 on t2.kcustomer_id = t1.id
// left outer join o_customer t3 on t3.id = t2.kcustomer_id
// left join o_order t2 on t2.kcustomer_id = t1.id
// left join o_customer t3 on t3.id = t2.kcustomer_id
// where t2.order_date is not null ; --bind()
Assert.assertTrue(generatedSql.contains("from contact t0 "));
// Relationship from Contact to Customer is mandatory so inner join here
Assert.assertTrue(generatedSql.contains("join o_customer t1 on t1.id = t0.customer_id"));
// outer join on many relationship 'orders'
Assert.assertTrue(generatedSql.contains("left outer join o_order t2 on t2.kcustomer_id = t1.id"));
Assert.assertTrue(generatedSql.contains("left join o_order t2 on t2.kcustomer_id = t1.id"));
}
@@ -27,9 +27,9 @@ public class TestQueryMultiManyOrder extends BaseTestCase {
Assert.assertTrue(!list.isEmpty());
Assert.assertTrue(sql.contains("join o_customer "));
Assert.assertFalse(sql.contains("left outer join contact "));
Assert.assertFalse(sql.contains("left outer join o_order_detail "));
Assert.assertFalse(sql.contains("left outer join o_product "));
Assert.assertFalse(sql.contains("left join contact "));
Assert.assertFalse(sql.contains("left join o_order_detail "));
Assert.assertFalse(sql.contains("left join o_product "));
}
}
@@ -1,140 +1,140 @@
package com.avaje.tests.query;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.Query;
import com.avaje.tests.model.basic.CKeyParent;
import com.avaje.tests.model.basic.Order;
import com.avaje.tests.model.basic.ResetBasicData;
import com.avaje.tests.model.basic.Vehicle;
import com.avaje.tests.model.basic.VehicleDriver;
import static org.assertj.core.api.StrictAssertions.assertThat;
public class TestSubQuery extends BaseTestCase {
@Test
public void testId() {
ResetBasicData.reset();
List<Integer> productIds = new ArrayList<Integer>();
productIds.add(3);
Query<Order> sq = Ebean.createQuery(Order.class).select("id").where()
.in("details.product.id", productIds).query();
Ebean.find(Order.class).where().in("id", sq).findList();
}
public void testCompositeKey() {
ResetBasicData.reset();
Query<CKeyParent> sq = Ebean.createQuery(CKeyParent.class).select("id.oneKey")
.setAutoTune(false).where().query();
Query<CKeyParent> pq = Ebean.find(CKeyParent.class).where().in("id.oneKey", sq).query();
pq.findList();
String sql = pq.getGeneratedSql();
String golden = "(t0.one_key) in (select t0.one_key from ckey_parent t0) ";
assertThat(sql).contains(golden);
}
/**
* show that ebean is not using the correct table name in the subquery (sq)
*
* public void testInheritance1() { ResetBasicData.reset();
*
* Query<Vehicle> sq = Ebean.createQuery(Vehicle.class) .select("id")
* .setAutoTune(false) .where() .query();
*
* Query<VehicleDriver> pq = Ebean.find(VehicleDriver.class)
* .where().in("vehicle.id", sq) .query();
*
* pq.findList();
*
* String sql = pq.getGeneratedSql(); System.err.println(sql);
*
* String golden = "(t0.vehicle_id) in (select t0.id from t0.vehicle t0)"; if
* (sql.indexOf(golden) < 0) { System.out.println("failed sql:"+sql);
* fail("golden string not found"); }
*
* }
*/
/**
* show that ebean is adding the discriminator to the list of columns in the
* subquery
*/
public void testInheritance2() {
ResetBasicData.reset();
Query<VehicleDriver> sq = Ebean.createQuery(VehicleDriver.class).select("vehicle")
.setAutoTune(false).where().query();
Query<Vehicle> pq = Ebean.find(Vehicle.class).where().in("id", sq).query();
pq.findList();
String sql = pq.getGeneratedSql();
// TODO: If, after bugfixing, the system still join against vehicle I do not
// know now, in our case, it is not necessary if not
// using it in the where clause
String golden = "(t0.id) in (select t0.vehicle_id from vehicle_driver t0 left outer join vehicle t1 on t1.id = t0.vehicle_id )";
assertThat(sql).contains(golden);
}
/**
* show that ebean is adding the discriminator to the list of columns in the
* subquery. Second test to make sure that joining is still possible after
* bugfixing testInheritance2.
*/
public void testInheritance3() {
ResetBasicData.reset();
Query<VehicleDriver> sq = Ebean.createQuery(VehicleDriver.class).select("vehicle")
.setAutoTune(false).where().eq("vehicle.licenseNumber", "abc").query();
Query<Vehicle> pq = Ebean.find(Vehicle.class).where().in("id", sq).query();
pq.findList();
String sql = pq.getGeneratedSql();
String golden = "(t0.id) in (select t0.vehicle_id from vehicle_driver t0 left outer join vehicle t1 on t1.id = t0.vehicle_id where t1.license_number = ? )";
assertThat(sql).contains(golden);
}
/**
* show that ebean is using the wrong column (from the vehicle_driver table
* instead of vehicle) for the selected column in the subquery. In contrast to
* testInheritance2+3 this test forces ebean to "drill down" to the key of the
* relation.
*/
public void testInheritance4() {
ResetBasicData.reset();
Query<VehicleDriver> sq = Ebean.createQuery(VehicleDriver.class).select("vehicle.id")
.setAutoTune(false).where().query();
Query<Vehicle> pq = Ebean.find(Vehicle.class).where().in("id", sq).query();
pq.findList();
String sql = pq.getGeneratedSql();
String golden = "(t0.id) in (select t0.vehicle_id from vehicle_driver t0 left outer join vehicle t1 on t1.id = t0.vehicle_id )";
assertThat(sql).contains(golden);
}
}
package com.avaje.tests.query;
import java.util.ArrayList;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.ebean.Query;
import com.avaje.tests.model.basic.CKeyParent;
import com.avaje.tests.model.basic.Order;
import com.avaje.tests.model.basic.ResetBasicData;
import com.avaje.tests.model.basic.Vehicle;
import com.avaje.tests.model.basic.VehicleDriver;
import static org.assertj.core.api.StrictAssertions.assertThat;
public class TestSubQuery extends BaseTestCase {
@Test
public void testId() {
ResetBasicData.reset();
List<Integer> productIds = new ArrayList<Integer>();
productIds.add(3);
Query<Order> sq = Ebean.createQuery(Order.class).select("id").where()
.in("details.product.id", productIds).query();
Ebean.find(Order.class).where().in("id", sq).findList();
}
public void testCompositeKey() {
ResetBasicData.reset();
Query<CKeyParent> sq = Ebean.createQuery(CKeyParent.class).select("id.oneKey")
.setAutoTune(false).where().query();
Query<CKeyParent> pq = Ebean.find(CKeyParent.class).where().in("id.oneKey", sq).query();
pq.findList();
String sql = pq.getGeneratedSql();
String golden = "(t0.one_key) in (select t0.one_key from ckey_parent t0) ";
assertThat(sql).contains(golden);
}
/**
* show that ebean is not using the correct table name in the subquery (sq)
*
* public void testInheritance1() { ResetBasicData.reset();
*
* Query<Vehicle> sq = Ebean.createQuery(Vehicle.class) .select("id")
* .setAutoTune(false) .where() .query();
*
* Query<VehicleDriver> pq = Ebean.find(VehicleDriver.class)
* .where().in("vehicle.id", sq) .query();
*
* pq.findList();
*
* String sql = pq.getGeneratedSql(); System.err.println(sql);
*
* String golden = "(t0.vehicle_id) in (select t0.id from t0.vehicle t0)"; if
* (sql.indexOf(golden) < 0) { System.out.println("failed sql:"+sql);
* fail("golden string not found"); }
*
* }
*/
/**
* show that ebean is adding the discriminator to the list of columns in the
* subquery
*/
public void testInheritance2() {
ResetBasicData.reset();
Query<VehicleDriver> sq = Ebean.createQuery(VehicleDriver.class).select("vehicle")
.setAutoTune(false).where().query();
Query<Vehicle> pq = Ebean.find(Vehicle.class).where().in("id", sq).query();
pq.findList();
String sql = pq.getGeneratedSql();
// TODO: If, after bugfixing, the system still join against vehicle I do not
// know now, in our case, it is not necessary if not
// using it in the where clause
String golden = "(t0.id) in (select t0.vehicle_id from vehicle_driver t0 left join vehicle t1 on t1.id = t0.vehicle_id )";
assertThat(sql).contains(golden);
}
/**
* show that ebean is adding the discriminator to the list of columns in the
* subquery. Second test to make sure that joining is still possible after
* bugfixing testInheritance2.
*/
public void testInheritance3() {
ResetBasicData.reset();
Query<VehicleDriver> sq = Ebean.createQuery(VehicleDriver.class).select("vehicle")
.setAutoTune(false).where().eq("vehicle.licenseNumber", "abc").query();
Query<Vehicle> pq = Ebean.find(Vehicle.class).where().in("id", sq).query();
pq.findList();
String sql = pq.getGeneratedSql();
String golden = "(t0.id) in (select t0.vehicle_id from vehicle_driver t0 left join vehicle t1 on t1.id = t0.vehicle_id where t1.license_number = ? )";
assertThat(sql).contains(golden);
}
/**
* show that ebean is using the wrong column (from the vehicle_driver table
* instead of vehicle) for the selected column in the subquery. In contrast to
* testInheritance2+3 this test forces ebean to "drill down" to the key of the
* relation.
*/
public void testInheritance4() {
ResetBasicData.reset();
Query<VehicleDriver> sq = Ebean.createQuery(VehicleDriver.class).select("vehicle.id")
.setAutoTune(false).where().query();
Query<Vehicle> pq = Ebean.find(Vehicle.class).where().in("id", sq).query();
pq.findList();
String sql = pq.getGeneratedSql();
String golden = "(t0.id) in (select t0.vehicle_id from vehicle_driver t0 left join vehicle t1 on t1.id = t0.vehicle_id )";
assertThat(sql).contains(golden);
}
}
@@ -57,7 +57,7 @@ public class TestDisjunctWhereOuterJoin extends BaseTestCase {
String sql = query.getGeneratedSql();
Assert.assertTrue(sql.contains("select distinct"));
Assert.assertTrue(sql.contains("outer join mrole "));
Assert.assertTrue(sql.contains("left join mrole "));
Assert.assertTrue(sql.contains(".role_name = ?"));
} finally {
@@ -49,14 +49,14 @@ public class TestDisjunctWhereOuterOnMany extends BaseTestCase {
// select distinct t0.id c0, t0.name c1
// from uuone t0
// join uutwo u1 on u1.master_id = t0.id
// left outer join uutwo t1 on t1.master_id = t0.id
// left join uutwo t1 on t1.master_id = t0.id
// where (t0.name = ? or u1.name = ? ) ;
// --bind(testDisjOuter_2_name,testDisjOuter_CHILD_1)
Assert.assertEquals(2, list.size());
Assert.assertEquals(2, rowCount);
String expectedSql = "select distinct t0.id, t0.name from uuone t0 left outer join uutwo u1 on u1.master_id = t0.id where (t0.name = ? or u1.name = ? ) ";
String expectedSql = "select distinct t0.id, t0.name from uuone t0 left join uutwo u1 on u1.master_id = t0.id where (t0.name = ? or u1.name = ? ) ";
Assert.assertEquals(expectedSql, sqlOf(query, 1));
}
@@ -50,14 +50,14 @@ public class TestQueryJoinManyNonRoot extends BaseTestCase {
assertTrue(!list.isEmpty());
assertTrue(sql.contains("join o_customer t1 on t1.id "));
assertTrue(sql.contains("left outer join contact t2 on"));
assertTrue(sql.contains("left join contact t2 on"));
// select t0.id c0, t0.status c1, t0.order_date c2, t0.ship_date c3, t1.name c4, t0.cretime c5, t0.updtime c6,
// t1.id c7, t1.status c8, t1.name c9, t1.smallnote c10, t1.anniversary c11, t1.cretime c12, t1.updtime c13, t1.billing_address_id c14, t1.shipping_address_id c15,
// t2.id c16, t2.first_name c17, t2.last_name c18, t2.phone c19, t2.mobile c20, t2.email c21, t2.cretime c22, t2.updtime c23, t2.customer_id c24, t2.group_id c25
// from o_order t0
// join o_customer t1 on t1.id = t0.kcustomer_id
// left outer join contact t2 on t2.customer_id = t1.id
// left join contact t2 on t2.customer_id = t1.id
// where t0.id > ? ; --bind(0)
}
@@ -79,10 +79,10 @@ public class TestQueryJoinManyNonRoot extends BaseTestCase {
assertTrue(!list.isEmpty());
assertTrue(sql.contains("join o_customer t1 on t1.id "));
assertTrue(sql.contains("left outer join o_order_detail "));
assertTrue(sql.contains("left outer join o_product "));
assertTrue(sql.contains("left join o_order_detail "));
assertTrue(sql.contains("left join o_product "));
Assert.assertFalse(sql.contains("left outer join contact"));
Assert.assertFalse(sql.contains("left join contact"));
}
@@ -107,10 +107,10 @@ public class TestQueryJoinManyNonRoot extends BaseTestCase {
assertTrue(!list.isEmpty());
assertTrue(sql.contains("join o_customer t1 on t1.id "));
assertTrue(sql.contains("left outer join contact "));
assertTrue(sql.contains("left join contact "));
Assert.assertFalse(sql.contains("left outer join o_order_detail "));
Assert.assertFalse(sql.contains("left outer join o_product "));
Assert.assertFalse(sql.contains("left join o_order_detail "));
Assert.assertFalse(sql.contains("left join o_product "));
}
@@ -80,7 +80,7 @@ public class TestQueryManyToOneWhereClauseJoin extends BaseTestCase {
String generatedSql = query.getGeneratedSql();
Assert.assertTrue(generatedSql.contains("from o_order t0 join o_customer t1 on t1.id = t0.kcustomer_id"));
Assert.assertTrue(generatedSql.contains("left outer join contact t2 on t2.customer_id = t1.id"));
Assert.assertTrue(generatedSql.contains("left join contact t2 on t2.customer_id = t1.id"));
Assert.assertTrue(generatedSql.contains("where lower(t1.name) like ?"));
// select t0.id c0, t0.status c1, t0.order_date c2, t0.ship_date c3, t1.name c4, t0.cretime c5, t0.updtime c6,
@@ -88,7 +88,7 @@ public class TestQueryManyToOneWhereClauseJoin extends BaseTestCase {
// t2.id c16, t2.first_name c17, t2.last_name c18, t2.phone c19, t2.mobile c20, t2.email c21, t2.cretime c22, t2.updtime c23, t2.customer_id c24, t2.group_id c25
// from o_order t0
// join o_customer t1 on t1.id = t0.kcustomer_id
// left outer join contact t2 on t2.customer_id = t1.id
// left join contact t2 on t2.customer_id = t1.id
// where lower(t1.name) like ? ; --bind(rob%)
}
}
@@ -76,7 +76,7 @@ public class TestOrderByWithDistinct extends BaseTestCase {
// select distinct t0.userid c0, t0.user_name c1, t1.id c2, t1.name c3
// from muser t0
// left outer join muser_type t1 on t1.id = t0.user_type_id
// left join muser_type t1 on t1.id = t0.user_type_id
// join mrole_muser u1z_ on u1z_.muser_userid = t0.userid
// join mrole u1 on u1.roleid = u1z_.mrole_roleid
// where u1.role_name = ?
@@ -109,7 +109,7 @@ public class TestOrderByWithDistinct extends BaseTestCase {
// select distinct t0.userid c0, t0.user_name c1, t1.id c2, t1.name c3
// from muser t0
// left outer join muser_type t1 on t1.id = t0.user_type_id
// left join muser_type t1 on t1.id = t0.user_type_id
// join mrole_muser u1z_ on u1z_.muser_userid = t0.userid
// join mrole u1 on u1.roleid = u1z_.mrole_roleid
// where u1.role_name = ?
@@ -37,12 +37,12 @@ public class TestQueryConversationRowCount extends BaseTestCase {
// select distinct t0.id c0, t0.title c1, t0.open c2, t0.version c3, t0.when_created c4, t0.when_updated c5, t0.group_id c6, t0.when_created
// from c_conversation t0
// left outer join c_participation u1 on u1.conversation_id = t0.id
// left join c_participation u1 on u1.conversation_id = t0.id
// where t0.group_id = ? and ((t0.open = ? and u1.user_id = ? ) or t0.open = ? )
// order by t0.when_created desc;
Assert.assertTrue(generatedSql.contains("select distinct t0.id, t0.title, t0.isopen"));
Assert.assertTrue(generatedSql.contains("left outer join c_participation u1 on u1.conversation_id = t0.id"));
Assert.assertTrue(generatedSql.contains("left join c_participation u1 on u1.conversation_id = t0.id"));
Assert.assertTrue(generatedSql.contains("where t0.group_id = ? and ((t0.isopen = ? and u1.user_id = ? ) or t0.isopen = ? )"));
@@ -52,7 +52,7 @@ public class TestQueryConversationRowCount extends BaseTestCase {
// select count(*) from (
// select distinct t0.id c0
// from c_conversation t0
// left outer join c_participation u1 on u1.conversation_id = t0.id
// left join c_participation u1 on u1.conversation_id = t0.id
// where t0.group_id = ? and ((t0.open = ? and u1.user_id = ? ) or t0.open = ? )
// ); --bind(1,true,1,true)
@@ -60,7 +60,7 @@ public class TestQueryConversationRowCount extends BaseTestCase {
Assert.assertEquals(1, loggedSql.size());
String countSql = trimSql(loggedSql.get(0), 0);
Assert.assertTrue(countSql.contains("select count(*) from ( select distinct t0.id from c_conversation t0 left outer join c_participation u1 on u1.conversation_id = t0.id where t0.group_id = ? and ((t0.isopen = ? and u1.user_id = ? ) or t0.isopen = ? )"));
Assert.assertTrue(countSql.contains("select count(*) from ( select distinct t0.id from c_conversation t0 left join c_participation u1 on u1.conversation_id = t0.id where t0.group_id = ? and ((t0.isopen = ? and u1.user_id = ? ) or t0.isopen = ? )"));
}
}
@@ -30,6 +30,6 @@ public class TestQueryRawExpressionMany extends BaseTestCase {
query.findCount();
List<String> sql = LoggedSqlCollector.stop();
assertThat(trimSql(sql.get(0), 1)).contains("select count(*) from ( select distinct t0.id from o_order t0 left outer join o_order_detail t1 on t1.order_id = t0.id where t1.order_qty = ?)");
assertThat(trimSql(sql.get(0), 1)).contains("select count(*) from ( select distinct t0.id from o_order t0 left join o_order_detail t1 on t1.order_id = t0.id where t1.order_qty = ?)");
}
}
@@ -34,14 +34,14 @@ public class TestQueryRowCountWithMany extends BaseTestCase {
// t1.id c8, t1.order_qty c9, t1.ship_qty c10, t1.unit_price c11, t1.cretime c12, t1.updtime c13, t1.order_id c14, t1.product_id c15, t0.cretime, t0.id, t1.id, t1.order_qty, t1.cretime
// from o_order t0
// join o_customer t2 on t2.id = t0.kcustomer_id
// left outer join o_order_detail t1 on t1.order_id = t0.id
// left join o_order_detail t1 on t1.order_id = t0.id
// join o_order_detail u1 on u1.order_id = t0.id
// where t1.id > 0 and u1.product_id = ?
// order by t0.cretime, t0.id, t1.id asc, t1.order_qty asc, t1.cretime desc; --bind(1)
String generatedSql = sqlOf(query, 1);
Assert.assertTrue(generatedSql.contains("select distinct t0.id, t0.status,")); // need the distinct
Assert.assertTrue(generatedSql.contains("left outer join o_order_detail t1 on t1.order_id = t0.id")); //fetch join
Assert.assertTrue(generatedSql.contains("left join o_order_detail t1 on t1.order_id = t0.id")); //fetch join
Assert.assertTrue(generatedSql.contains("join o_order_detail u1 on u1.order_id = t0.id")); //predicate join
Assert.assertTrue(generatedSql.contains(" u1.product_id = ?")); // u1 as predicate alias
Assert.assertTrue(generatedSql.contains(" order by t0.cretime"));
@@ -50,7 +50,7 @@ public class TestQueryRowCountWithMany extends BaseTestCase {
int rowCount = query.findCount();
// select count(*) from o_order t0
// left outer join o_order_detail t1 on t1.order_id = t0.id
// left join o_order_detail t1 on t1.order_id = t0.id
// where t1.product_id = ? ; --bind(1)
// select count(*) from (
@@ -107,7 +107,7 @@ public class TestQuerySingleAttribute extends BaseTestCase {
List<String> names = query.findSingleAttributeList();
assertThat(sqlOf(query)).contains("select distinct t0.name from o_customer t0 left outer join o_address t1 on t1.id = t0.billing_address_id where t0.status = ? and lower(t1.city) like ?");
assertThat(sqlOf(query)).contains("select distinct t0.name from o_customer t0 left join o_address t1 on t1.id = t0.billing_address_id where t0.status = ? and lower(t1.city) like ?");
assertThat(names).isNotNull();
}
@@ -1,168 +1,167 @@
package com.avaje.tests.singleTableInheritance;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.tests.singleTableInheritance.model.*;
public class TestInheritQuery extends BaseTestCase {
@Test
public void test() {
ZoneExternal zone = new ZoneExternal();
zone.setAttribute("ABC");
Ebean.save(zone);
PalletLocationExternal location = new PalletLocationExternal();
location.setZone(zone);
location.setAttribute("123");
Ebean.save(location);
// This line should work too:
List<PalletLocation> locations = Ebean.find(PalletLocation.class).where().eq("zone", zone)
.findList();
// List<PalletLocation> locations =
// Ebean.find(PalletLocation.class).where().eq("zone.id",
// zone.getId()).findList();
Assert.assertNotNull(locations);
Assert.assertEquals(1, locations.size());
PalletLocation rereadLoc = locations.get(0);
Assert.assertTrue(rereadLoc instanceof PalletLocation);
Zone rereadZone = rereadLoc.getZone();
Assert.assertNotNull(rereadZone);
Assert.assertTrue(rereadZone instanceof ZoneExternal);
}
@Test
public void testDiscriminator_bug417() {
Ebean.deleteAll(Ebean.find(Warehouse.class).findList());
Ebean.deleteAll(Ebean.find(PalletLocation.class).findList());
Ebean.deleteAll(Ebean.find(Zone.class).findList());
Ebean.deleteAll(Ebean.find(ZoneInternal.class).findList());
Ebean.deleteAll(Ebean.find(ZoneInternal.class).findList());
ZoneInternal zoneInt = new ZoneInternal();
zoneInt.setAttribute("some zone 1");
Ebean.save(zoneInt);
ZoneExternal zoneExt = new ZoneExternal();
zoneExt.setAttribute("some zone 2");
Ebean.save(zoneExt);
// queries of Zone and subclasses as root node of query
// query abstract class on attribute (root of heirarchy)
List<Zone> zones = Ebean.find(Zone.class).where().startsWith("attribute", "some zone").findList();
// select t0.type c0, t0.ID c1, t0.attribute c2, t0.attribute c3 from zones t0 where t0.attribute like ? ; --bind(some zone%)
Assert.assertEquals(2, zones.size());
Assert.assertTrue(zones.contains(zoneInt));
Assert.assertTrue(zones.contains(zoneExt));
// query internal zones only
// discriminator is in WHERE clause where it belongs
List<ZoneInternal> internalZones = Ebean.find(ZoneInternal.class).where().startsWith("attribute", "some zone").findList();
// select t0.type c0, t0.ID c1, t0.attribute c2 from zones t0 where t0.type = 'INT' and t0.attribute like ? ; --bind(some zone%)
Assert.assertEquals(1, internalZones.size());
Assert.assertTrue(internalZones.contains(zoneInt));
Assert.assertFalse(internalZones.contains(zoneExt));
Assert.assertTrue(internalZones.get(0) instanceof ZoneInternal);
// query external zones only
List<ZoneExternal> externalZones = Ebean.find(ZoneExternal.class).where().startsWith("attribute", "some zone").findList();
// select t0.type c0, t0.ID c1, t0.attribute c2 from zones t0 where t0.type = 'EXT' and t0.attribute like ? ; --bind(some zone%)
Assert.assertEquals(1, externalZones.size());
Assert.assertTrue(externalZones.contains(zoneExt));
Assert.assertFalse(externalZones.contains(zoneInt));
Assert.assertTrue(externalZones.get(0) instanceof ZoneExternal);
// parents with children of Zones and subclasses
Warehouse wh = new Warehouse();
wh.setOfficeZone(zoneInt); // many-to-one
wh.getShippingZones().add(zoneExt); // many-to-many
Ebean.save(wh);
// JOIN clause, no discriminator
// parent with many-to-one, doesn't put in discriminator, why not, PK sufficient?
// eager join
Warehouse wh2 = Ebean.find(Warehouse.class, wh.getId());
// select t0.ID c0, t1.type c1, t0.officeZoneId c2 from warehouses t0 left outer join zones t1 on t1.ID = t0.officeZoneId where t0.ID = ? ; --bind(1)
Assert.assertNotNull(wh2);
Assert.assertEquals(wh.getId(), wh2.getId());
Assert.assertEquals(wh.getOfficeZone(), wh2.getOfficeZone());
Assert.assertEquals(wh.getOfficeZone().getAttribute(), wh2.getOfficeZone().getAttribute());
// before the fix, next assertion runs this lazy query:
// select t0.ID c0, t1.type c1, t1.ID c2 from warehouses t0
// left outer join WarehousesShippingZones t1z_ on t1z_.warehouseId = t0.ID
// left outer join zones t1 on t1.ID = t1z_.shippingZoneId
// where t1.type = 'EXT' // this should be in the join clause
// and t0.ID = ?
// order by t0.ID; --bind(1)
// this works here because we have at least one shipping zone
Assert.assertEquals(1, wh2.getShippingZones().size());
Assert.assertTrue(wh2.getShippingZones().contains(zoneExt));
// set optional concrete to null to set stage for failure
wh.setOfficeZone(null);
Ebean.save(wh);
// no discriminator here
wh2 = Ebean.find(Warehouse.class)
.where().eq("id", wh.getId())
.findUnique();
Assert.assertNotNull(wh2);
// discriminator is used here, should be in join
// assuming this "manual" fetch is equivalent to autofetch (i.e., autofetch should work the same way)
// before Daryl's fix
// select t0.ID c0, t1.type c1, t1.ID c2, t1.attribute c3 from warehouses t0 left outer join zones t1 on t1.ID = t0.officeZoneId where t1.type = 'INT' and t0.ID = ?
// todo: after Daryl's fix, not sure if this is proper, no discriminator at all, isn't PK/FK sufficient?
// select t0.ID c0, t1.type c1, t1.ID c2, t1.attribute c3 from warehouses t0 left outer join zones t1 on t1.ID = t0.officeZoneId where t0.ID = ? ; --bind(1)
wh2 = Ebean.find(Warehouse.class)
.fetch("officeZone")
.where().eq("id", wh.getId())
.findUnique();
// key assertion #1 - fails due to left join with discriminator in WHERE
Assert.assertNotNull(wh2);
// clear children to set the stage for left join failure
wh.getShippingZones().clear();
Ebean.save(wh);
wh2 = Ebean.find(Warehouse.class, wh.getId());
Assert.assertNotNull(wh2);
Assert.assertEquals(wh.getId(), wh2.getId());
Assert.assertEquals(0, wh.getShippingZones().size());
// query with lazy load of abstract children
wh = Ebean.find(Warehouse.class)
.where().eq("id", wh.getId())
.findUnique();
Assert.assertNotNull(wh);
Assert.assertEquals(wh.getId(), wh2.getId());
Assert.assertEquals(0, wh.getShippingZones().size());
// query with fetch of abstract children
wh = Ebean.find(Warehouse.class)
.fetch("shippingZones")
.where().eq("id", wh.getId())
.findUnique();
// key assertion #2 - fails due to left join with discriminator in WHERE
Assert.assertNotNull(wh);
Assert.assertEquals(wh.getId(), wh2.getId());
Assert.assertEquals(0, wh.getShippingZones().size());
}
package com.avaje.tests.singleTableInheritance;
import java.util.List;
import org.junit.Assert;
import org.junit.Test;
import com.avaje.ebean.BaseTestCase;
import com.avaje.ebean.Ebean;
import com.avaje.tests.singleTableInheritance.model.*;
public class TestInheritQuery extends BaseTestCase {
@Test
public void test() {
ZoneExternal zone = new ZoneExternal();
zone.setAttribute("ABC");
Ebean.save(zone);
PalletLocationExternal location = new PalletLocationExternal();
location.setZone(zone);
location.setAttribute("123");
Ebean.save(location);
// This line should work too:
List<PalletLocation> locations = Ebean.find(PalletLocation.class).where().eq("zone", zone)
.findList();
// List<PalletLocation> locations =
// Ebean.find(PalletLocation.class).where().eq("zone.id",
// zone.getId()).findList();
Assert.assertNotNull(locations);
Assert.assertEquals(1, locations.size());
PalletLocation rereadLoc = locations.get(0);
Assert.assertTrue(rereadLoc instanceof PalletLocation);
Zone rereadZone = rereadLoc.getZone();
Assert.assertNotNull(rereadZone);
Assert.assertTrue(rereadZone instanceof ZoneExternal);
}
@Test
public void testDiscriminator_bug417() {
Ebean.deleteAll(Ebean.find(Warehouse.class).findList());
Ebean.deleteAll(Ebean.find(PalletLocation.class).findList());
Ebean.deleteAll(Ebean.find(Zone.class).findList());
Ebean.deleteAll(Ebean.find(ZoneInternal.class).findList());
Ebean.deleteAll(Ebean.find(ZoneInternal.class).findList());
ZoneInternal zoneInt = new ZoneInternal();
zoneInt.setAttribute("some zone 1");
Ebean.save(zoneInt);
ZoneExternal zoneExt = new ZoneExternal();
zoneExt.setAttribute("some zone 2");
Ebean.save(zoneExt);
// queries of Zone and subclasses as root node of query
// query abstract class on attribute (root of heirarchy)
List<Zone> zones = Ebean.find(Zone.class).where().startsWith("attribute", "some zone").findList();
// select t0.type c0, t0.ID c1, t0.attribute c2, t0.attribute c3 from zones t0 where t0.attribute like ? ; --bind(some zone%)
Assert.assertEquals(2, zones.size());
Assert.assertTrue(zones.contains(zoneInt));
Assert.assertTrue(zones.contains(zoneExt));
// query internal zones only
// discriminator is in WHERE clause where it belongs
List<ZoneInternal> internalZones = Ebean.find(ZoneInternal.class).where().startsWith("attribute", "some zone").findList();
// select t0.type c0, t0.ID c1, t0.attribute c2 from zones t0 where t0.type = 'INT' and t0.attribute like ? ; --bind(some zone%)
Assert.assertEquals(1, internalZones.size());
Assert.assertTrue(internalZones.contains(zoneInt));
Assert.assertFalse(internalZones.contains(zoneExt));
Assert.assertTrue(internalZones.get(0) instanceof ZoneInternal);
// query external zones only
List<ZoneExternal> externalZones = Ebean.find(ZoneExternal.class).where().startsWith("attribute", "some zone").findList();
// select t0.type c0, t0.ID c1, t0.attribute c2 from zones t0 where t0.type = 'EXT' and t0.attribute like ? ; --bind(some zone%)
Assert.assertEquals(1, externalZones.size());
Assert.assertTrue(externalZones.contains(zoneExt));
Assert.assertFalse(externalZones.contains(zoneInt));
Assert.assertTrue(externalZones.get(0) instanceof ZoneExternal);
// parents with children of Zones and subclasses
Warehouse wh = new Warehouse();
wh.setOfficeZone(zoneInt); // many-to-one
wh.getShippingZones().add(zoneExt); // many-to-many
Ebean.save(wh);
// JOIN clause, no discriminator
// parent with many-to-one, doesn't put in discriminator, why not, PK sufficient?
// eager join
Warehouse wh2 = Ebean.find(Warehouse.class, wh.getId());
Assert.assertNotNull(wh2);
Assert.assertEquals(wh.getId(), wh2.getId());
Assert.assertEquals(wh.getOfficeZone(), wh2.getOfficeZone());
Assert.assertEquals(wh.getOfficeZone().getAttribute(), wh2.getOfficeZone().getAttribute());
// before the fix, next assertion runs this lazy query:
// select t0.ID c0, t1.type c1, t1.ID c2 from warehouses t0
// left join WarehousesShippingZones t1z_ on t1z_.warehouseId = t0.ID
// left join zones t1 on t1.ID = t1z_.shippingZoneId
// where t1.type = 'EXT' // this should be in the join clause
// and t0.ID = ?
// order by t0.ID; --bind(1)
// this works here because we have at least one shipping zone
Assert.assertEquals(1, wh2.getShippingZones().size());
Assert.assertTrue(wh2.getShippingZones().contains(zoneExt));
// set optional concrete to null to set stage for failure
wh.setOfficeZone(null);
Ebean.save(wh);
// no discriminator here
wh2 = Ebean.find(Warehouse.class)
.where().eq("id", wh.getId())
.findUnique();
Assert.assertNotNull(wh2);
// discriminator is used here, should be in join
// assuming this "manual" fetch is equivalent to autofetch (i.e., autofetch should work the same way)
// before Daryl's fix
// select t0.ID c0, t1.type c1, t1.ID c2, t1.attribute c3 from warehouses t0 left join zones t1 on t1.ID = t0.officeZoneId where t1.type = 'INT' and t0.ID = ?
// todo: after Daryl's fix, not sure if this is proper, no discriminator at all, isn't PK/FK sufficient?
// select t0.ID c0, t1.type c1, t1.ID c2, t1.attribute c3 from warehouses t0 left join zones t1 on t1.ID = t0.officeZoneId where t0.ID = ? ; --bind(1)
wh2 = Ebean.find(Warehouse.class)
.fetch("officeZone")
.where().eq("id", wh.getId())
.findUnique();
// key assertion #1 - fails due to left join with discriminator in WHERE
Assert.assertNotNull(wh2);
// clear children to set the stage for left join failure
wh.getShippingZones().clear();
Ebean.save(wh);
wh2 = Ebean.find(Warehouse.class, wh.getId());
Assert.assertNotNull(wh2);
Assert.assertEquals(wh.getId(), wh2.getId());
Assert.assertEquals(0, wh.getShippingZones().size());
// query with lazy load of abstract children
wh = Ebean.find(Warehouse.class)
.where().eq("id", wh.getId())
.findUnique();
Assert.assertNotNull(wh);
Assert.assertEquals(wh.getId(), wh2.getId());
Assert.assertEquals(0, wh.getShippingZones().size());
// query with fetch of abstract children
wh = Ebean.find(Warehouse.class)
.fetch("shippingZones")
.where().eq("id", wh.getId())
.findUnique();
// key assertion #2 - fails due to left join with discriminator in WHERE
Assert.assertNotNull(wh);
Assert.assertEquals(wh.getId(), wh2.getId());
Assert.assertEquals(0, wh.getShippingZones().size());
}
}