HHH-18178 Validation of CTE source query in `with` method

This commit is contained in:
Marco Belladelli 2024-06-06 10:03:06 +02:00
parent 726ae6a959
commit edc7b5d680
4 changed files with 58 additions and 6 deletions

View File

@ -784,10 +784,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
final HqlParser.QueryExpressionContext queryExpressionContext = (HqlParser.QueryExpressionContext) ctx.getChild( queryExpressionIndex ); final HqlParser.QueryExpressionContext queryExpressionContext = (HqlParser.QueryExpressionContext) ctx.getChild( queryExpressionIndex );
final SqmSelectQuery<Object> cte; final SqmSelectQuery<Object> cte;
if ( cteContainer instanceof SqmSubQuery<?> ) { if ( cteContainer instanceof SqmSubQuery<?> ) {
cte = new SqmSubQuery<>( cte = new SqmSubQuery<>( ( (SqmSubQuery<?>) cteContainer ).getParent(), creationContext.getNodeBuilder() );
processingStateStack.getCurrent().getProcessingQuery(),
creationContext.getNodeBuilder()
);
} }
else { else {
cte = new SqmSelectStatement<>( creationContext.getNodeBuilder() ); cte = new SqmSelectStatement<>( creationContext.getNodeBuilder() );

View File

@ -168,7 +168,7 @@ public abstract class AbstractSqmSelectQuery<T>
return name; return name;
} }
private <X> JpaCteCriteria<X> withInternal(String name, AbstractQuery<X> criteria) { protected <X> JpaCteCriteria<X> withInternal(String name, AbstractQuery<X> criteria) {
final SqmCteStatement<X> cteStatement = new SqmCteStatement<>( final SqmCteStatement<X> cteStatement = new SqmCteStatement<>(
name, name,
(SqmSelectQuery<X>) criteria, (SqmSelectQuery<X>) criteria,
@ -181,7 +181,7 @@ public abstract class AbstractSqmSelectQuery<T>
return cteStatement; return cteStatement;
} }
private <X> JpaCteCriteria<X> withInternal( protected <X> JpaCteCriteria<X> withInternal(
String name, String name,
AbstractQuery<X> baseCriteria, AbstractQuery<X> baseCriteria,
boolean unionDistinct, boolean unionDistinct,

View File

@ -11,10 +11,12 @@ import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.hibernate.Internal; import org.hibernate.Internal;
import org.hibernate.query.criteria.JpaCriteriaQuery; import org.hibernate.query.criteria.JpaCriteriaQuery;
import org.hibernate.query.criteria.JpaCteCriteria;
import org.hibernate.query.criteria.JpaExpression; import org.hibernate.query.criteria.JpaExpression;
import org.hibernate.query.criteria.JpaSelection; import org.hibernate.query.criteria.JpaSelection;
import org.hibernate.query.sqm.FetchClauseType; 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 org.hibernate.query.sqm.tree.from.SqmRoot;
import jakarta.persistence.Tuple; import jakarta.persistence.Tuple;
import jakarta.persistence.criteria.AbstractQuery;
import jakarta.persistence.criteria.Expression; import jakarta.persistence.criteria.Expression;
import jakarta.persistence.criteria.Order; import jakarta.persistence.criteria.Order;
import jakarta.persistence.criteria.ParameterExpression; import jakarta.persistence.criteria.ParameterExpression;
@ -252,6 +255,31 @@ public class SqmSelectStatement<T> extends AbstractSqmSelectQuery<T> implements
parameters.add( parameter ); parameters.add( parameter );
} }
@Override
protected <X> JpaCteCriteria<X> withInternal(String name, AbstractQuery<X> 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 <X> JpaCteCriteria<X> withInternal(
String name,
AbstractQuery<X> baseCriteria,
boolean unionDistinct,
Function<JpaCteCriteria<X>, AbstractQuery<X>> 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 // JPA

View File

@ -14,6 +14,7 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.criteria.JpaCrossJoin; import org.hibernate.query.criteria.JpaCrossJoin;
@ -201,6 +202,32 @@ public class SqmSubQuery<T> extends AbstractSqmSelectQuery<T> implements SqmSele
return ( (JpaCteContainer) parent ).getCteCriteria( cteName ); return ( (JpaCteContainer) parent ).getCteCriteria( cteName );
} }
@Override
protected <X> JpaCteCriteria<X> withInternal(String name, AbstractQuery<X> criteria) {
if ( !( criteria instanceof SqmSubQuery<?> ) || ( (SqmSubQuery<X>) 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 <X> JpaCteCriteria<X> withInternal(
String name,
AbstractQuery<X> baseCriteria,
boolean unionDistinct,
Function<JpaCteCriteria<X>, AbstractQuery<X>> recursiveCriteriaProducer) {
if ( !( baseCriteria instanceof SqmSubQuery<?> ) || ( (SqmSubQuery<X>) 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 @Override
public SqmQuery<?> getContainingQuery() { public SqmQuery<?> getContainingQuery() {
return parent; return parent;