diff --git a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 index 8ced23f28..fab6d9a07 100644 --- a/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 +++ b/spring-data-jpa/src/main/antlr4/org/springframework/data/jpa/repository/query/Hql.g4 @@ -112,15 +112,11 @@ joinSpecifier ; fromRoot - : entityName variable? - | LATERAL? '(' subquery ')' variable? - | functionCallAsFromSource variable? + : entityName variable? # RootEntity + | LATERAL? '(' subquery ')' variable? # RootSubquery + | setReturningFunction variable? # RootFunction ; -functionCallAsFromSource - : identifier '(' (expression (',' expression)*)? ')' - ; - join : joinType JOIN FETCH? joinTarget joinRestriction? // Spec BNF says joinType isn't optional, but text says that it is. ; @@ -128,11 +124,7 @@ join joinTarget : path variable? # JoinPath | LATERAL? '(' subquery ')' variable? # JoinSubquery - | functionCallAsJoinTarget variable? # JoinFunctionCall - ; - -functionCallAsJoinTarget - : identifier '(' (expression (',' expression)*)? ')' + | setReturningFunction variable? # JoinFunctionCall ; // https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-update @@ -768,6 +760,14 @@ function | genericFunction # GenericFunctionInvocation ; +setReturningFunction + : simpleSetReturningFunction + ; + +simpleSetReturningFunction + : identifier '(' genericFunctionArguments? ')' + ; + /** * Any function with an irregular syntax for the argument list * @@ -1888,4 +1888,4 @@ ESCAPE_SEQUENCE QUOTED_IDENTIFIER : BACKTICK ( ESCAPE_SEQUENCE | '\\' BACKTICK | ~([`]) )* BACKTICK - ; \ No newline at end of file + ; diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HibernateQueryInformation.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HibernateQueryInformation.java index fd77f0ea9..e1ea9173d 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HibernateQueryInformation.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HibernateQueryInformation.java @@ -23,7 +23,7 @@ import org.jspecify.annotations.Nullable; * Hibernate-specific query details capturing common table expression details. * * @author Mark Paluch - * @author oscar.fanchin + * @author Oscar Fanchin * @since 3.5 */ class HibernateQueryInformation extends QueryInformation { diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java index 3a85c5912..e35b71258 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlCountQueryTransformer.java @@ -30,7 +30,7 @@ import org.springframework.data.jpa.repository.query.QueryTransformers.CountSele * @author Greg Turnquist * @author Christoph Strobl * @author Mark Paluch - * @author oscar.fanchin + * @author Oscar Fanchin * @since 3.1 */ @SuppressWarnings("ConstantValue") @@ -113,7 +113,6 @@ class HqlCountQueryTransformer extends HqlQueryRenderer { } } - if (ctx.whereClause() != null) { builder.appendExpression(visit(ctx.whereClause())); } @@ -133,48 +132,6 @@ class HqlCountQueryTransformer extends HqlQueryRenderer { return builder; } - @Override - public QueryRendererBuilder visitFromRoot(HqlParser.FromRootContext ctx) { - - QueryRendererBuilder builder = QueryRenderer.builder(); - - if (ctx.entityName() != null) { - - builder.appendExpression(visit(ctx.entityName())); - - if (ctx.variable() != null) { - builder.appendExpression(visit(ctx.variable())); - } - } else if (ctx.subquery() != null) { - - if (ctx.LATERAL() != null) { - builder.append(QueryTokens.expression(ctx.LATERAL())); - } - - QueryRendererBuilder nested = QueryRenderer.builder(); - - nested.append(TOKEN_OPEN_PAREN); - nested.appendInline(visit(ctx.subquery())); - nested.append(TOKEN_CLOSE_PAREN); - - builder.appendExpression(nested); - - if (ctx.variable() != null) { - builder.appendExpression(visit(ctx.variable())); - } - } else if (ctx.functionCallAsFromSource() != null) { - - builder.appendExpression(visit(ctx.functionCallAsFromSource())); - - if (ctx.variable() != null) { - builder.appendExpression(visit(ctx.variable())); - } - } - - - return builder; - } - @Override public QueryRendererBuilder visitJoin(HqlParser.JoinContext ctx) { @@ -193,6 +150,7 @@ class HqlCountQueryTransformer extends HqlQueryRenderer { return builder; } + @Override public QueryTokenStream visitSelectClause(HqlParser.SelectClauseContext ctx) { diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryIntrospector.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryIntrospector.java index 3c3f4b29e..ba88ab2df 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryIntrospector.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryIntrospector.java @@ -21,15 +21,15 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -import org.springframework.data.jpa.repository.query.HqlParser.VariableContext; - import org.jspecify.annotations.Nullable; +import org.springframework.data.jpa.repository.query.HqlParser.VariableContext; + /** * {@link ParsedQueryIntrospector} for HQL queries. * * @author Mark Paluch - * @author oscar.fanchin + * @author Oscar Fanchin */ @SuppressWarnings({ "UnreachableCode", "ConstantValue" }) class HqlQueryIntrospector extends HqlBaseVisitor implements ParsedQueryIntrospector { @@ -52,9 +52,9 @@ class HqlQueryIntrospector extends HqlBaseVisitor implements ParsedQueryIn @Override public Void visitSelectClause(HqlParser.SelectClauseContext ctx) { - if (!projectionProcessed) { - projection = captureSelectItems(ctx.selectionList().selection(), renderer); - projectionProcessed = true; + if (!this.projectionProcessed) { + this.projection = captureSelectItems(ctx.selectionList().selection(), renderer); + this.projectionProcessed = true; } return super.visitSelectClause(ctx); @@ -65,21 +65,36 @@ class HqlQueryIntrospector extends HqlBaseVisitor implements ParsedQueryIn this.hasCte = true; return super.visitCte(ctx); } - + @Override - public Void visitFunctionCallAsFromSource(HqlParser.FunctionCallAsFromSourceContext ctx) { - this.hasFromFunction = true; - return super.visitFunctionCallAsFromSource(ctx); + public Void visitRootEntity(HqlParser.RootEntityContext ctx) { + + if (this.primaryFromAlias == null && ctx.variable() != null && !HqlQueryRenderer.isSubquery(ctx)) { + this.primaryFromAlias = capturePrimaryAlias(ctx.variable()); + } + + return super.visitRootEntity(ctx); } @Override - public Void visitFromRoot(HqlParser.FromRootContext ctx) { + public Void visitRootSubquery(HqlParser.RootSubqueryContext ctx) { - if (primaryFromAlias == null && ctx.variable() != null && !HqlQueryRenderer.isSubquery(ctx)) { - primaryFromAlias = capturePrimaryAlias(ctx.variable()); + if (this.primaryFromAlias == null && ctx.variable() != null && !HqlQueryRenderer.isSubquery(ctx)) { + this.primaryFromAlias = capturePrimaryAlias(ctx.variable()); } - return super.visitFromRoot(ctx); + return super.visitRootSubquery(ctx); + } + + @Override + public Void visitRootFunction(HqlParser.RootFunctionContext ctx) { + + if (this.primaryFromAlias == null && ctx.variable() != null && !HqlQueryRenderer.isSubquery(ctx)) { + this.primaryFromAlias = capturePrimaryAlias(ctx.variable()); + this.hasFromFunction = true; + } + + return super.visitRootFunction(ctx); } @Override diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java index a6b3dd4ca..01557b33d 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlQueryRenderer.java @@ -64,24 +64,6 @@ class HqlQueryRenderer extends HqlBaseVisitor { return visit(ctx.ql_statement()); } - @Override - public QueryTokenStream visitFunctionCallAsFromSource(HqlParser.FunctionCallAsFromSourceContext ctx) { - - QueryRendererBuilder builder = QueryRenderer.builder(); - - builder.append(visit(ctx.identifier())); - - builder.append(TOKEN_OPEN_PAREN); - - if (!ctx.expression().isEmpty()) { - builder.append(QueryTokenStream.concatExpressions(ctx.expression(), this::visit, TOKEN_COMMA)); - } - - builder.append(TOKEN_CLOSE_PAREN); - - return builder; - } - @Override public QueryTokenStream visitQl_statement(HqlParser.Ql_statementContext ctx) { @@ -369,48 +351,78 @@ class HqlQueryRenderer extends HqlBaseVisitor { } @Override - public QueryTokenStream visitFromRoot(HqlParser.FromRootContext ctx) { + public QueryTokenStream visitRootEntity(HqlParser.RootEntityContext ctx) { QueryRendererBuilder builder = QueryRenderer.builder(); - if (ctx.entityName() != null) { + builder.appendExpression(visit(ctx.entityName())); - builder.appendExpression(visit(ctx.entityName())); - - if (ctx.variable() != null) { - builder.appendExpression(visit(ctx.variable())); - } - - } else if (ctx.subquery() != null) { - - if (ctx.LATERAL() != null) { - builder.append(QueryTokens.expression(ctx.LATERAL())); - } - - QueryRendererBuilder nested = QueryRenderer.builder(); - - nested.append(TOKEN_OPEN_PAREN); - nested.appendInline(visit(ctx.subquery())); - nested.append(TOKEN_CLOSE_PAREN); - - builder.appendExpression(nested); - - if (ctx.variable() != null) { - builder.appendExpression(visit(ctx.variable())); - } - - } else if (ctx.functionCallAsFromSource() != null) { - - builder.appendExpression(visit(ctx.functionCallAsFromSource())); - - if (ctx.variable() != null) { - builder.appendExpression(visit(ctx.variable())); - } + if (ctx.variable() != null) { + builder.appendExpression(visit(ctx.variable())); } return builder; } + @Override + public QueryTokenStream visitRootSubquery(HqlParser.RootSubqueryContext ctx) { + + QueryRendererBuilder builder = QueryRenderer.builder(); + + if (ctx.LATERAL() != null) { + builder.append(QueryTokens.expression(ctx.LATERAL())); + } + + QueryRendererBuilder nested = QueryRenderer.builder(); + + nested.append(TOKEN_OPEN_PAREN); + nested.appendInline(visit(ctx.subquery())); + nested.append(TOKEN_CLOSE_PAREN); + + builder.appendExpression(nested); + + if (ctx.variable() != null) { + builder.appendExpression(visit(ctx.variable())); + } + + return builder; + } + + @Override + public QueryTokenStream visitRootFunction(HqlParser.RootFunctionContext ctx) { + + QueryRendererBuilder builder = QueryRenderer.builder(); + + builder.appendExpression(visit(ctx.setReturningFunction())); + + if (ctx.variable() != null) { + builder.appendExpression(visit(ctx.variable())); + } + + return builder; + } + + @Override + public QueryTokenStream visitSetReturningFunction(HqlParser.SetReturningFunctionContext ctx) { + return visit(ctx.simpleSetReturningFunction()); + } + + @Override + public QueryTokenStream visitSimpleSetReturningFunction(HqlParser.SimpleSetReturningFunctionContext ctx) { + + QueryRendererBuilder builder = QueryRenderer.builder(); + + builder.append(visit(ctx.identifier())); + + builder.append(TOKEN_OPEN_PAREN); + if (ctx.genericFunctionArguments() != null) { + builder.append(visit(ctx.genericFunctionArguments())); + } + builder.append(TOKEN_CLOSE_PAREN); + + return builder; + } + @Override public QueryTokenStream visitJoin(HqlParser.JoinContext ctx) { @@ -459,7 +471,7 @@ class HqlQueryRenderer extends HqlBaseVisitor { } builder.append(TOKEN_OPEN_PAREN); - builder.append(visit(ctx.subquery())); + builder.appendInline(visit(ctx.subquery())); builder.append(TOKEN_CLOSE_PAREN); if (ctx.variable() != null) { @@ -474,7 +486,7 @@ class HqlQueryRenderer extends HqlBaseVisitor { QueryRendererBuilder builder = QueryRenderer.builder(); - builder.append(visit(ctx.functionCallAsJoinTarget())); + builder.append(visit(ctx.setReturningFunction())); if (ctx.variable() != null) { builder.appendExpression(visit(ctx.variable())); @@ -484,24 +496,6 @@ class HqlQueryRenderer extends HqlBaseVisitor { } - @Override - public QueryTokenStream visitFunctionCallAsJoinTarget(HqlParser.FunctionCallAsJoinTargetContext ctx) { - - QueryRendererBuilder builder = QueryRenderer.builder(); - - builder.append(visit(ctx.identifier())); - - builder.append(TOKEN_OPEN_PAREN); - - if (!ctx.expression().isEmpty()) { - builder.append(QueryTokenStream.concatExpressions(ctx.expression(), this::visit, TOKEN_COMMA)); - } - - builder.append(TOKEN_CLOSE_PAREN); - - return builder; - } - @Override public QueryTokenStream visitUpdateStatement(HqlParser.UpdateStatementContext ctx) { diff --git a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlSortedQueryTransformer.java b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlSortedQueryTransformer.java index 45074e5a4..175e918c8 100644 --- a/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlSortedQueryTransformer.java +++ b/spring-data-jpa/src/main/java/org/springframework/data/jpa/repository/query/HqlSortedQueryTransformer.java @@ -32,7 +32,7 @@ import org.springframework.util.ObjectUtils; * * @author Greg Turnquist * @author Christoph Strobl - * @author oscar.fanchin + * @author Oscar Fanchin * @since 3.1 */ @SuppressWarnings("ConstantValue") diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java index a557af1d4..040c632df 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryRendererTests.java @@ -5,7 +5,7 @@ * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * - * https://www.apache.org/licenses/LICENSE-2.0 + *https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, @@ -36,7 +36,7 @@ import org.junit.jupiter.params.provider.ValueSource; * @author Christoph Strobl * @author Mark Paluch * @author Yannick Brandt - * @author oscar.fanchin + * @author Oscar Fanchin * @since 3.1 */ class HqlQueryRendererTests { @@ -608,8 +608,8 @@ class HqlQueryRendererTests { SELECT DISTINCT emp FROM Employee emp WHERE EXISTS (SELECT spouseEmp - FROM Employee spouseEmp - WHERE spouseEmp = emp.spouse) + FROM Employee spouseEmp + WHERE spouseEmp = emp.spouse) """); } @@ -620,14 +620,14 @@ class HqlQueryRendererTests { SELECT DISTINCT emp FROM Employee emp WHERE EVERY (SELECT spouseEmp - FROM Employee spouseEmp) > 1 + FROM Employee spouseEmp) > 1 """); assertQuery(""" SELECT DISTINCT emp FROM Employee emp WHERE ALL (SELECT spouseEmp - FROM Employee spouseEmp) > 1 + FROM Employee spouseEmp) > 1 """); assertQuery(""" @@ -656,14 +656,14 @@ class HqlQueryRendererTests { SELECT DISTINCT emp FROM Employee emp WHERE ANY (SELECT spouseEmp - FROM Employee spouseEmp) > 1 + FROM Employee spouseEmp) > 1 """); assertQuery(""" SELECT DISTINCT emp FROM Employee emp WHERE SOME (SELECT spouseEmp - FROM Employee spouseEmp) > 1 + FROM Employee spouseEmp) > 1 """); assertQuery(""" @@ -772,7 +772,7 @@ class HqlQueryRendererTests { assertQuery(""" SELECT s.name, COUNT(p) FROM Suppliers s LEFT JOIN s.products p - ON p.status = 'inStock' + ON p.status = 'inStock' GROUP BY s.name """); } @@ -854,15 +854,15 @@ class HqlQueryRendererTests { assertQuery(""" SELECT e FROM Employee e JOIN e.projects p WHERE TREAT(p AS LargeProject).budget > 1000 - OR TREAT(p AS SmallProject).name LIKE 'Persist%' - OR p.description LIKE "cost overrun" + OR TREAT(p AS SmallProject).name LIKE 'Persist%' + OR p.description LIKE "cost overrun" """); assertQuery(""" SELECT e FROM Employee e JOIN e.projects p WHERE TREAT(p AS LargeProject).budget > 1000 - OR TREAT(p AS SmallProject).name LIKE 'Persist%' - OR p.description LIKE 'cost overrun' + OR TREAT(p AS SmallProject).name LIKE 'Persist%' + OR p.description LIKE 'cost overrun' """); } @@ -872,7 +872,7 @@ class HqlQueryRendererTests { assertQuery(""" SELECT e FROM Employee e WHERE TREAT(e AS Exempt).vacationDays > 10 - OR TREAT(e AS Contractor).hours > 100 + OR TREAT(e AS Contractor).hours > 100 """); } @@ -883,8 +883,8 @@ class HqlQueryRendererTests { SELECT emp FROM Employee emp WHERE emp.salary > ALL (SELECT m.salary - FROM Manager m - WHERE m.department = emp.department) + FROM Manager m + WHERE m.department = emp.department) """); } @@ -895,8 +895,8 @@ class HqlQueryRendererTests { SELECT DISTINCT emp FROM Employee emp WHERE EXISTS (SELECT spouseEmp - FROM Employee spouseEmp - WHERE spouseEmp = emp.spouse) + FROM Employee spouseEmp + WHERE spouseEmp = emp.spouse) """); } @@ -970,9 +970,9 @@ class HqlQueryRendererTests { UPDATE Employee e SET e.salary = CASE WHEN e.rating = 1 THEN e.salary * 1.1 - WHEN e.rating = 2 THEN e.salary * 1.05 - ELSE e.salary * 1.01 - END + WHEN e.rating = 2 THEN e.salary * 1.05 + ELSE e.salary * 1.01 + END """); } @@ -982,10 +982,10 @@ class HqlQueryRendererTests { assertQuery(""" UPDATE Employee e SET e.salary = - CASE e.rating WHEN 1 THEN e.salary * 1.1 - WHEN 2 THEN e.salary * 1.05 - ELSE e.salary * 1.01 - END + CASE e.rating WHEN 1 THEN e.salary * 1.1 + WHEN 2 THEN e.salary * 1.05 + ELSE e.salary * 1.01 + END """); } @@ -994,11 +994,11 @@ class HqlQueryRendererTests { assertQuery(""" SELECT e.name, - CASE TYPE(e) WHEN Exempt THEN 'Exempt' - WHEN Contractor THEN 'Contractor' - WHEN Intern THEN 'Intern' - ELSE 'NonExempt' - END + CASE TYPE(e) WHEN Exempt THEN 'Exempt' + WHEN Contractor THEN 'Contractor' + WHEN Intern THEN 'Intern' + ELSE 'NonExempt' + END FROM Employee e WHERE e.dept.name = 'Engineering' """); @@ -1009,12 +1009,12 @@ class HqlQueryRendererTests { assertQuery(""" SELECT e.name, - f.name, - CONCAT(CASE WHEN f.annualMiles > 50000 THEN 'Platinum ' - WHEN f.annualMiles > 25000 THEN 'Gold ' - ELSE '' - END, - 'Frequent Flyer') + f.name, + CONCAT(CASE WHEN f.annualMiles > 50000 THEN 'Platinum ' + WHEN f.annualMiles > 25000 THEN 'Gold ' + ELSE '' + END, + 'Frequent Flyer') FROM Employee e JOIN e.frequentFlierPlan f """); } @@ -1104,8 +1104,8 @@ class HqlQueryRendererTests { SELECT c FROM Customer c WHERE EXISTS (SELECT c2 - FROM Customer c2 - WHERE c2.orders %s c.orders) + FROM Customer c2 + WHERE c2.orders %s c.orders) """.formatted(distinctFrom)); } @@ -1814,12 +1814,12 @@ class HqlQueryRendererTests { "from Person pr " + // "left join pr.phones ph " + // "where ph is null " + // - " or ph.type = :phoneType"); + "or ph.type = :phoneType"); assertQuery("select distinct pr " + // "from Person pr " + // "left outer join pr.phones ph " + // "where ph is null " + // - " or ph.type = :phoneType"); + "or ph.type = :phoneType"); assertQuery("select pr.name, ph.number " + // "from Person pr " + // "left join pr.phones ph with ph.type = :phoneType "); @@ -1843,8 +1843,7 @@ class HqlQueryRendererTests { "(select c.duration as duration " + // " from p.calls c" + // " order by c.duration desc" + // - " limit 1 " + // - " ) longest " + // + " limit 1) longest " + // "where p.number = :phoneNumber"); assertQuery("select ph " + // "from Phone ph " + // @@ -2208,7 +2207,7 @@ class HqlQueryRendererTests { SELECT b FROM MyEntity b WHERE b.status = :status - AND utl_raw.cast_to_varchar2((nlssort(lower(b.name), 'nls_sort=binary_ai'))) LIKE lower(:name) + AND utl_raw.cast_to_varchar2((nlssort(lower(b.name), 'nls_sort=binary_ai'))) LIKE lower(:name) ORDER BY utl_raw.cast_to_varchar2((nlssort(lower(b.name), 'nls_sort=binary_ai'))) ASC """); @@ -2377,17 +2376,17 @@ class HqlQueryRendererTests { assertQuery("select ie from ItemExample ie where ie.status = com.app.domain.object.Status.UP"); } - @Test // GH-3864 - Added support for Set Return function (SRF) support H7 parsing and - // rendering + @Test // GH-3864 void fromSRFWithAlias() { + assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date , :integerValue ) d + from some_function(:date, :integerValue) d """); assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date ) d + from some_function(:date) d """); assertQuery(""" @@ -2397,21 +2396,21 @@ class HqlQueryRendererTests { assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date , :integerValue , :longValue ) d + from some_function(:date, :integerValue, :longValue) d """); } - @Test // GH-3864 - Added support for Set Return function support H7 parsing and - // rendering + @Test // GH-3864 void fromSRFWithoutAlias() { + assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date , :integerValue ) + from some_function(:date, :integerValue) """); assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date ) + from some_function(:date) """); assertQuery(""" @@ -2421,21 +2420,21 @@ class HqlQueryRendererTests { assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date , :integerValue , :longValue ) + from some_function(:date, :integerValue, :longValue) """); } - @Test // GH-3864 - Added support for Set Return function support H7 parsing and - // rendering + @Test // GH-3864 void joinEntityToSRFWithFunctionAlias() { + assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from EntityClass e join some_function(:date , :integerValue ) d on (e.id = d.idFunction) + from EntityClass e join some_function(:date, :integerValue) d on (e.id = d.idFunction) """); assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from EntityClass e join some_function(:date ) d on (e.id = d.idFunction) + from EntityClass e join some_function(:date) d on (e.id = d.idFunction) """); assertQuery(""" @@ -2443,24 +2442,23 @@ class HqlQueryRendererTests { from EntityClass e join some_function() d on (e.id = d.idFunction) """); - assertQuery( - """ - select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from EntityClass e join some_function(:date , :integerValue , :longValue ) d on (e.id = d.idFunction) - """); + assertQuery(""" + select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) + from EntityClass e join some_function(:date, :integerValue, :longValue) d on (e.id = d.idFunction) + """); } - @Test // GH-3864 - Added support for Set Return function support H7 parsing and - // rendering + @Test // GH-3864 void joinEntityToSRFWithoutFunctionAlias() { + assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from EntityClass e join some_function(:date , :integerValue ) on (e.id = idFunction) + from EntityClass e join some_function(:date, :integerValue) on (e.id = idFunction) """); assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from EntityClass e join some_function(:date ) on (e.id = idFunction) + from EntityClass e join some_function(:date) on (e.id = idFunction) """); assertQuery(""" @@ -2470,21 +2468,21 @@ class HqlQueryRendererTests { assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from EntityClass e join some_function(:date , :integerValue , :longValue ) on (e.id = idFunction) + from EntityClass e join some_function(:date, :integerValue, :longValue) on (e.id = idFunction) """); } - @Test // GH-3864 - Added support for Set Return function support H7 parsing and - // rendering + @Test // GH-3864 void joinSRFToEntityWithoutFunctionWithAlias() { + assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date , :integerValue ) d join EntityClass e on (e.id = d.idFunction) + from some_function(:date, :integerValue) d join EntityClass e on (e.id = d.idFunction) """); assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date ) d join EntityClass e on (e.id = idFunction) + from some_function(:date) d join EntityClass e on (e.id = idFunction) """); assertQuery(""" @@ -2493,22 +2491,22 @@ class HqlQueryRendererTests { """); assertQuery(""" - select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date , :integerValue , :longValue ) d join EntityClass e on (e.id = d.idFunction) + select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) + from some_function(:date, :integerValue, :longValue) d join EntityClass e on (e.id = d.idFunction) """); } - @Test // GH-3864 - Added support for Set Return function support H7 parsing and - // rendering + @Test // GH-3864 void joinSRFToEntityWithoutFunctionWithoutAlias() { + assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date , :integerValue ) join EntityClass e on (e.id = idFunction) + from some_function(:date, :integerValue) join EntityClass e on (e.id = idFunction) """); assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date ) join EntityClass e on (e.id = idFunction) + from some_function(:date) join EntityClass e on (e.id = idFunction) """); assertQuery(""" @@ -2518,23 +2516,23 @@ class HqlQueryRendererTests { assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date , :integerValue , :longValue ) join EntityClass e on (e.id = idFunction) + from some_function(:date, :integerValue, :longValue) join EntityClass e on (e.id = idFunction) """); } - @Test // GH-3864 - Added support for Set Return function support H7 parsing and - // rendering + @Test // GH-3864 void selectSRFIntoSubquery() { + assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) from (select x.idFunction idFunction, x.nameFunction nameFunction - from some_function(:date , :integerValue ) x) d + from some_function(:date, :integerValue) x) d """); assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) from (select x.idFunction idFunction, x.nameFunction nameFunction - from some_function(:date ) x) d + from some_function(:date) x) d """); assertQuery(""" @@ -2546,82 +2544,82 @@ class HqlQueryRendererTests { assertQuery(""" select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) from (select x.idFunction idFunction, x.nameFunction nameFunction - from some_function(:date , :integerValue , :longValue ) x) d + from some_function(:date, :integerValue, :longValue) x) d """); } - @Test // GH-3864 - Added support for Set Return function support H7 parsing and - // rendering + @Test // GH-3864 void joinEntityToSRFIntoSubquery() { + assertQuery(""" - select new com.example.dto.SampleDto(k.id, d.nameFunction) - from EntityClass k - inner join (select x.idFunction idFunction, x.nameFunction nameFunction - from some_function(:date , :integerValue ) x ) d on (k.id = d.idFunction) + select new com.example.dto.SampleDto(k.id, d.nameFunction) + from EntityClass k + inner join (select x.idFunction idFunction, x.nameFunction nameFunction + from some_function(:date, :integerValue) x) d on (k.id = d.idFunction) """); assertQuery(""" - select new com.example.dto.SampleDto(k.id, d.nameFunction) - from EntityClass k - inner join (select x.idFunction idFunction, x.nameFunction nameFunction - from some_function(:date ) x ) d on (k.id = d.idFunction) + select new com.example.dto.SampleDto(k.id, d.nameFunction) + from EntityClass k + inner join (select x.idFunction idFunction, x.nameFunction nameFunction + from some_function(:date) x) d on (k.id = d.idFunction) """); assertQuery(""" - select new com.example.dto.SampleDto(k.id, d.nameFunction) - from EntityClass k - inner join (select x.idFunction idFunction, x.nameFunction nameFunction - from some_function() x ) d on (k.id = d.idFunction) + select new com.example.dto.SampleDto(k.id, d.nameFunction) + from EntityClass k + inner join (select x.idFunction idFunction, x.nameFunction nameFunction + from some_function() x) d on (k.id = d.idFunction) """); assertQuery(""" - select new com.example.dto.SampleDto(k.id, d.nameFunction) - from EntityClass k - inner join (select x.idFunction idFunction, x.nameFunction nameFunction - from some_function(:date , :integerValue , :longValue ) x ) d on (k.id = d.idFunction) + select new com.example.dto.SampleDto(k.id, d.nameFunction) + from EntityClass k + inner join (select x.idFunction idFunction, x.nameFunction nameFunction + from some_function(:date, :integerValue, :longValue) x) d on (k.id = d.idFunction) """); } - @Test // GH-3864 - Added support for Set Return function support H7 parsing and - // rendering + @Test // GH-3864 void joinLateralEntityToSRF() { + assertQuery(""" - select new com.example.dto.SampleDto(k.id, d.nameFunction) - from EntityClass k - join lateral (select x.idFunction idFunction, x.nameFunction nameFunction - from some_function(:date , :integerValue ) x where x.idFunction = k.id ) d + select new com.example.dto.SampleDto(k.id, d.nameFunction) + from EntityClass k + join lateral (select x.idFunction idFunction, x.nameFunction nameFunction + from some_function(:date, :integerValue) x where x.idFunction = k.id) d """); assertQuery(""" - select new com.example.dto.SampleDto(k.id, d.nameFunction) - from EntityClass k - join lateral (select x.idFunction idFunction, x.nameFunction nameFunction - from some_function(:date ) x where x.idFunction = k.id ) d + select new com.example.dto.SampleDto(k.id, d.nameFunction) + from EntityClass k + join lateral (select x.idFunction idFunction, x.nameFunction nameFunction + from some_function(:date) x where x.idFunction = k.id) d """); assertQuery(""" - select new com.example.dto.SampleDto(k.id, d.nameFunction) - from EntityClass k - join lateral (select x.idFunction idFunction, x.nameFunction nameFunction - from some_function() x where x.idFunction = k.id ) d + select new com.example.dto.SampleDto(k.id, d.nameFunction) + from EntityClass k + join lateral (select x.idFunction idFunction, x.nameFunction nameFunction + from some_function() x where x.idFunction = k.id) d """); assertQuery(""" - select new com.example.dto.SampleDto(k.id, d.nameFunction) - from EntityClass k - join lateral (select x.idFunction idFunction, x.nameFunction nameFunction - from some_function(:date , :integerValue , :longValue ) x where x.idFunction = k.id ) d + select new com.example.dto.SampleDto(k.id, d.nameFunction) + from EntityClass k + join lateral (select x.idFunction idFunction, x.nameFunction nameFunction + from some_function(:date, :integerValue, :longValue) x where x.idFunction = k.id) d """); } - @Test // GH-3864 - Added support for Set Return function support H7 parsing and - // rendering + @Test // GH-3864 void joinTwoFunctions() { + assertQuery(""" - select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) - from some_function(:date , :integerValue ) d - inner join some_function_single_param(:date ) k on (d.idFunction = k.idFunctionSP) + select new com.example.dto.SampleDto(d.idFunction, d.nameFunction) + from some_function(:date, :integerValue) d + inner join some_function_single_param(:date) k on (d.idFunction = k.idFunctionSP) """); } diff --git a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java index 71d2327f7..260a788d6 100644 --- a/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java +++ b/spring-data-jpa/src/test/java/org/springframework/data/jpa/repository/query/HqlQueryTransformerTests.java @@ -1133,32 +1133,31 @@ class HqlQueryTransformerTests { assertCountQuery("select distinct substring(e.firstname, 1, position('a' in e.lastname)) as x from from Employee", "select count(distinct substring(e.firstname, 1, position('a' in e.lastname))) from from Employee"); } - - + @Test // GH-3864 void testCountFromFunctionWithAlias() { // given - var original = "select x.id, x.value from some_function(:date , :integerValue ) x"; + var original = "select x.id, x.value from some_function(:date, :integerValue) x"; // when var results = createCountQueryFor(original); // then - assertThat(results).contains("select count(*) from some_function(:date , :integerValue ) x"); - } - + assertThat(results).contains("select count(*) from some_function(:date, :integerValue) x"); + } + @Test // GH-3864 void testCountFromFunctionNoAlias() { // given - var original = "select id, value from some_function(:date , :integerValue )"; + var original = "select id, value from some_function(:date, :integerValue)"; // when var results = createCountQueryFor(original); // then - assertThat(results).contains("select count(*) from some_function(:date , :integerValue )"); + assertThat(results).contains("select count(*) from some_function(:date, :integerValue)"); } @Test // GH-3427