diff --git a/extensions/panache/panache-hibernate-common/runtime/src/main/java/io/quarkus/panache/hibernate/common/runtime/PanacheJpaUtil.java b/extensions/panache/panache-hibernate-common/runtime/src/main/java/io/quarkus/panache/hibernate/common/runtime/PanacheJpaUtil.java index 3f1c2d22752d7..3029a33398242 100644 --- a/extensions/panache/panache-hibernate-common/runtime/src/main/java/io/quarkus/panache/hibernate/common/runtime/PanacheJpaUtil.java +++ b/extensions/panache/panache-hibernate-common/runtime/src/main/java/io/quarkus/panache/hibernate/common/runtime/PanacheJpaUtil.java @@ -61,7 +61,7 @@ public static String createFindQuery(Class entityClass, String query, int par return "FROM " + getEntityName(entityClass); } - String trimmed = query.trim(); + String trimmed = query.replace('\n', ' ').replace('\r', ' ').trim(); if (trimmed.isEmpty()) { return "FROM " + getEntityName(entityClass); } diff --git a/integration-tests/hibernate-orm-panache-kotlin/src/main/kotlin/io/quarkus/it/panache/kotlin/TestEndpoint.kt b/integration-tests/hibernate-orm-panache-kotlin/src/main/kotlin/io/quarkus/it/panache/kotlin/TestEndpoint.kt index fa1bb50df7c41..42ff7b0990706 100644 --- a/integration-tests/hibernate-orm-panache-kotlin/src/main/kotlin/io/quarkus/it/panache/kotlin/TestEndpoint.kt +++ b/integration-tests/hibernate-orm-panache-kotlin/src/main/kotlin/io/quarkus/it/panache/kotlin/TestEndpoint.kt @@ -5,6 +5,7 @@ import io.quarkus.panache.common.Page import io.quarkus.panache.common.Parameters import io.quarkus.panache.common.Sort import io.quarkus.panache.common.exception.PanacheQueryException +import io.quarkus.runtime.annotations.RegisterForReflection import jakarta.inject.Inject import jakarta.persistence.LockModeType import jakarta.persistence.NoResultException @@ -1091,4 +1092,47 @@ class TestEndpoint { return "OK" } + + @GET + @Path("project") + @Transactional + fun testProject(): String { + @RegisterForReflection + data class MyProjection( + val projectedName: String + ) + + val mark = Person() + mark.name = "Mark" + mark.persistAndFlush() + + val hqlWithoutSpace = """ + select + name as projectedName + from + io.quarkus.it.panache.kotlin.Person + where + name = ?1 + """.trimIndent() + val withoutSpace = Person.find(hqlWithoutSpace, "Mark").project(MyProjection::class.java).firstResult() + Assertions.assertNotNull(withoutSpace) + Assertions.assertEquals(mark.name, withoutSpace?.projectedName) + + // There is a space behind "select " + val hqlWithSpace = """ + select + name as projectedName + from + io.quarkus.it.panache.kotlin.Person + where + name = ?1 + """.trimIndent() + val withSpace = Person.find(hqlWithSpace, "Mark").project(MyProjection::class.java).firstResult() + Assertions.assertNotNull(withSpace) + Assertions.assertEquals(mark.name, withSpace?.projectedName) + + Person.deleteAll() + + return "OK" + } } diff --git a/integration-tests/hibernate-orm-panache-kotlin/src/test/kotlin/io/quarkus/it/panache/ProjectionTest.kt b/integration-tests/hibernate-orm-panache-kotlin/src/test/kotlin/io/quarkus/it/panache/ProjectionTest.kt new file mode 100644 index 0000000000000..bdacd91f12281 --- /dev/null +++ b/integration-tests/hibernate-orm-panache-kotlin/src/test/kotlin/io/quarkus/it/panache/ProjectionTest.kt @@ -0,0 +1,21 @@ +package io.quarkus.it.panache + +import io.quarkus.test.junit.QuarkusIntegrationTest +import io.quarkus.test.junit.QuarkusTest +import io.restassured.RestAssured +import org.hamcrest.Matchers +import org.junit.jupiter.api.Test + +// Native tests +@QuarkusIntegrationTest +class ProjectionIT : ProjectionTest() + +// Quarkus/JVM tests +@QuarkusTest +open class ProjectionTest { + + @Test + fun testProject() { + RestAssured.`when`()["/test/project"].then().body(Matchers.`is`("OK")) + } +} diff --git a/integration-tests/java-17/src/main/java/io/quarkus/it/hibernate/panache/person/PersonResource.java b/integration-tests/java-17/src/main/java/io/quarkus/it/hibernate/panache/person/PersonResource.java index 2744c1b059654..0bf2c3756bae0 100644 --- a/integration-tests/java-17/src/main/java/io/quarkus/it/hibernate/panache/person/PersonResource.java +++ b/integration-tests/java-17/src/main/java/io/quarkus/it/hibernate/panache/person/PersonResource.java @@ -1,6 +1,7 @@ package io.quarkus.it.hibernate.panache.person; import java.net.URI; +import java.util.Arrays; import java.util.List; import jakarta.transaction.Transactional; @@ -24,4 +25,39 @@ public Response addPerson(Person person) { return Response.created(URI.create("/persons/entity/" + id)).build(); } + + @GET + @Path("hql-project") + @Transactional + public Response testPanacheHqlProject() { + var mark = new Person(); + mark.firstname = "Mark"; + mark.lastname = "Mark"; + mark.persistAndFlush(); + + var hqlWithoutSpace = """ + select + firstname, + lastname + from + io.quarkus.it.hibernate.panache.person.Person + where + firstname = ?1 + """; + var persistedWithoutSpace = Person.find(hqlWithoutSpace, "Mark").project(PersonName.class).firstResult(); + + // We need to escape the whitespace in Java otherwise the compiler removes it. + var hqlWithSpace = """ + select\s + firstname, + lastname + from + io.quarkus.it.hibernate.panache.person.Person + where + firstname = ?1 + """; + var persistedWithSpace = Person.find(hqlWithSpace, "Mark").project(PersonName.class).firstResult(); + + return Response.ok(Arrays.asList(persistedWithoutSpace, persistedWithSpace)).build(); + } } diff --git a/integration-tests/java-17/src/test/java/io/quarkus/it/hibernate/panache/person/PersonResourceTest.java b/integration-tests/java-17/src/test/java/io/quarkus/it/hibernate/panache/person/PersonResourceTest.java index b90e972c9dfc0..bbc5a7df07ac9 100644 --- a/integration-tests/java-17/src/test/java/io/quarkus/it/hibernate/panache/person/PersonResourceTest.java +++ b/integration-tests/java-17/src/test/java/io/quarkus/it/hibernate/panache/person/PersonResourceTest.java @@ -4,6 +4,7 @@ import static io.restassured.RestAssured.when; import static org.hamcrest.CoreMatchers.is; +import io.quarkus.test.TestTransaction; import org.junit.jupiter.api.Test; import io.quarkus.it.mongodb.panache.person.Person; @@ -19,6 +20,7 @@ class PersonResourceTest { private static final String ROOT_URL = "/hibernate/persons"; @Test + @TestTransaction void testRecordInPanache() { var person1 = new Person(); person1.firstname = "Loïc"; @@ -42,4 +44,11 @@ void testRecordInPanache() { .body("size()", is(2)); } + @Test + @TestTransaction + void testHqlPanacheProject() { + when().get(ROOT_URL + "/hql-project") + .then().statusCode(200) + .body("size()", is(2)); + } }