diff --git a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java index 4173f80d59..0be91cfdc2 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java +++ b/hibernate-core/src/main/java/org/hibernate/query/hql/internal/SemanticQueryBuilder.java @@ -784,10 +784,7 @@ public class SemanticQueryBuilder extends HqlParserBaseVisitor implem final HqlParser.QueryExpressionContext queryExpressionContext = (HqlParser.QueryExpressionContext) ctx.getChild( queryExpressionIndex ); final SqmSelectQuery cte; if ( cteContainer instanceof SqmSubQuery ) { - cte = new SqmSubQuery<>( - processingStateStack.getCurrent().getProcessingQuery(), - creationContext.getNodeBuilder() - ); + cte = new SqmSubQuery<>( ( (SqmSubQuery) cteContainer ).getParent(), creationContext.getNodeBuilder() ); } else { cte = new SqmSelectStatement<>( creationContext.getNodeBuilder() ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java index 890e726b0f..05cc41b558 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/AbstractSqmSelectQuery.java @@ -168,7 +168,7 @@ public abstract class AbstractSqmSelectQuery return name; } - private JpaCteCriteria withInternal(String name, AbstractQuery criteria) { + protected JpaCteCriteria withInternal(String name, AbstractQuery criteria) { final SqmCteStatement cteStatement = new SqmCteStatement<>( name, (SqmSelectQuery) criteria, @@ -181,7 +181,7 @@ public abstract class AbstractSqmSelectQuery return cteStatement; } - private JpaCteCriteria withInternal( + protected JpaCteCriteria withInternal( String name, AbstractQuery baseCriteria, boolean unionDistinct, diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectStatement.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectStatement.java index 35c552d36c..6bb0f72a5a 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectStatement.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSelectStatement.java @@ -11,10 +11,12 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; import java.util.stream.Collectors; import org.hibernate.Internal; import org.hibernate.query.criteria.JpaCriteriaQuery; +import org.hibernate.query.criteria.JpaCteCriteria; import org.hibernate.query.criteria.JpaExpression; import org.hibernate.query.criteria.JpaSelection; import org.hibernate.query.sqm.FetchClauseType; @@ -32,6 +34,7 @@ import org.hibernate.query.sqm.tree.predicate.SqmPredicate; import org.hibernate.query.sqm.tree.from.SqmRoot; import jakarta.persistence.Tuple; +import jakarta.persistence.criteria.AbstractQuery; import jakarta.persistence.criteria.Expression; import jakarta.persistence.criteria.Order; import jakarta.persistence.criteria.ParameterExpression; @@ -252,6 +255,31 @@ public class SqmSelectStatement extends AbstractSqmSelectQuery implements parameters.add( parameter ); } + @Override + protected JpaCteCriteria withInternal(String name, AbstractQuery criteria) { + if ( criteria instanceof SqmSubQuery ) { + throw new IllegalArgumentException( + "Invalid query type provided to root query 'with' method, " + + "expecting a root query to use as CTE instead found a subquery" + ); + } + return super.withInternal( name, criteria ); + } + + @Override + protected JpaCteCriteria withInternal( + String name, + AbstractQuery baseCriteria, + boolean unionDistinct, + Function, AbstractQuery> recursiveCriteriaProducer) { + if ( baseCriteria instanceof SqmSubQuery ) { + throw new IllegalArgumentException( + "Invalid query type provided to root query 'with' method, " + + "expecting a root query to use as CTE instead found a subquery" + ); + } + return super.withInternal( name, baseCriteria, unionDistinct, recursiveCriteriaProducer ); + } // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // JPA diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSubQuery.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSubQuery.java index 33d2458d0b..d114170694 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSubQuery.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/tree/select/SqmSubQuery.java @@ -14,6 +14,7 @@ import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.Function; import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.query.criteria.JpaCrossJoin; @@ -201,6 +202,32 @@ public class SqmSubQuery extends AbstractSqmSelectQuery implements SqmSele return ( (JpaCteContainer) parent ).getCteCriteria( cteName ); } + @Override + protected JpaCteCriteria withInternal(String name, AbstractQuery criteria) { + if ( !( criteria instanceof SqmSubQuery ) || ( (SqmSubQuery) criteria ).getParent() != parent ) { + throw new IllegalArgumentException( + "Invalid query type provided to subquery 'with' method, " + + "expecting a subquery with the same parent to use as CTE" + ); + } + return super.withInternal( name, criteria ); + } + + @Override + protected JpaCteCriteria withInternal( + String name, + AbstractQuery baseCriteria, + boolean unionDistinct, + Function, AbstractQuery> recursiveCriteriaProducer) { + if ( !( baseCriteria instanceof SqmSubQuery ) || ( (SqmSubQuery) baseCriteria ).getParent() != parent ) { + throw new IllegalArgumentException( + "Invalid query type provided to subquery 'with' method, " + + "expecting a subquery with the same parent to use as CTE" + ); + } + return super.withInternal( name, baseCriteria, unionDistinct, recursiveCriteriaProducer ); + } + @Override public SqmQuery getContainingQuery() { return parent;