Add support for Set-Returning Functions (SRF) to HQL parser and query rendering.
Signed-off-by: oscarfanchin <oscar.fanchin@gmail.com> Closes: #3864 Original pull request: #3879
This commit is contained in:
committed by
Mark Paluch
parent
85fcbcd2fb
commit
2ebe4caba6
@@ -114,8 +114,13 @@ joinSpecifier
|
||||
fromRoot
|
||||
: entityName variable?
|
||||
| LATERAL? '(' subquery ')' variable?
|
||||
| functionCallAsFromSource variable?
|
||||
;
|
||||
|
||||
functionCallAsFromSource
|
||||
: identifier '(' (expression (',' expression)*)? ')'
|
||||
;
|
||||
|
||||
join
|
||||
: joinType JOIN FETCH? joinTarget joinRestriction? // Spec BNF says joinType isn't optional, but text says that it is.
|
||||
;
|
||||
@@ -123,6 +128,11 @@ join
|
||||
joinTarget
|
||||
: path variable? # JoinPath
|
||||
| LATERAL? '(' subquery ')' variable? # JoinSubquery
|
||||
| functionCallAsJoinTarget variable? # JoinFunctionCall
|
||||
;
|
||||
|
||||
functionCallAsJoinTarget
|
||||
: identifier '(' (expression (',' expression)*)? ')'
|
||||
;
|
||||
|
||||
// https://docs.jboss.org/hibernate/orm/6.1/userguide/html_single/Hibernate_User_Guide.html#hql-update
|
||||
@@ -1878,4 +1888,4 @@ ESCAPE_SEQUENCE
|
||||
|
||||
QUOTED_IDENTIFIER
|
||||
: BACKTICK ( ESCAPE_SEQUENCE | '\\' BACKTICK | ~([`]) )* BACKTICK
|
||||
;
|
||||
;
|
||||
@@ -23,19 +23,29 @@ import org.jspecify.annotations.Nullable;
|
||||
* Hibernate-specific query details capturing common table expression details.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author oscar.fanchin
|
||||
* @since 3.5
|
||||
*/
|
||||
class HibernateQueryInformation extends QueryInformation {
|
||||
|
||||
private final boolean hasCte;
|
||||
|
||||
private final boolean hasFromFunction;
|
||||
|
||||
|
||||
public HibernateQueryInformation(@Nullable String alias, List<QueryToken> projection,
|
||||
boolean hasConstructorExpression, boolean hasCte) {
|
||||
boolean hasConstructorExpression, boolean hasCte,boolean hasFromFunction) {
|
||||
super(alias, projection, hasConstructorExpression);
|
||||
this.hasCte = hasCte;
|
||||
this.hasFromFunction = hasFromFunction;
|
||||
}
|
||||
|
||||
public boolean hasCte() {
|
||||
return hasCte;
|
||||
}
|
||||
|
||||
public boolean hasFromFunction() {
|
||||
return hasFromFunction;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.data.jpa.repository.query.QueryTransformers.CountSele
|
||||
* @author Greg Turnquist
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author oscar.fanchin
|
||||
* @since 3.1
|
||||
*/
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@@ -38,11 +39,13 @@ class HqlCountQueryTransformer extends HqlQueryRenderer {
|
||||
private final @Nullable String countProjection;
|
||||
private final @Nullable String primaryFromAlias;
|
||||
private final boolean containsCTE;
|
||||
private final boolean containsFromFunction;
|
||||
|
||||
HqlCountQueryTransformer(@Nullable String countProjection, HibernateQueryInformation queryInformation) {
|
||||
this.countProjection = countProjection;
|
||||
this.primaryFromAlias = queryInformation.getAlias();
|
||||
this.containsCTE = queryInformation.hasCte();
|
||||
this.containsFromFunction = queryInformation.hasFromFunction();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -156,11 +159,19 @@ class HqlCountQueryTransformer extends HqlQueryRenderer {
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -204,7 +215,7 @@ class HqlCountQueryTransformer extends HqlQueryRenderer {
|
||||
} else {
|
||||
|
||||
// with CTE primary alias fails with hibernate (WITH entities AS (…) SELECT count(c) FROM entities c)
|
||||
if (containsCTE) {
|
||||
if (containsCTE || containsFromFunction) {
|
||||
nested.append(QueryTokens.token("*"));
|
||||
} else {
|
||||
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jspecify.annotations.Nullable;
|
||||
* {@link ParsedQueryIntrospector} for HQL queries.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author oscar.fanchin
|
||||
*/
|
||||
@SuppressWarnings({ "UnreachableCode", "ConstantValue" })
|
||||
class HqlQueryIntrospector extends HqlBaseVisitor<Void> implements ParsedQueryIntrospector<HibernateQueryInformation> {
|
||||
@@ -40,11 +41,12 @@ class HqlQueryIntrospector extends HqlBaseVisitor<Void> implements ParsedQueryIn
|
||||
private boolean projectionProcessed;
|
||||
private boolean hasConstructorExpression = false;
|
||||
private boolean hasCte = false;
|
||||
private boolean hasFromFunction = false;
|
||||
|
||||
@Override
|
||||
public HibernateQueryInformation getParsedQueryInformation() {
|
||||
return new HibernateQueryInformation(primaryFromAlias, projection == null ? Collections.emptyList() : projection,
|
||||
hasConstructorExpression, hasCte);
|
||||
hasConstructorExpression, hasCte, hasFromFunction);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -63,6 +65,12 @@ 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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Void visitFromRoot(HqlParser.FromRootContext ctx) {
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.springframework.util.ObjectUtils;
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @author Christoph Strobl
|
||||
* @author Oscar Fanchin
|
||||
* @since 3.1
|
||||
*/
|
||||
@SuppressWarnings({ "ConstantConditions", "DuplicatedCode", "UnreachableCode" })
|
||||
@@ -63,6 +64,24 @@ 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) {
|
||||
|
||||
@@ -376,6 +395,14 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
|
||||
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()));
|
||||
}
|
||||
@@ -442,6 +469,39 @@ class HqlQueryRenderer extends HqlBaseVisitor<QueryTokenStream> {
|
||||
return builder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitJoinFunctionCall(HqlParser.JoinFunctionCallContext ctx) {
|
||||
|
||||
QueryRendererBuilder builder = QueryRenderer.builder();
|
||||
|
||||
builder.append(visit(ctx.functionCallAsJoinTarget()));
|
||||
|
||||
if (ctx.variable() != null) {
|
||||
builder.appendExpression(visit(ctx.variable()));
|
||||
}
|
||||
|
||||
return builder;
|
||||
|
||||
}
|
||||
|
||||
@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) {
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.util.ObjectUtils;
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
* @author Christoph Strobl
|
||||
* @author oscar.fanchin
|
||||
* @since 3.1
|
||||
*/
|
||||
@SuppressWarnings("ConstantValue")
|
||||
@@ -122,6 +123,19 @@ class HqlSortedQueryTransformer extends HqlQueryRenderer {
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitJoinFunctionCall(HqlParser.JoinFunctionCallContext ctx) {
|
||||
|
||||
QueryTokenStream tokens = super.visitJoinFunctionCall(ctx);
|
||||
|
||||
if (ctx.variable() != null && !tokens.isEmpty()) {
|
||||
transformerSupport.registerAlias(tokens.getLast());
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public QueryTokenStream visitVariable(HqlParser.VariableContext ctx) {
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.junit.jupiter.params.provider.ValueSource;
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Yannick Brandt
|
||||
* @author oscar.fanchin
|
||||
* @since 3.1
|
||||
*/
|
||||
class HqlQueryRendererTests {
|
||||
@@ -2375,4 +2376,254 @@ class HqlQueryRendererTests {
|
||||
assertQuery("select ie from ItemExample ie left join ie.object io where io.object = :externalId");
|
||||
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
|
||||
void fromSRFWithAlias() {
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function(:date , :integerValue ) d
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function(:date ) d
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function() d
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function(:date , :integerValue , :longValue ) d
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3864 - Added support for Set Return function support H7 parsing and
|
||||
// rendering
|
||||
void fromSRFWithoutAlias() {
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function(:date , :integerValue )
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function(:date )
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function()
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function(:date , :integerValue , :longValue )
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3864 - Added support for Set Return function support H7 parsing and
|
||||
// rendering
|
||||
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)
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from EntityClass e join some_function(:date ) d on (e.id = d.idFunction)
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
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)
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3864 - Added support for Set Return function support H7 parsing and
|
||||
// rendering
|
||||
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)
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from EntityClass e join some_function(:date ) on (e.id = idFunction)
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from EntityClass e join some_function() on (e.id = idFunction)
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
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
|
||||
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)
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function(:date ) d join EntityClass e on (e.id = idFunction)
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function() d join EntityClass e on (e.id = idFunction)
|
||||
""");
|
||||
|
||||
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)
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3864 - Added support for Set Return function support H7 parsing and
|
||||
// rendering
|
||||
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)
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function(:date ) join EntityClass e on (e.id = idFunction)
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from some_function() join EntityClass e on (e.id = idFunction)
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
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
|
||||
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
|
||||
""");
|
||||
|
||||
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
|
||||
""");
|
||||
|
||||
assertQuery("""
|
||||
select new com.example.dto.SampleDto(d.idFunction, d.nameFunction)
|
||||
from (select x.idFunction idFunction, x.nameFunction nameFunction
|
||||
from some_function() 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 , :integerValue , :longValue ) x) d
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3864 - Added support for Set Return function support H7 parsing and
|
||||
// rendering
|
||||
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)
|
||||
""");
|
||||
|
||||
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)
|
||||
""");
|
||||
|
||||
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)
|
||||
""");
|
||||
|
||||
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)
|
||||
""");
|
||||
}
|
||||
|
||||
@Test // GH-3864 - Added support for Set Return function support H7 parsing and
|
||||
// rendering
|
||||
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
|
||||
""");
|
||||
|
||||
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
|
||||
""");
|
||||
|
||||
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
|
||||
""");
|
||||
|
||||
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
|
||||
""");
|
||||
|
||||
}
|
||||
|
||||
@Test // GH-3864 - Added support for Set Return function support H7 parsing and
|
||||
// rendering
|
||||
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)
|
||||
""");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1133,6 +1133,33 @@ 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";
|
||||
|
||||
// when
|
||||
var results = createCountQueryFor(original);
|
||||
|
||||
// then
|
||||
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 )";
|
||||
|
||||
// when
|
||||
var results = createCountQueryFor(original);
|
||||
|
||||
// then
|
||||
assertThat(results).contains("select count(*) from some_function(:date , :integerValue )");
|
||||
}
|
||||
|
||||
@Test // GH-3427
|
||||
void sortShouldBeAppendedWithSpacingInCaseOfSetOperator() {
|
||||
|
||||
Reference in New Issue
Block a user