mirror of
https://github.com/ebean-orm/ebean.git
synced 2024-04-21 10:51:47 +00:00
Merge pull request #2996 from ebean-orm/buchtajz-query_select_bugs
Add support for specifying select clause with RawSql
This commit is contained in:
@@ -8,6 +8,7 @@ import io.ebeaninternal.api.SpiQuery;
|
||||
import io.ebeaninternal.server.core.OrmQueryRequest;
|
||||
import io.ebeaninternal.server.deploy.BeanDescriptor;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryLimitRequest;
|
||||
import io.ebeaninternal.server.querydefn.OrmQueryProperties;
|
||||
import io.ebeaninternal.server.rawsql.SpiRawSql;
|
||||
import io.ebeaninternal.server.util.BindParamsParser;
|
||||
|
||||
@@ -56,7 +57,19 @@ final class CQueryBuilderRawSql {
|
||||
|
||||
private String buildMainQuery(String orderBy, OrmQueryRequest<?> request, CQueryPredicates predicates, SpiRawSql.Sql sql) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(sql.getPreFrom());
|
||||
OrmQueryProperties ormQueryProperties = request.query().getDetail().getChunk(null, false);
|
||||
if (ormQueryProperties.hasSelectClause()) {
|
||||
boolean first = true;
|
||||
for (String selectProperty : ormQueryProperties.getIncluded()) {
|
||||
if (!first) {
|
||||
sb.append(", ");
|
||||
}
|
||||
sb.append(selectProperty);
|
||||
first = false;
|
||||
}
|
||||
} else {
|
||||
sb.append(sql.getPreFrom());
|
||||
}
|
||||
sb.append(" ");
|
||||
|
||||
String s = sql.getPreWhere();
|
||||
|
||||
@@ -591,10 +591,17 @@ public class DefaultOrmQuery<T> extends AbstractQuery implements SpiQuery<T> {
|
||||
*/
|
||||
@Override
|
||||
public final void setSelectId() {
|
||||
// clear select and fetch joins
|
||||
detail.clear();
|
||||
select(beanDescriptor.idSelect());
|
||||
singleAttribute = true;
|
||||
if (rawSql != null) {
|
||||
String column = rawSql.mapToColumn(beanDescriptor.idSelect());
|
||||
if (column != null) {
|
||||
select(column);
|
||||
}
|
||||
} else {
|
||||
// clear select and fetch joins
|
||||
detail.clear();
|
||||
select(beanDescriptor.idSelect());
|
||||
singleAttribute = true;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -60,4 +60,8 @@ public final class DRawSql implements SpiRawSql {
|
||||
return columnMapping;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String mapToColumn(String property) {
|
||||
return columnMapping.mapToColumn(property);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,13 +5,7 @@ import io.ebean.util.CamelCaseHelper;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Internal service API for Raw Sql.
|
||||
@@ -31,6 +25,7 @@ public interface SpiRawSql extends RawSql {
|
||||
|
||||
SpiRawSql.ColumnMapping getColumnMapping();
|
||||
|
||||
String mapToColumn(String property);
|
||||
|
||||
/**
|
||||
* Represents the sql part of the query. For parsed RawSql the sql is broken
|
||||
@@ -363,7 +358,6 @@ public interface SpiRawSql extends RawSql {
|
||||
* </p>
|
||||
*/
|
||||
public void tableAliasMapping(String tableAlias, String path) {
|
||||
|
||||
String startMatch = tableAlias + ".";
|
||||
for (Map.Entry<String, Column> entry : dbColumnMap.entrySet()) {
|
||||
if (entry.getKey().startsWith(startMatch)) {
|
||||
@@ -372,6 +366,11 @@ public interface SpiRawSql extends RawSql {
|
||||
}
|
||||
}
|
||||
|
||||
public String mapToColumn(String property) {
|
||||
final var column = propertyColumnMap.get(property);
|
||||
return column == null ? null : column.getDbColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* A Column of the RawSql that is mapped to a bean property (or ignored).
|
||||
*/
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package org.tests.rawsql;
|
||||
|
||||
import io.ebean.*;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.xtest.IgnorePlatform;
|
||||
import io.ebean.annotation.Platform;
|
||||
import io.ebean.test.LoggedSql;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import io.ebean.xtest.IgnorePlatform;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.Customer;
|
||||
import org.tests.model.basic.Order;
|
||||
@@ -21,7 +21,6 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
RawSql rawSql = RawSqlBuilder.parse("select r.id, r.name from o_customer r ")
|
||||
@@ -42,10 +41,37 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
|
||||
LoggedSql.start();
|
||||
assertThat(query.findCount()).isEqualTo(list.size());
|
||||
List<String>sql = LoggedSql.stop();
|
||||
assertThat(sql.get(0)).startsWith("select count(*) from ( select r.id, r.name from o_customer r");
|
||||
assertThat(sql.get(0)).startsWith("select count(*) from ( select r.id from o_customer r");
|
||||
assertThat(sql.get(0)).doesNotContain("order by");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFindCount_when_idPropertyNotMapped() {
|
||||
ResetBasicData.reset();
|
||||
|
||||
// mapping does not include the id column & property
|
||||
RawSql rawSql = RawSqlBuilder.parse("select r.name, r.status from o_customer r ")
|
||||
.columnMapping("r.name", "name")
|
||||
.columnMapping("r.status", "status")
|
||||
.create();
|
||||
|
||||
Query<Customer> query = DB.find(Customer.class);
|
||||
query.setRawSql(rawSql);
|
||||
query.where().ilike("name", "r%").orderBy("name");
|
||||
|
||||
LoggedSql.start();
|
||||
List<Customer> list = query.findList();
|
||||
assertNotNull(list);
|
||||
|
||||
// check also select count(*)
|
||||
assertThat(query.findCount()).isEqualTo(list.size());
|
||||
List<String>sql = LoggedSql.stop();
|
||||
assertThat(sql.get(0)).startsWith("select r.name, r.status from o_customer r where lower(r.name) like ?");
|
||||
assertThat(sql.get(0)).contains(" order by r.name");
|
||||
assertThat(sql.get(1)).startsWith("select count(*) from ( select r.name, r.status from o_customer r where lower(r.name) like ?");
|
||||
assertThat(sql.get(1)).doesNotContain("order by");
|
||||
}
|
||||
|
||||
@Test
|
||||
@IgnorePlatform({Platform.MYSQL, Platform.MARIADB, Platform.SQLSERVER})
|
||||
public void test_upperCaseSql() {
|
||||
@@ -158,7 +184,7 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
|
||||
LoggedSql.start();
|
||||
query.findCount();
|
||||
List<String>sql = LoggedSql.stop();
|
||||
assertThat(sql.get(0)).startsWith("select count(*) from ( select o.id, o.order_date, o.ship_date from o_order o");
|
||||
assertThat(sql.get(0)).startsWith("select count(*) from ( select o.id from o_order o");
|
||||
assertThat(sql.get(0)).doesNotContain("order by");
|
||||
}
|
||||
|
||||
@@ -193,7 +219,7 @@ public class TestRawSqlOrmQuery extends BaseTestCase {
|
||||
LoggedSql.start();
|
||||
query.findCount();
|
||||
List<String>sql = LoggedSql.stop();
|
||||
assertThat(sql.get(0)).startsWith("select count(*) from ( select o.id, o.order_date, o.ship_date from o_order o");
|
||||
assertThat(sql.get(0)).startsWith("select count(*) from ( select o.id from o_order o");
|
||||
assertThat(sql.get(0)).doesNotContain("order by");
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
package org.tests.rawsql;
|
||||
|
||||
import io.ebean.DB;
|
||||
import io.ebean.FetchGroup;
|
||||
import io.ebean.RawSql;
|
||||
import io.ebean.RawSqlBuilder;
|
||||
import io.ebean.xtest.BaseTestCase;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.tests.model.basic.ResetBasicData;
|
||||
import org.tests.rawsql.transport.QuerySumResponse;
|
||||
import org.tests.rawsql.transport.SampleReport;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TestRawSqlQuerySelect extends BaseTestCase {
|
||||
|
||||
@Test
|
||||
public void testRawSQL() {
|
||||
|
||||
ResetBasicData.reset();
|
||||
|
||||
RawSql rawSql = RawSqlBuilder.parse("select id, name, anniversary, city from (select c.id, c.name, c.anniversary, a.city from o_customer c left join o_address a ON a.id = c.billing_address_id order by c.id) w").create();
|
||||
String sumSql = "COUNT(1)::BIGINT AS count, SUM(id)::DOUBLE PRECISION AS sum";
|
||||
|
||||
var query = DB.find(SampleReport.class);
|
||||
query.setRawSql(rawSql);
|
||||
query.setMaxRows(10);
|
||||
List<SampleReport> list = query.findList();
|
||||
Assertions.assertNotNull(list);
|
||||
Assertions.assertTrue(!list.isEmpty() && list.size() < 11);
|
||||
|
||||
var countSum = DB.find(SampleReport.class)
|
||||
.setRawSql(rawSql)
|
||||
//.select(sumSql)
|
||||
.select(FetchGroup.of(SampleReport.class, sumSql))
|
||||
.setMaxRows(10)
|
||||
.asDto(QuerySumResponse.class)
|
||||
.findOne();
|
||||
Assertions.assertInstanceOf(QuerySumResponse.class, countSum);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.tests.rawsql.transport;
|
||||
|
||||
public class QuerySumResponse {
|
||||
private long count;
|
||||
private Double sum;
|
||||
|
||||
public QuerySumResponse() {
|
||||
}
|
||||
|
||||
public QuerySumResponse(long count, Double sum) {
|
||||
this.count = count;
|
||||
this.sum = sum;
|
||||
}
|
||||
|
||||
public long getCount() {
|
||||
return count;
|
||||
}
|
||||
|
||||
public void setCount(long count) {
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public Double getSum() {
|
||||
return sum;
|
||||
}
|
||||
|
||||
public void setSum(Double sum) {
|
||||
this.sum = sum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package org.tests.rawsql.transport;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import java.sql.Date;
|
||||
|
||||
@Entity
|
||||
public class SampleReport {
|
||||
Long id;
|
||||
String name;
|
||||
Date anniversary;
|
||||
String city;
|
||||
}
|
||||
Reference in New Issue
Block a user