95
95
import org .hibernate .persister .entity .EntityPersister ;
96
96
import org .hibernate .persister .entity .Joinable ;
97
97
import org .hibernate .persister .entity .SingleTableEntityPersister ;
98
- import org .hibernate .query .sqm .BinaryArithmeticOperator ;
99
98
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 ;
105
99
import org .hibernate .query .QueryLogging ;
106
100
import org .hibernate .query .ReturnableType ;
107
101
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 ;
111
102
import org .hibernate .query .criteria .JpaPath ;
103
+ import org .hibernate .query .spi .NavigablePath ;
112
104
import org .hibernate .query .spi .QueryOptions ;
113
105
import org .hibernate .query .spi .QueryParameterBinding ;
114
106
import org .hibernate .query .spi .QueryParameterBindings ;
115
107
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 ;
116
113
import org .hibernate .query .sqm .InterpretationException ;
114
+ import org .hibernate .query .sqm .SortOrder ;
117
115
import org .hibernate .query .sqm .SqmExpressible ;
118
116
import org .hibernate .query .sqm .SqmPathSource ;
119
117
import org .hibernate .query .sqm .SqmQuerySource ;
118
+ import org .hibernate .query .sqm .TemporalUnit ;
119
+ import org .hibernate .query .sqm .UnaryArithmeticOperator ;
120
120
import org .hibernate .query .sqm .function .AbstractSqmSelfRenderingFunctionDescriptor ;
121
121
import org .hibernate .query .sqm .function .SelfRenderingAggregateFunctionSqlAstExpression ;
122
122
import org .hibernate .query .sqm .function .SelfRenderingFunctionSqlAstExpression ;
262
262
import org .hibernate .sql .ast .tree .SqlAstNode ;
263
263
import org .hibernate .sql .ast .tree .Statement ;
264
264
import org .hibernate .sql .ast .tree .cte .CteColumn ;
265
+ import org .hibernate .sql .ast .tree .cte .CteContainer ;
265
266
import org .hibernate .sql .ast .tree .cte .CteStatement ;
266
267
import org .hibernate .sql .ast .tree .cte .CteTable ;
267
268
import org .hibernate .sql .ast .tree .cte .SearchClauseSpecification ;
288
289
import org .hibernate .sql .ast .tree .expression .Over ;
289
290
import org .hibernate .sql .ast .tree .expression .Overflow ;
290
291
import org .hibernate .sql .ast .tree .expression .QueryLiteral ;
292
+ import org .hibernate .sql .ast .tree .expression .QueryTransformer ;
291
293
import org .hibernate .sql .ast .tree .expression .SelfRenderingExpression ;
292
294
import org .hibernate .sql .ast .tree .expression .SelfRenderingSqlFragmentExpression ;
293
295
import org .hibernate .sql .ast .tree .expression .SqlSelectionExpression ;
@@ -385,6 +387,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
385
387
private final SqlAstCreationContext creationContext ;
386
388
private final boolean jpaQueryComplianceEnabled ;
387
389
private final SqmStatement <?> statement ;
390
+ private final CteContainer cteContainer = new GlobalCteContainer ();
388
391
389
392
private final QueryOptions queryOptions ;
390
393
private final LoadQueryInfluencers loadQueryInfluencers ;
@@ -430,6 +433,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
430
433
private final Stack <Supplier <MappingModelExpressible <?>>> inferrableTypeAccessStack = new StandardStack <>(
431
434
() -> null
432
435
);
436
+ private final Stack <List <QueryTransformer >> queryTransformers = new StandardStack <>();
433
437
private boolean inTypeInference ;
434
438
435
439
private SqmByUnit appliedByUnit ;
@@ -659,7 +663,7 @@ public Statement visitStatement(SqmStatement<?> sqmStatement) {
659
663
660
664
@ Override
661
665
public UpdateStatement visitUpdateStatement (SqmUpdateStatement <?> sqmStatement ) {
662
- Map < String , CteStatement > cteStatements = this .visitCteContainer ( sqmStatement );
666
+ final CteContainer cteContainer = this .visitCteContainer ( sqmStatement );
663
667
664
668
final SqmRoot <?> sqmTarget = sqmStatement .getTarget ();
665
669
final String entityName = sqmTarget .getEntityName ();
@@ -719,7 +723,7 @@ public UpdateStatement visitUpdateStatement(SqmUpdateStatement<?> sqmStatement)
719
723
}
720
724
721
725
return new UpdateStatement (
722
- sqmStatement . isWithRecursive (), cteStatements ,
726
+ cteContainer ,
723
727
(NamedTableReference ) rootTableGroup .getPrimaryTableReference (),
724
728
assignments ,
725
729
SqlAstTreeHelper .combinePredicates ( suppliedPredicate , additionalRestrictions ),
@@ -897,7 +901,7 @@ public Expression resolveSqlExpression(
897
901
898
902
@ Override
899
903
public DeleteStatement visitDeleteStatement (SqmDeleteStatement <?> statement ) {
900
- Map < String , CteStatement > cteStatements = this .visitCteContainer ( statement );
904
+ final CteContainer cteContainer = this .visitCteContainer ( statement );
901
905
902
906
final String entityName = statement .getTarget ().getEntityName ();
903
907
final EntityPersister entityDescriptor = creationContext .getSessionFactory ()
@@ -947,8 +951,7 @@ public DeleteStatement visitDeleteStatement(SqmDeleteStatement<?> statement) {
947
951
}
948
952
949
953
return new DeleteStatement (
950
- statement .isWithRecursive (),
951
- cteStatements ,
954
+ cteContainer ,
952
955
(NamedTableReference ) rootTableGroup .getPrimaryTableReference (),
953
956
SqlAstTreeHelper .combinePredicates ( suppliedPredicate , additionalRestrictions ),
954
957
Collections .emptyList ()
@@ -964,7 +967,7 @@ public DeleteStatement visitDeleteStatement(SqmDeleteStatement<?> statement) {
964
967
965
968
@ Override
966
969
public InsertStatement visitInsertSelectStatement (SqmInsertSelectStatement <?> sqmStatement ) {
967
- Map < String , CteStatement > cteStatements = this .visitCteContainer ( sqmStatement );
970
+ final CteContainer cteContainer = this .visitCteContainer ( sqmStatement );
968
971
969
972
final String entityName = sqmStatement .getTarget ().getEntityName ();
970
973
final EntityPersister entityDescriptor = creationContext .getSessionFactory ()
@@ -1005,8 +1008,7 @@ public InsertStatement visitInsertSelectStatement(SqmInsertSelectStatement<?> sq
1005
1008
getFromClauseAccess ().registerTableGroup ( rootPath , rootTableGroup );
1006
1009
1007
1010
insertStatement = new InsertStatement (
1008
- sqmStatement .isWithRecursive (),
1009
- cteStatements ,
1011
+ cteContainer ,
1010
1012
(NamedTableReference ) rootTableGroup .getPrimaryTableReference (),
1011
1013
Collections .emptyList ()
1012
1014
);
@@ -1051,7 +1053,7 @@ public InsertStatement visitInsertSelectStatement(SqmInsertSelectStatement<?> sq
1051
1053
1052
1054
@ Override
1053
1055
public InsertStatement visitInsertValuesStatement (SqmInsertValuesStatement <?> sqmStatement ) {
1054
- Map < String , CteStatement > cteStatements = this .visitCteContainer ( sqmStatement );
1056
+ final CteContainer cteContainer = this .visitCteContainer ( sqmStatement );
1055
1057
final String entityName = sqmStatement .getTarget ().getEntityName ();
1056
1058
final EntityPersister entityDescriptor = creationContext .getSessionFactory ()
1057
1059
.getRuntimeMetamodels ()
@@ -1087,8 +1089,7 @@ public InsertStatement visitInsertValuesStatement(SqmInsertValuesStatement<?> sq
1087
1089
getFromClauseAccess ().registerTableGroup ( rootPath , rootTableGroup );
1088
1090
1089
1091
final InsertStatement insertStatement = new InsertStatement (
1090
- sqmStatement .isWithRecursive (),
1091
- cteStatements ,
1092
+ cteContainer ,
1092
1093
(NamedTableReference ) rootTableGroup .getPrimaryTableReference (),
1093
1094
Collections .emptyList ()
1094
1095
);
@@ -1371,10 +1372,10 @@ public Values visitValues(SqmValues sqmValues) {
1371
1372
1372
1373
@ Override
1373
1374
public SelectStatement visitSelectStatement (SqmSelectStatement <?> statement ) {
1374
- Map < String , CteStatement > cteStatements = this .visitCteContainer ( statement );
1375
+ final CteContainer cteContainer = this .visitCteContainer ( statement );
1375
1376
final QueryPart queryPart = visitQueryPart ( statement .getQueryPart () );
1376
1377
final List <DomainResult <?>> domainResults = queryPart .isRoot () ? this .domainResults : Collections .emptyList ();
1377
- return new SelectStatement ( statement . isWithRecursive (), cteStatements , queryPart , domainResults );
1378
+ return new SelectStatement ( cteContainer , queryPart , domainResults );
1378
1379
}
1379
1380
1380
1381
@ Override
@@ -1560,14 +1561,15 @@ public static CteTable createCteTable(
1560
1561
}
1561
1562
1562
1563
@ Override
1563
- public Map < String , CteStatement > visitCteContainer (SqmCteContainer consumer ) {
1564
+ public CteContainer visitCteContainer (SqmCteContainer consumer ) {
1564
1565
final Collection <SqmCteStatement <?>> sqmCteStatements = consumer .getCteStatements ();
1565
- final Map <String , CteStatement > cteStatements = new LinkedHashMap <>( sqmCteStatements .size () );
1566
+ if ( consumer .isWithRecursive () ) {
1567
+ cteContainer .setWithRecursive ( true );
1568
+ }
1566
1569
for ( SqmCteStatement <?> sqmCteStatement : sqmCteStatements ) {
1567
- final CteStatement cteStatement = visitCteStatement ( sqmCteStatement );
1568
- cteStatements .put ( cteStatement .getCteTable ().getTableExpression (), cteStatement );
1570
+ cteContainer .addCteStatement ( visitCteStatement ( sqmCteStatement ) );
1569
1571
}
1570
- return cteStatements ;
1572
+ return cteContainer ;
1571
1573
}
1572
1574
1573
1575
private boolean trackSelectionsForGroup ;
@@ -1688,6 +1690,7 @@ else if ( sqmQuerySpec.hasPositionalGroupItem() ) {
1688
1690
// In sub-queries, we can never deduplicate the selection items as that might change semantics
1689
1691
deduplicateSelectionItems = false ;
1690
1692
pushProcessingState ( processingState );
1693
+ queryTransformers .push ( new ArrayList <>() );
1691
1694
1692
1695
try {
1693
1696
// we want to visit the from-clause first
@@ -1721,14 +1724,23 @@ else if ( sqmQuerySpec.hasPositionalGroupItem() ) {
1721
1724
applyCollectionFilterPredicates ( sqlQuerySpec );
1722
1725
}
1723
1726
1724
- return sqlQuerySpec ;
1727
+ QuerySpec finalQuerySpec = sqlQuerySpec ;
1728
+ for ( QueryTransformer transformer : queryTransformers .getCurrent () ) {
1729
+ finalQuerySpec = transformer .transform (
1730
+ cteContainer ,
1731
+ finalQuerySpec ,
1732
+ this
1733
+ );
1734
+ }
1735
+ return finalQuerySpec ;
1725
1736
}
1726
1737
finally {
1727
1738
if ( additionalRestrictions != null ) {
1728
1739
sqlQuerySpec .applyPredicate ( additionalRestrictions );
1729
1740
}
1730
1741
additionalRestrictions = originalAdditionalRestrictions ;
1731
1742
popProcessingStateStack ();
1743
+ queryTransformers .pop ();
1732
1744
currentSqmQueryPart = sqmQueryPart ;
1733
1745
deduplicateSelectionItems = originalDeduplicateSelectionItems ;
1734
1746
}
@@ -4738,6 +4750,11 @@ public Expression visitFunction(SqmFunction<?> sqmFunction) {
4738
4750
}
4739
4751
}
4740
4752
4753
+ @ Override
4754
+ public void registerQueryTransformer (QueryTransformer transformer ) {
4755
+ queryTransformers .getCurrent ().add ( transformer );
4756
+ }
4757
+
4741
4758
@ Override
4742
4759
public Star visitStar (SqmStar sqmStar ) {
4743
4760
return new Star ();
@@ -6564,4 +6581,38 @@ private static JdbcMappingContainer highestPrecedence(JdbcMappingContainer type1
6564
6581
6565
6582
return type1 ;
6566
6583
}
6584
+
6585
+ private class GlobalCteContainer implements CteContainer {
6586
+ private final Map <String , CteStatement > cteStatements ;
6587
+ private boolean recursive ;
6588
+
6589
+ public GlobalCteContainer () {
6590
+ this .cteStatements = new LinkedHashMap <>();
6591
+ }
6592
+
6593
+ @ Override
6594
+ public boolean isWithRecursive () {
6595
+ return recursive ;
6596
+ }
6597
+
6598
+ @ Override
6599
+ public void setWithRecursive (boolean recursive ) {
6600
+ this .recursive = recursive ;
6601
+ }
6602
+
6603
+ @ Override
6604
+ public Map <String , CteStatement > getCteStatements () {
6605
+ return cteStatements ;
6606
+ }
6607
+
6608
+ @ Override
6609
+ public CteStatement getCteStatement (String cteLabel ) {
6610
+ return cteStatements .get ( cteLabel );
6611
+ }
6612
+
6613
+ @ Override
6614
+ public void addCteStatement (CteStatement cteStatement ) {
6615
+ cteStatements .put ( cteStatement .getCteTable ().getTableExpression (), cteStatement );
6616
+ }
6617
+ }
6567
6618
}
0 commit comments