From 230d18e48ffd96157865743faa34a391461b7726 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20Bucht=C3=ADk?=
Date: Fri, 27 Jan 2023 11:39:37 +0100
Subject: [PATCH 1/5] failing test for rawSql select .asDto query
---
.../tests/rawsql/TestRawSqlQuerySelect.java | 42 +++++++++++++++++++
.../rawsql/transport/QuerySumResponse.java | 30 +++++++++++++
.../tests/rawsql/transport/SampleReport.java | 12 ++++++
3 files changed, 84 insertions(+)
create mode 100644 ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java
create mode 100644 ebean-test/src/test/java/org/tests/rawsql/transport/QuerySumResponse.java
create mode 100644 ebean-test/src/test/java/org/tests/rawsql/transport/SampleReport.java
diff --git a/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java b/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java
new file mode 100644
index 000000000..029b1ec53
--- /dev/null
+++ b/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java
@@ -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.Test;
+import org.tests.model.basic.ResetBasicData;
+import org.tests.rawsql.transport.QuerySumResponse;
+import org.tests.rawsql.transport.SampleReport;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+
+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();
+
+ var query = DB.find(SampleReport.class);
+ query.setMaxRows(10);
+
+ List list = query.findList();
+ assertNotNull(list);
+
+ String sumSql = "COUNT(1)::Long AS count, SUM(id) AS sum";
+
+ query.setRawSql(rawSql);
+ //query.select(sumSql);
+ query.select(FetchGroup.of(SampleReport.class, sumSql));
+
+ query.asDto(QuerySumResponse.class);
+ var countSum = query.findOneOrEmpty().orElseThrow();
+ //assertThat((countSum instanceof QuerySumResponse));
+ }
+}
diff --git a/ebean-test/src/test/java/org/tests/rawsql/transport/QuerySumResponse.java b/ebean-test/src/test/java/org/tests/rawsql/transport/QuerySumResponse.java
new file mode 100644
index 000000000..d6a61b6f5
--- /dev/null
+++ b/ebean-test/src/test/java/org/tests/rawsql/transport/QuerySumResponse.java
@@ -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;
+ }
+}
diff --git a/ebean-test/src/test/java/org/tests/rawsql/transport/SampleReport.java b/ebean-test/src/test/java/org/tests/rawsql/transport/SampleReport.java
new file mode 100644
index 000000000..a119896e8
--- /dev/null
+++ b/ebean-test/src/test/java/org/tests/rawsql/transport/SampleReport.java
@@ -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;
+}
From 6055a33dc8e2205938e2f02dffee8a952c568a03 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20Bucht=C3=ADk?=
Date: Fri, 27 Jan 2023 12:11:01 +0100
Subject: [PATCH 2/5] fix changes
---
.../src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java b/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java
index 029b1ec53..1ac19ff93 100644
--- a/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java
+++ b/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java
@@ -24,6 +24,7 @@ public class TestRawSqlQuerySelect extends BaseTestCase {
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();
var query = DB.find(SampleReport.class);
+ query.setRawSql(rawSql);
query.setMaxRows(10);
List list = query.findList();
@@ -31,11 +32,10 @@ public class TestRawSqlQuerySelect extends BaseTestCase {
String sumSql = "COUNT(1)::Long AS count, SUM(id) AS sum";
- query.setRawSql(rawSql);
//query.select(sumSql);
query.select(FetchGroup.of(SampleReport.class, sumSql));
-
query.asDto(QuerySumResponse.class);
+
var countSum = query.findOneOrEmpty().orElseThrow();
//assertThat((countSum instanceof QuerySumResponse));
}
From 01a0cee3c213a0d3043730ad4e482809a6e46cc6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20Bucht=C3=ADk?=
Date: Fri, 10 Feb 2023 12:17:40 +0100
Subject: [PATCH 3/5] patch RawSql query builder, fix tests
---
.../server/query/CQueryBuilderRawSql.java | 15 +++++++++++-
.../tests/rawsql/TestRawSqlQuerySelect.java | 24 +++++++++----------
2 files changed, 26 insertions(+), 13 deletions(-)
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilderRawSql.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilderRawSql.java
index 290b706c2..812a13202 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilderRawSql.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilderRawSql.java
@@ -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.replace("::Long", "::BIGINT"));
+ first = false;
+ }
+ } else {
+ sb.append(sql.getPreFrom());
+ }
sb.append(" ");
String s = sql.getPreWhere();
diff --git a/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java b/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java
index 1ac19ff93..7732fa5e6 100644
--- a/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java
+++ b/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlQuerySelect.java
@@ -5,6 +5,7 @@ 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;
@@ -12,8 +13,6 @@ import org.tests.rawsql.transport.SampleReport;
import java.util.List;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
-
public class TestRawSqlQuerySelect extends BaseTestCase {
@Test
@@ -22,21 +21,22 @@ public class TestRawSqlQuerySelect extends BaseTestCase {
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 list = query.findList();
- assertNotNull(list);
+ Assertions.assertNotNull(list);
+ Assertions.assertTrue(!list.isEmpty() && list.size() < 11);
- String sumSql = "COUNT(1)::Long AS count, SUM(id) AS sum";
-
- //query.select(sumSql);
- query.select(FetchGroup.of(SampleReport.class, sumSql));
- query.asDto(QuerySumResponse.class);
-
- var countSum = query.findOneOrEmpty().orElseThrow();
- //assertThat((countSum instanceof QuerySumResponse));
+ 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);
}
}
From 1af3d0bcf3e755825ca02360b94309fb9b68308d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michal=20Bucht=C3=ADk?=
Date: Fri, 10 Feb 2023 12:27:10 +0100
Subject: [PATCH 4/5] remove unnecessary replace
---
.../java/io/ebeaninternal/server/query/CQueryBuilderRawSql.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilderRawSql.java b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilderRawSql.java
index 812a13202..2963d979d 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilderRawSql.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/query/CQueryBuilderRawSql.java
@@ -64,7 +64,7 @@ final class CQueryBuilderRawSql {
if (!first) {
sb.append(", ");
}
- sb.append(selectProperty.replace("::Long", "::BIGINT"));
+ sb.append(selectProperty);
first = false;
}
} else {
From 523fe6ae5493efea5f240b926b7f1edca33161c3 Mon Sep 17 00:00:00 2001
From: Rob Bygrave
Date: Fri, 10 Mar 2023 20:31:54 +1300
Subject: [PATCH 5/5] #2946 - Support specify select clause for RawSql
---
.../server/querydefn/DefaultOrmQuery.java | 15 ++++++--
.../ebeaninternal/server/rawsql/DRawSql.java | 4 ++
.../server/rawsql/SpiRawSql.java | 15 ++++----
.../org/tests/rawsql/TestRawSqlOrmQuery.java | 38 ++++++++++++++++---
4 files changed, 54 insertions(+), 18 deletions(-)
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java
index 075dbaa76..e9822ec26 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/querydefn/DefaultOrmQuery.java
@@ -591,10 +591,17 @@ public class DefaultOrmQuery extends AbstractQuery implements SpiQuery {
*/
@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
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/DRawSql.java b/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/DRawSql.java
index c58b8bc11..6d17f7270 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/DRawSql.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/DRawSql.java
@@ -60,4 +60,8 @@ public final class DRawSql implements SpiRawSql {
return columnMapping;
}
+ @Override
+ public String mapToColumn(String property) {
+ return columnMapping.mapToColumn(property);
+ }
}
diff --git a/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/SpiRawSql.java b/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/SpiRawSql.java
index d38f600ee..d54a296e5 100644
--- a/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/SpiRawSql.java
+++ b/ebean-core/src/main/java/io/ebeaninternal/server/rawsql/SpiRawSql.java
@@ -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 {
*
*/
public void tableAliasMapping(String tableAlias, String path) {
-
String startMatch = tableAlias + ".";
for (Map.Entry 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).
*/
diff --git a/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java b/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java
index 441100133..280969cdf 100644
--- a/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java
+++ b/ebean-test/src/test/java/org/tests/rawsql/TestRawSqlOrmQuery.java
@@ -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());
Listsql = 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 query = DB.find(Customer.class);
+ query.setRawSql(rawSql);
+ query.where().ilike("name", "r%").orderBy("name");
+
+ LoggedSql.start();
+ List list = query.findList();
+ assertNotNull(list);
+
+ // check also select count(*)
+ assertThat(query.findCount()).isEqualTo(list.size());
+ Listsql = 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();
Listsql = 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();
Listsql = 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");
}