Merge pull request #3171 from ebean-orm/feature/filterMany-raw-expression

FIX for filterMany with raw expression with single SQL query
This commit is contained in:
Rob Bygrave
2023-08-21 09:39:40 +12:00
committed by GitHub
3 changed files with 78 additions and 4 deletions
@@ -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();
}
/**
@@ -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");
}
}
@@ -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<String> 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<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