mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
FIX for filterMany with raw expression with single SQL query
Fix for the case where the filterMany is not executed on a separate
query but instead part of the origin query.
The fix is to use the appropriate DeployParser and also fix the path
alias like ${} -> ${contacts}
This commit is contained in:
@@ -10,6 +10,7 @@ import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.deploy.BeanPropertyAssocMany;
|
||||
import io.ebeaninternal.server.deploy.DeployParser;
|
||||
import io.ebeaninternal.server.deploy.DeployPropertyParser;
|
||||
import io.ebeaninternal.server.expression.DefaultExpressionRequest;
|
||||
import io.ebeaninternal.server.persist.Binder;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
@@ -198,9 +199,10 @@ public final class CQueryPredicates {
|
||||
OrmQueryProperties chunk = query.detail().getChunk(manyProperty.name(), false);
|
||||
SpiExpressionList<?> filterManyExpr = chunk.getFilterMany();
|
||||
if (filterManyExpr != null) {
|
||||
this.filterMany = new DefaultExpressionRequest(request, deployParser, binder, filterManyExpr);
|
||||
DeployPropertyParser parser = manyProperty.targetDescriptor().parser();
|
||||
this.filterMany = new DefaultExpressionRequest(request, parser, binder, filterManyExpr);
|
||||
if (buildSql) {
|
||||
dbFilterMany = filterMany.buildSql();
|
||||
dbFilterMany = filterManyPaths(manyProperty.name(), filterMany.buildSql());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -216,6 +218,22 @@ public final class CQueryPredicates {
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the table alias place-holders.
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package io.ebeaninternal.server.query;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
class CQueryPredicatesTest {
|
||||
|
||||
@Test
|
||||
void filterManyPaths_one() {
|
||||
String result = CQueryPredicates.filterManyPaths("contacts", "${}first is not null");
|
||||
assertThat(result).isEqualTo("${contacts}first is not null");
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterManyPaths_nested() {
|
||||
String result = CQueryPredicates.filterManyPaths("contacts", "${address}city");
|
||||
assertThat(result).isEqualTo("${contacts.address}city");
|
||||
}
|
||||
|
||||
@Test
|
||||
void filterManyPaths_2() {
|
||||
String result = CQueryPredicates.filterManyPaths("contacts", "${}first ${}last");
|
||||
assertThat(result).isEqualTo("${contacts}first ${contacts}last");
|
||||
}
|
||||
}
|
||||
@@ -152,6 +152,24 @@ public class TestQueryFilterMany extends BaseTestCase {
|
||||
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<String> 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
|
||||
public void test_with_findOneOrEmpty() {
|
||||
|
||||
|
||||
Reference in New Issue
Block a user