Skip to content

Commit a35288c

Browse files
committed
Introduce QueryTransformer for functions
1 parent 89bf82f commit a35288c

File tree

16 files changed

+180
-44
lines changed

16 files changed

+180
-44
lines changed

hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmAggregateFunction.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
2222
import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
2323
import org.hibernate.sql.ast.tree.SqlAstNode;
24+
import org.hibernate.sql.ast.tree.expression.Expression;
25+
import org.hibernate.sql.ast.tree.predicate.Predicate;
2426

2527
/**
2628
* @author Christian Beikov
@@ -73,7 +75,7 @@ public SelfRenderingSqmAggregateFunction<T> copy(SqmCopyContext context) {
7375
}
7476

7577
@Override
76-
public SelfRenderingFunctionSqlAstExpression convertToSqlAst(SqmToSqlAstConverter walker) {
78+
public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
7779
final ReturnableType<?> resultType = resolveResultType(
7880
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
7981
);

hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmFunction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.hibernate.query.sqm.tree.SqmVisitableNode;
2424
import org.hibernate.query.sqm.tree.expression.SqmFunction;
2525
import org.hibernate.sql.ast.tree.SqlAstNode;
26+
import org.hibernate.sql.ast.tree.expression.Expression;
2627
import org.hibernate.type.spi.TypeConfiguration;
2728

2829
import static java.util.Collections.emptyList;
@@ -109,7 +110,7 @@ protected static List<SqlAstNode> resolveSqlAstArguments(List<? extends SqmTyped
109110
}
110111

111112
@Override
112-
public SelfRenderingFunctionSqlAstExpression convertToSqlAst(SqmToSqlAstConverter walker) {
113+
public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
113114
final ReturnableType<?> resultType = resolveResultType(
114115
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
115116
);

hibernate-core/src/main/java/org/hibernate/query/sqm/function/SelfRenderingSqmOrderedSetAggregateFunction.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.hibernate.query.sqm.tree.select.SqmSortSpecification;
2626
import org.hibernate.sql.ast.Clause;
2727
import org.hibernate.sql.ast.tree.SqlAstNode;
28+
import org.hibernate.sql.ast.tree.expression.Expression;
2829
import org.hibernate.sql.ast.tree.predicate.Predicate;
2930
import org.hibernate.sql.ast.tree.select.SortSpecification;
3031

@@ -91,7 +92,7 @@ public SelfRenderingSqmOrderedSetAggregateFunction<T> copy(SqmCopyContext contex
9192
}
9293

9394
@Override
94-
public SelfRenderingFunctionSqlAstExpression convertToSqlAst(SqmToSqlAstConverter walker) {
95+
public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
9596
final ReturnableType<?> resultType = resolveResultType(
9697
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
9798
);

hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java

Lines changed: 79 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -95,28 +95,28 @@
9595
import org.hibernate.persister.entity.EntityPersister;
9696
import org.hibernate.persister.entity.Joinable;
9797
import org.hibernate.persister.entity.SingleTableEntityPersister;
98-
import org.hibernate.query.sqm.BinaryArithmeticOperator;
9998
import org.hibernate.query.BindableType;
100-
import org.hibernate.query.sqm.CastType;
101-
import org.hibernate.query.sqm.ComparisonOperator;
102-
import org.hibernate.query.sqm.DynamicInstantiationNature;
103-
import org.hibernate.query.sqm.FetchClauseType;
104-
import org.hibernate.query.spi.NavigablePath;
10599
import org.hibernate.query.QueryLogging;
106100
import org.hibernate.query.ReturnableType;
107101
import org.hibernate.query.SemanticException;
108-
import org.hibernate.query.sqm.SortOrder;
109-
import org.hibernate.query.sqm.TemporalUnit;
110-
import org.hibernate.query.sqm.UnaryArithmeticOperator;
111102
import org.hibernate.query.criteria.JpaPath;
103+
import org.hibernate.query.spi.NavigablePath;
112104
import org.hibernate.query.spi.QueryOptions;
113105
import org.hibernate.query.spi.QueryParameterBinding;
114106
import org.hibernate.query.spi.QueryParameterBindings;
115107
import org.hibernate.query.spi.QueryParameterImplementor;
108+
import org.hibernate.query.sqm.BinaryArithmeticOperator;
109+
import org.hibernate.query.sqm.CastType;
110+
import org.hibernate.query.sqm.ComparisonOperator;
111+
import org.hibernate.query.sqm.DynamicInstantiationNature;
112+
import org.hibernate.query.sqm.FetchClauseType;
116113
import org.hibernate.query.sqm.InterpretationException;
114+
import org.hibernate.query.sqm.SortOrder;
117115
import org.hibernate.query.sqm.SqmExpressible;
118116
import org.hibernate.query.sqm.SqmPathSource;
119117
import org.hibernate.query.sqm.SqmQuerySource;
118+
import org.hibernate.query.sqm.TemporalUnit;
119+
import org.hibernate.query.sqm.UnaryArithmeticOperator;
120120
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
121121
import org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression;
122122
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
@@ -261,6 +261,7 @@
261261
import org.hibernate.sql.ast.spi.SqlSelection;
262262
import org.hibernate.sql.ast.tree.Statement;
263263
import org.hibernate.sql.ast.tree.cte.CteColumn;
264+
import org.hibernate.sql.ast.tree.cte.CteContainer;
264265
import org.hibernate.sql.ast.tree.cte.CteStatement;
265266
import org.hibernate.sql.ast.tree.cte.CteTable;
266267
import org.hibernate.sql.ast.tree.cte.SearchClauseSpecification;
@@ -287,6 +288,7 @@
287288
import org.hibernate.sql.ast.tree.expression.Over;
288289
import org.hibernate.sql.ast.tree.expression.Overflow;
289290
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
291+
import org.hibernate.sql.ast.tree.expression.QueryTransformer;
290292
import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
291293
import org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression;
292294
import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression;
@@ -384,6 +386,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
384386
private final SqlAstCreationContext creationContext;
385387
private final boolean jpaQueryComplianceEnabled;
386388
private final SqmStatement<?> statement;
389+
private final CteContainer cteContainer = new GlobalCteContainer();
387390

388391
private final QueryOptions queryOptions;
389392
private final LoadQueryInfluencers loadQueryInfluencers;
@@ -429,6 +432,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
429432
private final Stack<Supplier<MappingModelExpressible<?>>> inferrableTypeAccessStack = new StandardStack<>(
430433
() -> null
431434
);
435+
private final Stack<List<QueryTransformer>> queryTransformers = new StandardStack<>();
432436
private boolean inTypeInference;
433437

434438
private SqmByUnit appliedByUnit;
@@ -658,7 +662,7 @@ public Statement visitStatement(SqmStatement<?> sqmStatement) {
658662

659663
@Override
660664
public UpdateStatement visitUpdateStatement(SqmUpdateStatement<?> sqmStatement) {
661-
Map<String, CteStatement> cteStatements = this.visitCteContainer( sqmStatement );
665+
final CteContainer cteContainer = this.visitCteContainer( sqmStatement );
662666

663667
final SqmRoot<?> sqmTarget = sqmStatement.getTarget();
664668
final String entityName = sqmTarget.getEntityName();
@@ -718,7 +722,7 @@ public UpdateStatement visitUpdateStatement(SqmUpdateStatement<?> sqmStatement)
718722
}
719723

720724
return new UpdateStatement(
721-
sqmStatement.isWithRecursive(), cteStatements,
725+
cteContainer,
722726
(NamedTableReference) rootTableGroup.getPrimaryTableReference(),
723727
assignments,
724728
SqlAstTreeHelper.combinePredicates( suppliedPredicate, additionalRestrictions ),
@@ -896,7 +900,7 @@ public Expression resolveSqlExpression(
896900

897901
@Override
898902
public DeleteStatement visitDeleteStatement(SqmDeleteStatement<?> statement) {
899-
Map<String, CteStatement> cteStatements = this.visitCteContainer( statement );
903+
final CteContainer cteContainer = this.visitCteContainer( statement );
900904

901905
final String entityName = statement.getTarget().getEntityName();
902906
final EntityPersister entityDescriptor = creationContext.getSessionFactory()
@@ -946,8 +950,7 @@ public DeleteStatement visitDeleteStatement(SqmDeleteStatement<?> statement) {
946950
}
947951

948952
return new DeleteStatement(
949-
statement.isWithRecursive(),
950-
cteStatements,
953+
cteContainer,
951954
(NamedTableReference) rootTableGroup.getPrimaryTableReference(),
952955
SqlAstTreeHelper.combinePredicates( suppliedPredicate, additionalRestrictions ),
953956
Collections.emptyList()
@@ -963,7 +966,7 @@ public DeleteStatement visitDeleteStatement(SqmDeleteStatement<?> statement) {
963966

964967
@Override
965968
public InsertStatement visitInsertSelectStatement(SqmInsertSelectStatement<?> sqmStatement) {
966-
Map<String, CteStatement> cteStatements = this.visitCteContainer( sqmStatement );
969+
final CteContainer cteContainer = this.visitCteContainer( sqmStatement );
967970

968971
final String entityName = sqmStatement.getTarget().getEntityName();
969972
final EntityPersister entityDescriptor = creationContext.getSessionFactory()
@@ -1004,8 +1007,7 @@ public InsertStatement visitInsertSelectStatement(SqmInsertSelectStatement<?> sq
10041007
getFromClauseAccess().registerTableGroup( rootPath, rootTableGroup );
10051008

10061009
insertStatement = new InsertStatement(
1007-
sqmStatement.isWithRecursive(),
1008-
cteStatements,
1010+
cteContainer,
10091011
(NamedTableReference) rootTableGroup.getPrimaryTableReference(),
10101012
Collections.emptyList()
10111013
);
@@ -1050,7 +1052,7 @@ public InsertStatement visitInsertSelectStatement(SqmInsertSelectStatement<?> sq
10501052

10511053
@Override
10521054
public InsertStatement visitInsertValuesStatement(SqmInsertValuesStatement<?> sqmStatement) {
1053-
Map<String, CteStatement> cteStatements = this.visitCteContainer( sqmStatement );
1055+
final CteContainer cteContainer = this.visitCteContainer( sqmStatement );
10541056
final String entityName = sqmStatement.getTarget().getEntityName();
10551057
final EntityPersister entityDescriptor = creationContext.getSessionFactory()
10561058
.getRuntimeMetamodels()
@@ -1086,8 +1088,7 @@ public InsertStatement visitInsertValuesStatement(SqmInsertValuesStatement<?> sq
10861088
getFromClauseAccess().registerTableGroup( rootPath, rootTableGroup );
10871089

10881090
final InsertStatement insertStatement = new InsertStatement(
1089-
sqmStatement.isWithRecursive(),
1090-
cteStatements,
1091+
cteContainer,
10911092
(NamedTableReference) rootTableGroup.getPrimaryTableReference(),
10921093
Collections.emptyList()
10931094
);
@@ -1370,10 +1371,10 @@ public Values visitValues(SqmValues sqmValues) {
13701371

13711372
@Override
13721373
public SelectStatement visitSelectStatement(SqmSelectStatement<?> statement) {
1373-
Map<String, CteStatement> cteStatements = this.visitCteContainer( statement );
1374+
final CteContainer cteContainer = this.visitCteContainer( statement );
13741375
final QueryPart queryPart = visitQueryPart( statement.getQueryPart() );
13751376
final List<DomainResult<?>> domainResults = queryPart.isRoot() ? this.domainResults : Collections.emptyList();
1376-
return new SelectStatement( statement.isWithRecursive(), cteStatements, queryPart, domainResults );
1377+
return new SelectStatement( cteContainer, queryPart, domainResults );
13771378
}
13781379

13791380
@Override
@@ -1559,14 +1560,15 @@ public static CteTable createCteTable(
15591560
}
15601561

15611562
@Override
1562-
public Map<String, CteStatement> visitCteContainer(SqmCteContainer consumer) {
1563+
public CteContainer visitCteContainer(SqmCteContainer consumer) {
15631564
final Collection<SqmCteStatement<?>> sqmCteStatements = consumer.getCteStatements();
1564-
final Map<String, CteStatement> cteStatements = new LinkedHashMap<>( sqmCteStatements.size() );
1565+
if ( consumer.isWithRecursive() ) {
1566+
cteContainer.setWithRecursive( true );
1567+
}
15651568
for ( SqmCteStatement<?> sqmCteStatement : sqmCteStatements ) {
1566-
final CteStatement cteStatement = visitCteStatement( sqmCteStatement );
1567-
cteStatements.put( cteStatement.getCteTable().getTableExpression(), cteStatement );
1569+
cteContainer.addCteStatement( visitCteStatement( sqmCteStatement ) );
15681570
}
1569-
return cteStatements;
1571+
return cteContainer;
15701572
}
15711573

15721574
private boolean trackSelectionsForGroup;
@@ -1687,6 +1689,7 @@ else if ( sqmQuerySpec.hasPositionalGroupItem() ) {
16871689
// In sub-queries, we can never deduplicate the selection items as that might change semantics
16881690
deduplicateSelectionItems = false;
16891691
pushProcessingState( processingState );
1692+
queryTransformers.push( new ArrayList<>() );
16901693

16911694
try {
16921695
// we want to visit the from-clause first
@@ -1720,14 +1723,23 @@ else if ( sqmQuerySpec.hasPositionalGroupItem() ) {
17201723
applyCollectionFilterPredicates( sqlQuerySpec );
17211724
}
17221725

1723-
return sqlQuerySpec;
1726+
QuerySpec finalQuerySpec = sqlQuerySpec;
1727+
for ( QueryTransformer transformer : queryTransformers.getCurrent() ) {
1728+
finalQuerySpec = transformer.transform(
1729+
cteContainer,
1730+
finalQuerySpec,
1731+
this
1732+
);
1733+
}
1734+
return finalQuerySpec;
17241735
}
17251736
finally {
17261737
if ( additionalRestrictions != null ) {
17271738
sqlQuerySpec.applyPredicate( additionalRestrictions );
17281739
}
17291740
additionalRestrictions = originalAdditionalRestrictions;
17301741
popProcessingStateStack();
1742+
queryTransformers.pop();
17311743
currentSqmQueryPart = sqmQueryPart;
17321744
deduplicateSelectionItems = originalDeduplicateSelectionItems;
17331745
}
@@ -4662,6 +4674,11 @@ public Expression visitFunction(SqmFunction<?> sqmFunction) {
46624674
}
46634675
}
46644676

4677+
@Override
4678+
public void registerQueryTransformer(QueryTransformer transformer) {
4679+
queryTransformers.getCurrent().add( transformer );
4680+
}
4681+
46654682
@Override
46664683
public Star visitStar(SqmStar sqmStar) {
46674684
return new Star();
@@ -6488,4 +6505,38 @@ private static JdbcMappingContainer highestPrecedence(JdbcMappingContainer type1
64886505

64896506
return type1;
64906507
}
6508+
6509+
private class GlobalCteContainer implements CteContainer {
6510+
private final Map<String, CteStatement> cteStatements;
6511+
private boolean recursive;
6512+
6513+
public GlobalCteContainer() {
6514+
this.cteStatements = new LinkedHashMap<>();
6515+
}
6516+
6517+
@Override
6518+
public boolean isWithRecursive() {
6519+
return recursive;
6520+
}
6521+
6522+
@Override
6523+
public void setWithRecursive(boolean recursive) {
6524+
this.recursive = recursive;
6525+
}
6526+
6527+
@Override
6528+
public Map<String, CteStatement> getCteStatements() {
6529+
return cteStatements;
6530+
}
6531+
6532+
@Override
6533+
public CteStatement getCteStatement(String cteLabel) {
6534+
return cteStatements.get( cteLabel );
6535+
}
6536+
6537+
@Override
6538+
public void addCteStatement(CteStatement cteStatement) {
6539+
cteStatements.put( cteStatement.getCteTable().getTableExpression(), cteStatement );
6540+
}
6541+
}
64916542
}

hibernate-core/src/main/java/org/hibernate/query/sqm/sql/FakeSqmToSqlAstConverter.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.hibernate.sql.ast.spi.SqlAstProcessingState;
2222
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
2323
import org.hibernate.sql.ast.tree.expression.Expression;
24+
import org.hibernate.sql.ast.tree.expression.QueryTransformer;
2425
import org.hibernate.sql.ast.tree.predicate.Predicate;
2526

2627
/**
@@ -75,6 +76,10 @@ public Stack<Clause> getCurrentClauseStack() {
7576
return null;
7677
}
7778

79+
@Override
80+
public void registerQueryTransformer(QueryTransformer transformer) {
81+
}
82+
7883
@Override
7984
public List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter<?> sqmParameter) {
8085
return null;

hibernate-core/src/main/java/org/hibernate/query/sqm/sql/SqmToSqlAstConverter.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import org.hibernate.sql.ast.spi.SqlAstCreationState;
1616
import org.hibernate.sql.ast.Clause;
1717
import org.hibernate.sql.ast.tree.expression.Expression;
18+
import org.hibernate.sql.ast.tree.expression.QueryTransformer;
1819
import org.hibernate.sql.ast.tree.predicate.Predicate;
1920

2021
/**
@@ -25,6 +26,8 @@
2526
public interface SqmToSqlAstConverter extends SemanticQueryWalker<Object>, SqlAstCreationState {
2627
Stack<Clause> getCurrentClauseStack();
2728

29+
void registerQueryTransformer(QueryTransformer transformer);
30+
2831
List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter<?> sqmParameter);
2932

3033
Predicate visitNestedTopLevelPredicate(SqmPredicate predicate);

hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstTranslator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1313,7 +1313,7 @@ protected void visitReturningColumns(MutationStatement mutationStatement) {
13131313
}
13141314

13151315
public void visitCteContainer(CteContainer cteContainer) {
1316-
final Collection<CteStatement> cteStatements = cteContainer.getCteStatements();
1316+
final Collection<CteStatement> cteStatements = cteContainer.getCteStatements().values();
13171317
if ( cteStatements.isEmpty() ) {
13181318
return;
13191319
}

hibernate-core/src/main/java/org/hibernate/sql/ast/spi/AbstractSqlAstWalker.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -250,23 +250,23 @@ public void visitOver(Over over) {
250250

251251
@Override
252252
public void visitSelectStatement(SelectStatement statement) {
253-
for ( CteStatement cteStatement : statement.getCteStatements() ) {
253+
for ( CteStatement cteStatement : statement.getCteStatements().values() ) {
254254
cteStatement.getCteDefinition().accept( this );
255255
}
256256
statement.getQueryPart().accept( this );
257257
}
258258

259259
@Override
260260
public void visitDeleteStatement(DeleteStatement statement) {
261-
for ( CteStatement cteStatement : statement.getCteStatements() ) {
261+
for ( CteStatement cteStatement : statement.getCteStatements().values() ) {
262262
cteStatement.getCteDefinition().accept( this );
263263
}
264264
statement.getRestriction().accept( this );
265265
}
266266

267267
@Override
268268
public void visitUpdateStatement(UpdateStatement statement) {
269-
for ( CteStatement cteStatement : statement.getCteStatements() ) {
269+
for ( CteStatement cteStatement : statement.getCteStatements().values() ) {
270270
cteStatement.getCteDefinition().accept( this );
271271
}
272272
for ( Assignment assignment : statement.getAssignments() ) {
@@ -277,7 +277,7 @@ public void visitUpdateStatement(UpdateStatement statement) {
277277

278278
@Override
279279
public void visitInsertStatement(InsertStatement statement) {
280-
for ( CteStatement cteStatement : statement.getCteStatements() ) {
280+
for ( CteStatement cteStatement : statement.getCteStatements().values() ) {
281281
cteStatement.getCteDefinition().accept( this );
282282
}
283283
if ( statement.getSourceSelectStatement() != null ) {

0 commit comments

Comments
 (0)