diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/expression/RawExpression.java b/ebean-core/src/main/java/io/ebeaninternal/server/expression/RawExpression.java index afe6572a8..db64b2ea7 100644 --- a/ebean-core/src/main/java/io/ebeaninternal/server/expression/RawExpression.java +++ b/ebean-core/src/main/java/io/ebeaninternal/server/expression/RawExpression.java @@ -2,6 +2,9 @@ package io.ebeaninternal.server.expression; import io.ebeaninternal.api.*; import io.ebeaninternal.server.deploy.BeanDescriptor; +import io.ebeaninternal.server.deploy.BeanProperty; +import io.ebeaninternal.server.deploy.BeanPropertyAssoc; +import io.ebeaninternal.server.deploy.DeployPropertyParser; import io.ebeaninternal.server.persist.MultiValueWrapper; import java.io.IOException; @@ -11,6 +14,7 @@ final class RawExpression extends NonPrepareExpression { final String sql; final Object[] values; + private String prefixPath; RawExpression(String sql, Object[] values) { this.sql = sql; @@ -51,9 +55,39 @@ final class RawExpression extends NonPrepareExpression { } } + @Override + public void prefixProperty(String path) { + this.prefixPath = path; + } + @Override public void addSql(SpiExpressionRequest request) { - request.parse(sql); + if (prefixPath == null) { + request.parse(sql); + } else { + BeanDescriptor descriptor = request.descriptor(); + BeanProperty beanProperty = descriptor.findPropertyFromPath(prefixPath); + BeanPropertyAssoc bpa = (BeanPropertyAssoc)beanProperty; + DeployPropertyParser parser = bpa.targetDescriptor().parser(); + request.append(filterManyPaths(prefixPath, parser.parse(sql))); + } + } + + + static String filterManyPaths(String prefix, String raw) { + final StringBuilder sb = new StringBuilder(raw.length() + 50); + int lastPos = 0; + int nextPos = raw.indexOf("${"); + while (nextPos > -1) { + sb.append(raw.substring(lastPos, nextPos)).append("${").append(prefix); + if (raw.charAt(nextPos + 2) != '}') { + sb.append('.'); + } + lastPos = nextPos + 2; + nextPos = raw.indexOf("${", nextPos + 2); + } + sb.append(raw.substring(lastPos)); + return sb.toString(); } /** diff --git a/ebean-core/src/test/java/io/ebeaninternal/server/expression/RawExpressionTest.java b/ebean-core/src/test/java/io/ebeaninternal/server/expression/RawExpressionTest.java index c87e46c47..47d550b15 100644 --- a/ebean-core/src/test/java/io/ebeaninternal/server/expression/RawExpressionTest.java +++ b/ebean-core/src/test/java/io/ebeaninternal/server/expression/RawExpressionTest.java @@ -74,4 +74,22 @@ public class RawExpressionTest extends BaseExpressionTest { query.queryBindKey(bindValuesKey); return bindValuesKey; } + + @Test + void filterManyPaths_one() { + String result = RawExpression.filterManyPaths("contacts", "${}first is not null"); + assertThat(result).isEqualTo("${contacts}first is not null"); + } + + @Test + void filterManyPaths_nested() { + String result = RawExpression.filterManyPaths("contacts", "${address}city"); + assertThat(result).isEqualTo("${contacts.address}city"); + } + + @Test + void filterManyPaths_2() { + String result = RawExpression.filterManyPaths("contacts", "${}first ${}last"); + assertThat(result).isEqualTo("${contacts}first ${contacts}last"); + } } diff --git a/ebean-test/src/test/java/org/tests/query/TestQueryFilterMany.java b/ebean-test/src/test/java/org/tests/query/TestQueryFilterMany.java index 75d158c88..dffe3a72e 100644 --- a/ebean-test/src/test/java/org/tests/query/TestQueryFilterMany.java +++ b/ebean-test/src/test/java/org/tests/query/TestQueryFilterMany.java @@ -134,18 +134,40 @@ public class TestQueryFilterMany extends BaseTestCase { } @Test - public void test_with_findOne() { - + public void test_with_findOne_rawSeparateQuery() { ResetBasicData.reset(); + LoggedSql.start(); Customer customer = DB.find(Customer.class) .setMaxRows(1) .order().asc("id") .fetch("orders") - .filterMany("orders").raw("1 = 0") + .filterMany("orders").raw("orderDate is not null") .findOne(); assertThat(customer).isNotNull(); + List sql = LoggedSql.stop(); + assertThat(sql).hasSize(2); + assertThat(sql.get(0)).contains("from o_customer t0 order by"); + assertThat(sql.get(1)).contains("from o_order t0 join o_customer t1 on t1.id = t0.kcustomer_id where"); + } + + @Test + public void test_with_findOne_rawSameQuery() { + ResetBasicData.reset(); + + LoggedSql.start(); + var result = DB.find(Customer.class) + .order().asc("id") + .fetch("orders") + .filterMany("orders").raw("orderDate is not null") + .findList(); + + assertThat(result).isNotEmpty(); + List sql = LoggedSql.stop(); + assertThat(sql).hasSize(1); + assertThat(sql.get(0)).contains("from o_customer t0 left join o_order t1"); + assertThat(sql.get(0)).contains("where t1.order_date is not null"); } @Test