-
-
Notifications
You must be signed in to change notification settings - Fork 269
M2M on child path produce wrong query on extra join #3653
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| package org.tests.basic; | ||
|
|
||
| import io.ebean.DB; | ||
| import io.ebean.Query; | ||
| import io.ebean.xtest.BaseTestCase; | ||
| import org.assertj.core.api.SoftAssertions; | ||
| import org.junit.jupiter.api.Test; | ||
| import org.tests.model.basic.Country; | ||
| import org.tests.model.basic.EBasic; | ||
| import org.tests.model.basic.OBeanChild; | ||
| import org.tests.model.basic.OCachedBean; | ||
| import org.tests.model.basic.ResetBasicData; | ||
|
|
||
| public class TestManyOnChildOfExtraJoin extends BaseTestCase { | ||
|
|
||
|
|
||
| @Test | ||
| public void test() { | ||
| ResetBasicData.reset(); | ||
|
|
||
| OCachedBean bean = new OCachedBean(); | ||
| bean.setName("m2m-with-sq"); | ||
| bean.getCountries().add(DB.reference(Country.class, "NZ")); | ||
| bean.getCountries().add(DB.reference(Country.class, "AU")); | ||
| DB.save(bean); | ||
|
|
||
| OBeanChild child = new OBeanChild(); | ||
| child.setCachedBean(bean); | ||
| DB.save(child); | ||
|
|
||
| EBasic b1 = new EBasic(); | ||
| b1.setName("Australia"); | ||
| b1.setStatus(EBasic.Status.ACTIVE); | ||
| DB.save(b1); | ||
|
|
||
| EBasic b2 = new EBasic(); | ||
| b2.setName("New Zealand"); | ||
| b2.setStatus(EBasic.Status.ACTIVE); | ||
| DB.save(b2); | ||
|
|
||
| Query<OBeanChild> query = DB.find(OBeanChild.class).where() | ||
| .eq("cachedBean.name", "m2m-with-sq") | ||
| .exists(DB.find(EBasic.class) | ||
| .alias("sq1") | ||
| .where() | ||
| .raw("cachedBean.countries.name = sq1.name") | ||
| .eq("status", EBasic.Status.ACTIVE) | ||
| .query()) | ||
| .query(); | ||
| SoftAssertions softly = new SoftAssertions(); | ||
| softly.assertThat(query.findList()).hasSize(1); | ||
| softly.assertThat(query.getGeneratedSql()).startsWith("select distinct"); | ||
| softly.assertAll(); | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -82,7 +82,7 @@ public void testOrderOnChainedFormulaProperty() { | |
| .orderBy().asc("order.totalAmount"); | ||
|
|
||
| shipQuery.findList(); | ||
| assertSql(shipQuery.getGeneratedSql()).isEqualTo("select t0.id " | ||
| assertSql(shipQuery.getGeneratedSql()).isEqualTo("select distinct t0.id, z_bt1.total_amount " | ||
| + "from or_order_ship t0 " | ||
| + "left join o_order t1 on t1.id = t0.order_id " | ||
| + "left join (select order_id, count(*) as total_items, sum(order_qty*unit_price) as total_amount from o_order_detail group by order_id) z_bt1 on z_bt1.order_id = t1.id " | ||
|
|
@@ -99,7 +99,7 @@ public void testWhereOnChainedFormulaProperty() { | |
| .where().isNotNull("order.totalAmount").query(); | ||
|
|
||
| shipQuery.findList(); | ||
| assertSql(shipQuery.getGeneratedSql()).isEqualTo("select t0.id " | ||
| assertSql(shipQuery.getGeneratedSql()).isEqualTo("select distinct t0.id " | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. --- new SQL (with distinct)
select distinct t0.id from or_order_ship t0
left join o_order t1 on t1.id = t0.order_id
left join (select order_id, count(*) as total_items, sum(order_qty*unit_price) as total_amount
from o_order_detail group by order_id) z_bt1 on z_bt1.order_id = t1.id
where z_bt1.total_amount is not null
-- old SQL (without distinct)
select t0.id from or_order_ship t0
left join o_order t1 on t1.id = t0.order_id
left join (select order_id, count(*) as total_items, sum(order_qty*unit_price) as total_amount
from o_order_detail group by order_id) z_bt1 on z_bt1.order_id = t1.id
where z_bt1.total_amount is not nullHere is also just a distinct added |
||
| + "from or_order_ship t0 " | ||
| + "left join o_order t1 on t1.id = t0.order_id " | ||
| + "left join (select order_id, count(*) as total_items, sum(order_qty*unit_price) as total_amount from o_order_detail group by order_id) z_bt1 on z_bt1.order_id = t1.id " | ||
|
|
@@ -313,7 +313,7 @@ public void test_ChildPersonParentFindIds() { | |
| List<String> loggedSql = LoggedSql.stop(); | ||
| assertEquals(1, loggedSql.size()); | ||
| assertThat(loggedSql.get(0)) | ||
| .contains("select t0.identifier from child_person t0") | ||
| .contains("select distinct t0.identifier from child_person t0") | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. -- new SQL (with distinct)
select distinct t0.identifier from child_person t0
left join parent_person t1 on t1.identifier = t0.parent_identifier
left join (select i2.parent_identifier, count(*) as child_count, sum(i2.age) as child_age
from child_person i2 group by i2.parent_identifier) f2 on f2.parent_identifier = t1.identifier
where coalesce(f2.child_age, 0) = ?
-- old SQL (without distinct)
select t0.identifier from child_person t0
left join parent_person t1 on t1.identifier = t0.parent_identifier
left join (select i2.parent_identifier, count(*) as child_count, sum(i2.age) as child_age
from child_person i2 group by i2.parent_identifier) f2 on f2.parent_identifier = t1.identifier
where coalesce(f2.child_age, 0) = ? |
||
| .contains("left join (select i2.parent_identifier") | ||
| .contains("where coalesce(f2.child_age, 0) = ?"); | ||
| } | ||
|
|
@@ -329,8 +329,8 @@ public void test_ChildPersonParentFindCount() { | |
|
|
||
| List<String> loggedSql = LoggedSql.stop(); | ||
| assertEquals(1, loggedSql.size()); | ||
| assertThat(loggedSql.get(0)).contains("select count(*) from child_person t0 left join parent_person t1 on t1.identifier = t0.parent_identifier"); | ||
| assertThat(loggedSql.get(0)).contains("where coalesce(f2.child_age, 0) = ?"); | ||
| assertThat(loggedSql.get(0)).contains("select count(*) from ( select distinct t0.identifier from child_person t0 left join parent_person t1 on t1.identifier = t0.parent_identifier"); | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. -- new SQL - with subquery & distinct
select count(*) from ( select distinct t0.identifier
from child_person t0
left join parent_person t1 on t1.identifier = t0.parent_identifier
left join (select i2.parent_identifier, count(*) as child_count, sum(i2.age) as child_age
from child_person i2 group by i2.parent_identifier) f2 on f2.parent_identifier = t1.identifier
where coalesce(f2.child_age, 0) = ?) -- subquery ends here
-- old SQL (same as above, but not wrapped in a subquery
select count(*) from child_person t0
left join parent_person t1 on t1.identifier = t0.parent_identifier
left join (select i2.parent_identifier, count(*) as child_count, sum(i2.age) as child_age
from child_person i2 group by i2.parent_identifier) f2 on f2.parent_identifier = t1.identifier
where coalesce(f2.child_age, 0) = ? |
||
| assertThat(loggedSql.get(0)).contains("where coalesce(f2.child_age, 0) = ?)"); | ||
| } | ||
|
|
||
| @Test | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem here is, that totalAmount is a
@Formulaproperty with join. And that join could be theoretically a M2MEbean generates a
SqlTreeNodeFormulaWhereJoinhere, which always returns true forhasMany()