Polishing.

Reuse setReturningFunction and genericFunctionArguments structure for easier extension. Split fromRoot into separate parser function fragments.

Fix trailing spaces.

See: #3864
Original pull request: #3879
This commit is contained in:
Mark Paluch
2025-05-12 15:46:29 +02:00
parent 2ebe4caba6
commit 01eb2b833d
8 changed files with 240 additions and 276 deletions

View File

@@ -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
;
;

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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<Void> implements ParsedQueryIntrospector<HibernateQueryInformation> {
@@ -52,9 +52,9 @@ class HqlQueryIntrospector extends HqlBaseVisitor<Void> 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<Void> 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

View File

@@ -64,24 +64,6 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
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<QueryTokenStream> {
}
@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<QueryTokenStream> {
}
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<QueryTokenStream> {
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<QueryTokenStream> {
}
@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) {

View File

@@ -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")

View File

@@ -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)
""");
}

View File

@@ -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