Introduce QueryTransformer for functions

This commit is contained in:
Christian Beikov 2022-02-01 11:44:51 +01:00
parent c2ee076ce6
commit f52cf04a16
16 changed files with 181 additions and 45 deletions

View File

@ -21,6 +21,8 @@
import org.hibernate.query.sqm.tree.predicate.SqmPredicate; import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
import org.hibernate.query.sqm.tree.select.SqmSelectableNode; import org.hibernate.query.sqm.tree.select.SqmSelectableNode;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.predicate.Predicate;
/** /**
* @author Christian Beikov * @author Christian Beikov
@ -73,7 +75,7 @@ public SelfRenderingSqmAggregateFunction<T> copy(SqmCopyContext context) {
} }
@Override @Override
public SelfRenderingFunctionSqlAstExpression convertToSqlAst(SqmToSqlAstConverter walker) { public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
final ReturnableType<?> resultType = resolveResultType( final ReturnableType<?> resultType = resolveResultType(
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration() walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
); );

View File

@ -23,6 +23,7 @@
import org.hibernate.query.sqm.tree.SqmVisitableNode; import org.hibernate.query.sqm.tree.SqmVisitableNode;
import org.hibernate.query.sqm.tree.expression.SqmFunction; import org.hibernate.query.sqm.tree.expression.SqmFunction;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
import static java.util.Collections.emptyList; import static java.util.Collections.emptyList;
@ -109,7 +110,7 @@ protected static List<SqlAstNode> resolveSqlAstArguments(List<? extends SqmTyped
} }
@Override @Override
public SelfRenderingFunctionSqlAstExpression convertToSqlAst(SqmToSqlAstConverter walker) { public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
final ReturnableType<?> resultType = resolveResultType( final ReturnableType<?> resultType = resolveResultType(
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration() walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
); );

View File

@ -25,6 +25,7 @@
import org.hibernate.query.sqm.tree.select.SqmSortSpecification; import org.hibernate.query.sqm.tree.select.SqmSortSpecification;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.ast.tree.select.SortSpecification; import org.hibernate.sql.ast.tree.select.SortSpecification;
@ -91,7 +92,7 @@ public SelfRenderingSqmOrderedSetAggregateFunction<T> copy(SqmCopyContext contex
} }
@Override @Override
public SelfRenderingFunctionSqlAstExpression convertToSqlAst(SqmToSqlAstConverter walker) { public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
final ReturnableType<?> resultType = resolveResultType( final ReturnableType<?> resultType = resolveResultType(
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration() walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
); );

View File

@ -95,28 +95,28 @@
import org.hibernate.persister.entity.EntityPersister; import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable; import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.SingleTableEntityPersister; import org.hibernate.persister.entity.SingleTableEntityPersister;
import org.hibernate.query.sqm.BinaryArithmeticOperator;
import org.hibernate.query.BindableType; import org.hibernate.query.BindableType;
import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.query.sqm.DynamicInstantiationNature;
import org.hibernate.query.sqm.FetchClauseType;
import org.hibernate.query.spi.NavigablePath;
import org.hibernate.query.QueryLogging; import org.hibernate.query.QueryLogging;
import org.hibernate.query.ReturnableType; import org.hibernate.query.ReturnableType;
import org.hibernate.query.SemanticException; import org.hibernate.query.SemanticException;
import org.hibernate.query.sqm.SortOrder;
import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.sqm.UnaryArithmeticOperator;
import org.hibernate.query.criteria.JpaPath; import org.hibernate.query.criteria.JpaPath;
import org.hibernate.query.spi.NavigablePath;
import org.hibernate.query.spi.QueryOptions; import org.hibernate.query.spi.QueryOptions;
import org.hibernate.query.spi.QueryParameterBinding; import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.QueryParameterImplementor; import org.hibernate.query.spi.QueryParameterImplementor;
import org.hibernate.query.sqm.BinaryArithmeticOperator;
import org.hibernate.query.sqm.CastType;
import org.hibernate.query.sqm.ComparisonOperator;
import org.hibernate.query.sqm.DynamicInstantiationNature;
import org.hibernate.query.sqm.FetchClauseType;
import org.hibernate.query.sqm.InterpretationException; import org.hibernate.query.sqm.InterpretationException;
import org.hibernate.query.sqm.SortOrder;
import org.hibernate.query.sqm.SqmExpressible; import org.hibernate.query.sqm.SqmExpressible;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.SqmQuerySource; import org.hibernate.query.sqm.SqmQuerySource;
import org.hibernate.query.sqm.TemporalUnit;
import org.hibernate.query.sqm.UnaryArithmeticOperator;
import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmSelfRenderingFunctionDescriptor;
import org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression; import org.hibernate.query.sqm.function.SelfRenderingAggregateFunctionSqlAstExpression;
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression; import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
@ -262,6 +262,7 @@
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.ast.tree.cte.CteColumn; import org.hibernate.sql.ast.tree.cte.CteColumn;
import org.hibernate.sql.ast.tree.cte.CteContainer;
import org.hibernate.sql.ast.tree.cte.CteStatement; import org.hibernate.sql.ast.tree.cte.CteStatement;
import org.hibernate.sql.ast.tree.cte.CteTable; import org.hibernate.sql.ast.tree.cte.CteTable;
import org.hibernate.sql.ast.tree.cte.SearchClauseSpecification; import org.hibernate.sql.ast.tree.cte.SearchClauseSpecification;
@ -288,6 +289,7 @@
import org.hibernate.sql.ast.tree.expression.Over; import org.hibernate.sql.ast.tree.expression.Over;
import org.hibernate.sql.ast.tree.expression.Overflow; import org.hibernate.sql.ast.tree.expression.Overflow;
import org.hibernate.sql.ast.tree.expression.QueryLiteral; import org.hibernate.sql.ast.tree.expression.QueryLiteral;
import org.hibernate.sql.ast.tree.expression.QueryTransformer;
import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression; import org.hibernate.sql.ast.tree.expression.SelfRenderingExpression;
import org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression; import org.hibernate.sql.ast.tree.expression.SelfRenderingSqlFragmentExpression;
import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression; import org.hibernate.sql.ast.tree.expression.SqlSelectionExpression;
@ -385,6 +387,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
private final SqlAstCreationContext creationContext; private final SqlAstCreationContext creationContext;
private final boolean jpaQueryComplianceEnabled; private final boolean jpaQueryComplianceEnabled;
private final SqmStatement<?> statement; private final SqmStatement<?> statement;
private final CteContainer cteContainer = new GlobalCteContainer();
private final QueryOptions queryOptions; private final QueryOptions queryOptions;
private final LoadQueryInfluencers loadQueryInfluencers; private final LoadQueryInfluencers loadQueryInfluencers;
@ -430,6 +433,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
private final Stack<Supplier<MappingModelExpressible<?>>> inferrableTypeAccessStack = new StandardStack<>( private final Stack<Supplier<MappingModelExpressible<?>>> inferrableTypeAccessStack = new StandardStack<>(
() -> null () -> null
); );
private final Stack<List<QueryTransformer>> queryTransformers = new StandardStack<>();
private boolean inTypeInference; private boolean inTypeInference;
private SqmByUnit appliedByUnit; private SqmByUnit appliedByUnit;
@ -659,7 +663,7 @@ public Statement visitStatement(SqmStatement<?> sqmStatement) {
@Override @Override
public UpdateStatement visitUpdateStatement(SqmUpdateStatement<?> sqmStatement) { public UpdateStatement visitUpdateStatement(SqmUpdateStatement<?> sqmStatement) {
Map<String, CteStatement> cteStatements = this.visitCteContainer( sqmStatement ); final CteContainer cteContainer = this.visitCteContainer( sqmStatement );
final SqmRoot<?> sqmTarget = sqmStatement.getTarget(); final SqmRoot<?> sqmTarget = sqmStatement.getTarget();
final String entityName = sqmTarget.getEntityName(); final String entityName = sqmTarget.getEntityName();
@ -719,7 +723,7 @@ public UpdateStatement visitUpdateStatement(SqmUpdateStatement<?> sqmStatement)
} }
return new UpdateStatement( return new UpdateStatement(
sqmStatement.isWithRecursive(), cteStatements, cteContainer,
(NamedTableReference) rootTableGroup.getPrimaryTableReference(), (NamedTableReference) rootTableGroup.getPrimaryTableReference(),
assignments, assignments,
SqlAstTreeHelper.combinePredicates( suppliedPredicate, additionalRestrictions ), SqlAstTreeHelper.combinePredicates( suppliedPredicate, additionalRestrictions ),
@ -897,7 +901,7 @@ public Expression resolveSqlExpression(
@Override @Override
public DeleteStatement visitDeleteStatement(SqmDeleteStatement<?> statement) { public DeleteStatement visitDeleteStatement(SqmDeleteStatement<?> statement) {
Map<String, CteStatement> cteStatements = this.visitCteContainer( statement ); final CteContainer cteContainer = this.visitCteContainer( statement );
final String entityName = statement.getTarget().getEntityName(); final String entityName = statement.getTarget().getEntityName();
final EntityPersister entityDescriptor = creationContext.getSessionFactory() final EntityPersister entityDescriptor = creationContext.getSessionFactory()
@ -947,8 +951,7 @@ public DeleteStatement visitDeleteStatement(SqmDeleteStatement<?> statement) {
} }
return new DeleteStatement( return new DeleteStatement(
statement.isWithRecursive(), cteContainer,
cteStatements,
(NamedTableReference) rootTableGroup.getPrimaryTableReference(), (NamedTableReference) rootTableGroup.getPrimaryTableReference(),
SqlAstTreeHelper.combinePredicates( suppliedPredicate, additionalRestrictions ), SqlAstTreeHelper.combinePredicates( suppliedPredicate, additionalRestrictions ),
Collections.emptyList() Collections.emptyList()
@ -964,7 +967,7 @@ public DeleteStatement visitDeleteStatement(SqmDeleteStatement<?> statement) {
@Override @Override
public InsertStatement visitInsertSelectStatement(SqmInsertSelectStatement<?> sqmStatement) { public InsertStatement visitInsertSelectStatement(SqmInsertSelectStatement<?> sqmStatement) {
Map<String, CteStatement> cteStatements = this.visitCteContainer( sqmStatement ); final CteContainer cteContainer = this.visitCteContainer( sqmStatement );
final String entityName = sqmStatement.getTarget().getEntityName(); final String entityName = sqmStatement.getTarget().getEntityName();
final EntityPersister entityDescriptor = creationContext.getSessionFactory() final EntityPersister entityDescriptor = creationContext.getSessionFactory()
@ -1005,8 +1008,7 @@ public InsertStatement visitInsertSelectStatement(SqmInsertSelectStatement<?> sq
getFromClauseAccess().registerTableGroup( rootPath, rootTableGroup ); getFromClauseAccess().registerTableGroup( rootPath, rootTableGroup );
insertStatement = new InsertStatement( insertStatement = new InsertStatement(
sqmStatement.isWithRecursive(), cteContainer,
cteStatements,
(NamedTableReference) rootTableGroup.getPrimaryTableReference(), (NamedTableReference) rootTableGroup.getPrimaryTableReference(),
Collections.emptyList() Collections.emptyList()
); );
@ -1051,7 +1053,7 @@ public InsertStatement visitInsertSelectStatement(SqmInsertSelectStatement<?> sq
@Override @Override
public InsertStatement visitInsertValuesStatement(SqmInsertValuesStatement<?> sqmStatement) { public InsertStatement visitInsertValuesStatement(SqmInsertValuesStatement<?> sqmStatement) {
Map<String, CteStatement> cteStatements = this.visitCteContainer( sqmStatement ); final CteContainer cteContainer = this.visitCteContainer( sqmStatement );
final String entityName = sqmStatement.getTarget().getEntityName(); final String entityName = sqmStatement.getTarget().getEntityName();
final EntityPersister entityDescriptor = creationContext.getSessionFactory() final EntityPersister entityDescriptor = creationContext.getSessionFactory()
.getRuntimeMetamodels() .getRuntimeMetamodels()
@ -1087,8 +1089,7 @@ public InsertStatement visitInsertValuesStatement(SqmInsertValuesStatement<?> sq
getFromClauseAccess().registerTableGroup( rootPath, rootTableGroup ); getFromClauseAccess().registerTableGroup( rootPath, rootTableGroup );
final InsertStatement insertStatement = new InsertStatement( final InsertStatement insertStatement = new InsertStatement(
sqmStatement.isWithRecursive(), cteContainer,
cteStatements,
(NamedTableReference) rootTableGroup.getPrimaryTableReference(), (NamedTableReference) rootTableGroup.getPrimaryTableReference(),
Collections.emptyList() Collections.emptyList()
); );
@ -1371,10 +1372,10 @@ public Values visitValues(SqmValues sqmValues) {
@Override @Override
public SelectStatement visitSelectStatement(SqmSelectStatement<?> statement) { public SelectStatement visitSelectStatement(SqmSelectStatement<?> statement) {
Map<String, CteStatement> cteStatements = this.visitCteContainer( statement ); final CteContainer cteContainer = this.visitCteContainer( statement );
final QueryPart queryPart = visitQueryPart( statement.getQueryPart() ); final QueryPart queryPart = visitQueryPart( statement.getQueryPart() );
final List<DomainResult<?>> domainResults = queryPart.isRoot() ? this.domainResults : Collections.emptyList(); final List<DomainResult<?>> domainResults = queryPart.isRoot() ? this.domainResults : Collections.emptyList();
return new SelectStatement( statement.isWithRecursive(), cteStatements, queryPart, domainResults ); return new SelectStatement( cteContainer, queryPart, domainResults );
} }
@Override @Override
@ -1560,14 +1561,15 @@ public static CteTable createCteTable(
} }
@Override @Override
public Map<String, CteStatement> visitCteContainer(SqmCteContainer consumer) { public CteContainer visitCteContainer(SqmCteContainer consumer) {
final Collection<SqmCteStatement<?>> sqmCteStatements = consumer.getCteStatements(); final Collection<SqmCteStatement<?>> sqmCteStatements = consumer.getCteStatements();
final Map<String, CteStatement> cteStatements = new LinkedHashMap<>( sqmCteStatements.size() ); if ( consumer.isWithRecursive() ) {
for ( SqmCteStatement<?> sqmCteStatement : sqmCteStatements ) { cteContainer.setWithRecursive( true );
final CteStatement cteStatement = visitCteStatement( sqmCteStatement );
cteStatements.put( cteStatement.getCteTable().getTableExpression(), cteStatement );
} }
return cteStatements; for ( SqmCteStatement<?> sqmCteStatement : sqmCteStatements ) {
cteContainer.addCteStatement( visitCteStatement( sqmCteStatement ) );
}
return cteContainer;
} }
private boolean trackSelectionsForGroup; private boolean trackSelectionsForGroup;
@ -1688,6 +1690,7 @@ else if ( sqmQuerySpec.hasPositionalGroupItem() ) {
// In sub-queries, we can never deduplicate the selection items as that might change semantics // In sub-queries, we can never deduplicate the selection items as that might change semantics
deduplicateSelectionItems = false; deduplicateSelectionItems = false;
pushProcessingState( processingState ); pushProcessingState( processingState );
queryTransformers.push( new ArrayList<>() );
try { try {
// we want to visit the from-clause first // we want to visit the from-clause first
@ -1721,7 +1724,15 @@ else if ( sqmQuerySpec.hasPositionalGroupItem() ) {
applyCollectionFilterPredicates( sqlQuerySpec ); applyCollectionFilterPredicates( sqlQuerySpec );
} }
return sqlQuerySpec; QuerySpec finalQuerySpec = sqlQuerySpec;
for ( QueryTransformer transformer : queryTransformers.getCurrent() ) {
finalQuerySpec = transformer.transform(
cteContainer,
finalQuerySpec,
this
);
}
return finalQuerySpec;
} }
finally { finally {
if ( additionalRestrictions != null ) { if ( additionalRestrictions != null ) {
@ -1729,6 +1740,7 @@ else if ( sqmQuerySpec.hasPositionalGroupItem() ) {
} }
additionalRestrictions = originalAdditionalRestrictions; additionalRestrictions = originalAdditionalRestrictions;
popProcessingStateStack(); popProcessingStateStack();
queryTransformers.pop();
currentSqmQueryPart = sqmQueryPart; currentSqmQueryPart = sqmQueryPart;
deduplicateSelectionItems = originalDeduplicateSelectionItems; deduplicateSelectionItems = originalDeduplicateSelectionItems;
} }
@ -4738,6 +4750,11 @@ public Expression visitFunction(SqmFunction<?> sqmFunction) {
} }
} }
@Override
public void registerQueryTransformer(QueryTransformer transformer) {
queryTransformers.getCurrent().add( transformer );
}
@Override @Override
public Star visitStar(SqmStar sqmStar) { public Star visitStar(SqmStar sqmStar) {
return new Star(); return new Star();
@ -6564,4 +6581,38 @@ private static JdbcMappingContainer highestPrecedence(JdbcMappingContainer type1
return type1; return type1;
} }
private class GlobalCteContainer implements CteContainer {
private final Map<String, CteStatement> cteStatements;
private boolean recursive;
public GlobalCteContainer() {
this.cteStatements = new LinkedHashMap<>();
}
@Override
public boolean isWithRecursive() {
return recursive;
}
@Override
public void setWithRecursive(boolean recursive) {
this.recursive = recursive;
}
@Override
public Map<String, CteStatement> getCteStatements() {
return cteStatements;
}
@Override
public CteStatement getCteStatement(String cteLabel) {
return cteStatements.get( cteLabel );
}
@Override
public void addCteStatement(CteStatement cteStatement) {
cteStatements.put( cteStatement.getCteTable().getTableExpression(), cteStatement );
}
}
} }

View File

@ -21,6 +21,7 @@
import org.hibernate.sql.ast.spi.SqlAstProcessingState; import org.hibernate.sql.ast.spi.SqlAstProcessingState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver; import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.QueryTransformer;
import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.sql.ast.tree.predicate.Predicate;
/** /**
@ -75,6 +76,10 @@ public Stack<Clause> getCurrentClauseStack() {
return null; return null;
} }
@Override
public void registerQueryTransformer(QueryTransformer transformer) {
}
@Override @Override
public List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter<?> sqmParameter) { public List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter<?> sqmParameter) {
return null; return null;

View File

@ -15,6 +15,7 @@
import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.tree.expression.Expression; import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.QueryTransformer;
import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.sql.ast.tree.predicate.Predicate;
/** /**
@ -25,6 +26,8 @@
public interface SqmToSqlAstConverter extends SemanticQueryWalker<Object>, SqlAstCreationState { public interface SqmToSqlAstConverter extends SemanticQueryWalker<Object>, SqlAstCreationState {
Stack<Clause> getCurrentClauseStack(); Stack<Clause> getCurrentClauseStack();
void registerQueryTransformer(QueryTransformer transformer);
List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter<?> sqmParameter); List<Expression> expandSelfRenderingFunctionMultiValueParameter(SqmParameter<?> sqmParameter);
Predicate visitNestedTopLevelPredicate(SqmPredicate predicate); Predicate visitNestedTopLevelPredicate(SqmPredicate predicate);

View File

@ -1313,7 +1313,7 @@ protected void visitReturningColumns(MutationStatement mutationStatement) {
} }
public void visitCteContainer(CteContainer cteContainer) { public void visitCteContainer(CteContainer cteContainer) {
final Collection<CteStatement> cteStatements = cteContainer.getCteStatements(); final Collection<CteStatement> cteStatements = cteContainer.getCteStatements().values();
if ( cteStatements.isEmpty() ) { if ( cteStatements.isEmpty() ) {
return; return;
} }

View File

@ -250,7 +250,7 @@ public void visitOver(Over over) {
@Override @Override
public void visitSelectStatement(SelectStatement statement) { public void visitSelectStatement(SelectStatement statement) {
for ( CteStatement cteStatement : statement.getCteStatements() ) { for ( CteStatement cteStatement : statement.getCteStatements().values() ) {
cteStatement.getCteDefinition().accept( this ); cteStatement.getCteDefinition().accept( this );
} }
statement.getQueryPart().accept( this ); statement.getQueryPart().accept( this );
@ -258,7 +258,7 @@ public void visitSelectStatement(SelectStatement statement) {
@Override @Override
public void visitDeleteStatement(DeleteStatement statement) { public void visitDeleteStatement(DeleteStatement statement) {
for ( CteStatement cteStatement : statement.getCteStatements() ) { for ( CteStatement cteStatement : statement.getCteStatements().values() ) {
cteStatement.getCteDefinition().accept( this ); cteStatement.getCteDefinition().accept( this );
} }
statement.getRestriction().accept( this ); statement.getRestriction().accept( this );
@ -266,7 +266,7 @@ public void visitDeleteStatement(DeleteStatement statement) {
@Override @Override
public void visitUpdateStatement(UpdateStatement statement) { public void visitUpdateStatement(UpdateStatement statement) {
for ( CteStatement cteStatement : statement.getCteStatements() ) { for ( CteStatement cteStatement : statement.getCteStatements().values() ) {
cteStatement.getCteDefinition().accept( this ); cteStatement.getCteDefinition().accept( this );
} }
for ( Assignment assignment : statement.getAssignments() ) { for ( Assignment assignment : statement.getAssignments() ) {
@ -277,7 +277,7 @@ public void visitUpdateStatement(UpdateStatement statement) {
@Override @Override
public void visitInsertStatement(InsertStatement statement) { public void visitInsertStatement(InsertStatement statement) {
for ( CteStatement cteStatement : statement.getCteStatements() ) { for ( CteStatement cteStatement : statement.getCteStatements().values() ) {
cteStatement.getCteDefinition().accept( this ); cteStatement.getCteDefinition().accept( this );
} }
if ( statement.getSourceSelectStatement() != null ) { if ( statement.getSourceSelectStatement() != null ) {

View File

@ -35,8 +35,8 @@ public void setWithRecursive(boolean withRecursive) {
} }
@Override @Override
public Collection<CteStatement> getCteStatements() { public Map<String, CteStatement> getCteStatements() {
return cteStatements.values(); return cteStatements;
} }
@Override @Override

View File

@ -6,7 +6,7 @@
*/ */
package org.hibernate.sql.ast.tree.cte; package org.hibernate.sql.ast.tree.cte;
import java.util.Collection; import java.util.Map;
/** /**
* The consumer part of a CTE statement - the select or insert or delete or update that uses * The consumer part of a CTE statement - the select or insert or delete or update that uses
@ -21,7 +21,7 @@ public interface CteContainer {
void setWithRecursive(boolean recursive); void setWithRecursive(boolean recursive);
Collection<CteStatement> getCteStatements(); Map<String, CteStatement> getCteStatements();
CteStatement getCteStatement(String cteLabel); CteStatement getCteStatement(String cteLabel);

View File

@ -13,6 +13,7 @@
import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlAstHelper; import org.hibernate.sql.ast.spi.SqlAstHelper;
import org.hibernate.sql.ast.tree.AbstractMutationStatement; import org.hibernate.sql.ast.tree.AbstractMutationStatement;
import org.hibernate.sql.ast.tree.cte.CteContainer;
import org.hibernate.sql.ast.tree.cte.CteStatement; import org.hibernate.sql.ast.tree.cte.CteStatement;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.from.NamedTableReference; import org.hibernate.sql.ast.tree.from.NamedTableReference;
@ -40,6 +41,20 @@ public DeleteStatement(
this.restriction = restriction; this.restriction = restriction;
} }
public DeleteStatement(
CteContainer cteContainer,
NamedTableReference targetTable,
Predicate restriction,
List<ColumnReference> returningColumns) {
this(
cteContainer.isWithRecursive(),
cteContainer.getCteStatements(),
targetTable,
restriction,
returningColumns
);
}
public DeleteStatement( public DeleteStatement(
boolean withRecursive, boolean withRecursive,
Map<String, CteStatement> cteStatements, Map<String, CteStatement> cteStatements,

View File

@ -0,0 +1,22 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
*/
package org.hibernate.sql.ast.tree.expression;
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.sql.ast.tree.cte.CteContainer;
import org.hibernate.sql.ast.tree.select.QuerySpec;
/**
* @author Christian Beikov
*/
public interface QueryTransformer {
QuerySpec transform(
CteContainer cteContainer,
QuerySpec querySpec,
SqmToSqlAstConverter converter);
}

View File

@ -14,6 +14,7 @@
import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.tree.AbstractMutationStatement; import org.hibernate.sql.ast.tree.AbstractMutationStatement;
import org.hibernate.sql.ast.tree.cte.CteContainer;
import org.hibernate.sql.ast.tree.cte.CteStatement; import org.hibernate.sql.ast.tree.cte.CteStatement;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.from.NamedTableReference; import org.hibernate.sql.ast.tree.from.NamedTableReference;
@ -37,7 +38,18 @@ public InsertStatement(NamedTableReference targetTable, List<ColumnReference> re
super( new LinkedHashMap<>(), targetTable, returningColumns ); super( new LinkedHashMap<>(), targetTable, returningColumns );
} }
public InsertStatement(boolean withRecursive, Map<String, CteStatement> cteStatements, NamedTableReference targetTable, List<ColumnReference> returningColumns) { public InsertStatement(
CteContainer cteContainer,
NamedTableReference targetTable,
List<ColumnReference> returningColumns) {
this( cteContainer.isWithRecursive(), cteContainer.getCteStatements(), targetTable, returningColumns );
}
public InsertStatement(
boolean withRecursive,
Map<String, CteStatement> cteStatements,
NamedTableReference targetTable,
List<ColumnReference> returningColumns) {
super( cteStatements, targetTable, returningColumns ); super( cteStatements, targetTable, returningColumns );
setWithRecursive( withRecursive ); setWithRecursive( withRecursive );
} }

View File

@ -13,6 +13,7 @@
import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.tree.AbstractStatement; import org.hibernate.sql.ast.tree.AbstractStatement;
import org.hibernate.sql.ast.tree.cte.CteContainer;
import org.hibernate.sql.ast.tree.cte.CteStatement; import org.hibernate.sql.ast.tree.cte.CteStatement;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
@ -31,6 +32,13 @@ public SelectStatement(QueryPart queryPart, List<DomainResult<?>> domainResults)
this( false, new LinkedHashMap<>(), queryPart, domainResults ); this( false, new LinkedHashMap<>(), queryPart, domainResults );
} }
public SelectStatement(
CteContainer cteContainer,
QueryPart queryPart,
List<DomainResult<?>> domainResults) {
this( cteContainer.isWithRecursive(), cteContainer.getCteStatements(), queryPart, domainResults );
}
public SelectStatement( public SelectStatement(
boolean withRecursive, boolean withRecursive,
Map<String, CteStatement> cteStatements, Map<String, CteStatement> cteStatements,

View File

@ -14,6 +14,7 @@
import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.spi.SqlAstTreeHelper; import org.hibernate.sql.ast.spi.SqlAstTreeHelper;
import org.hibernate.sql.ast.tree.AbstractMutationStatement; import org.hibernate.sql.ast.tree.AbstractMutationStatement;
import org.hibernate.sql.ast.tree.cte.CteContainer;
import org.hibernate.sql.ast.tree.cte.CteStatement; import org.hibernate.sql.ast.tree.cte.CteStatement;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.from.NamedTableReference; import org.hibernate.sql.ast.tree.from.NamedTableReference;
@ -45,6 +46,22 @@ public UpdateStatement(
this.restriction = restriction; this.restriction = restriction;
} }
public UpdateStatement(
CteContainer cteContainer,
NamedTableReference targetTable,
List<Assignment> assignments,
Predicate restriction,
List<ColumnReference> returningColumns) {
this(
cteContainer.isWithRecursive(),
cteContainer.getCteStatements(),
targetTable,
assignments,
restriction,
returningColumns
);
}
public UpdateStatement( public UpdateStatement(
boolean withRecursive, boolean withRecursive,
Map<String, CteStatement> cteStatements, Map<String, CteStatement> cteStatements,

View File

@ -20,7 +20,6 @@
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor; import org.hibernate.query.sqm.function.AbstractSqmFunctionDescriptor;
import org.hibernate.query.sqm.function.FunctionRenderingSupport; import org.hibernate.query.sqm.function.FunctionRenderingSupport;
import org.hibernate.query.sqm.function.SelfRenderingFunctionSqlAstExpression;
import org.hibernate.query.sqm.function.SelfRenderingSqmFunction; import org.hibernate.query.sqm.function.SelfRenderingSqmFunction;
import org.hibernate.query.sqm.function.SqmFunctionDescriptor; import org.hibernate.query.sqm.function.SqmFunctionDescriptor;
import org.hibernate.query.sqm.produce.function.ArgumentsValidator; import org.hibernate.query.sqm.produce.function.ArgumentsValidator;
@ -31,9 +30,9 @@
import org.hibernate.query.sqm.sql.SqmToSqlAstConverter; import org.hibernate.query.sqm.sql.SqmToSqlAstConverter;
import org.hibernate.query.sqm.tree.SqmCopyContext; import org.hibernate.query.sqm.tree.SqmCopyContext;
import org.hibernate.query.sqm.tree.SqmTypedNode; import org.hibernate.query.sqm.tree.SqmTypedNode;
import org.hibernate.query.sqm.tree.expression.SqmAny;
import org.hibernate.query.sqm.tree.expression.SqmLiteral; import org.hibernate.query.sqm.tree.expression.SqmLiteral;
import org.hibernate.sql.ast.spi.SqlAstQueryPartProcessingState; import org.hibernate.sql.ast.spi.SqlAstQueryPartProcessingState;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.DelegatingTableGroup; import org.hibernate.sql.ast.tree.from.DelegatingTableGroup;
import org.hibernate.sql.ast.tree.from.NamedTableReference; import org.hibernate.sql.ast.tree.from.NamedTableReference;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
@ -174,7 +173,7 @@ public OrderByFragmentSelfRenderingSqmFunction<T> copy(SqmCopyContext context) {
} }
@Override @Override
public SelfRenderingFunctionSqlAstExpression convertToSqlAst(SqmToSqlAstConverter walker) { public Expression convertToSqlAst(SqmToSqlAstConverter walker) {
final ReturnableType<?> resultType = resolveResultType( final ReturnableType<?> resultType = resolveResultType(
walker.getCreationContext().getMappingMetamodel().getTypeConfiguration() walker.getCreationContext().getMappingMetamodel().getTypeConfiguration()
); );