mirror of
https://github.com/hibernate/hibernate-orm
synced 2025-02-22 19:15:15 +00:00
Flatten the junctions in the SQM model
This commit is contained in:
parent
71e3b5277a
commit
0a73425520
@ -49,17 +49,16 @@
|
||||
import org.hibernate.query.sqm.tree.from.SqmFromClause;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmEmptinessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInSubQueryPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmJunctionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmLikePredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmOrPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
@ -598,19 +597,14 @@ public SqmGroupedPredicate visitGroupedPredicate(SqmGroupedPredicate predicate)
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmAndPredicate visitAndPredicate(SqmAndPredicate predicate) {
|
||||
return new SqmAndPredicate(
|
||||
(SqmPredicate) predicate.getLeftHandPredicate().accept( this ),
|
||||
(SqmPredicate) predicate.getRightHandPredicate().accept( this ),
|
||||
getCreationContext().getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmOrPredicate visitOrPredicate(SqmOrPredicate predicate) {
|
||||
return new SqmOrPredicate(
|
||||
(SqmPredicate) predicate.getLeftHandPredicate().accept( this ),
|
||||
(SqmPredicate) predicate.getRightHandPredicate().accept( this ),
|
||||
public SqmJunctionPredicate visitJunctionPredicate(SqmJunctionPredicate predicate) {
|
||||
final List<SqmPredicate> predicates = new ArrayList<>( predicate.getPredicates().size() );
|
||||
for ( SqmPredicate subPredicate : predicate.getPredicates() ) {
|
||||
predicates.add( (SqmPredicate) subPredicate.accept( this ) );
|
||||
}
|
||||
return new SqmJunctionPredicate(
|
||||
predicate.getOperator(),
|
||||
predicates,
|
||||
getCreationContext().getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
@ -151,7 +151,6 @@
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmValues;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||
@ -160,12 +159,12 @@
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInSubQueryPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmJunctionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmLikePredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNegatablePredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmOrPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.AbstractSqmSelectQuery;
|
||||
@ -191,6 +190,7 @@
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
import jakarta.persistence.metamodel.SingularAttribute;
|
||||
import org.antlr.v4.runtime.ParserRuleContext;
|
||||
import org.antlr.v4.runtime.Token;
|
||||
@ -1784,18 +1784,41 @@ public SqmGroupedPredicate visitGroupedPredicate(HqlParser.GroupedPredicateConte
|
||||
|
||||
@Override
|
||||
public SqmPredicate visitAndPredicate(HqlParser.AndPredicateContext ctx) {
|
||||
return new SqmAndPredicate(
|
||||
return junction(
|
||||
Predicate.BooleanOperator.AND,
|
||||
(SqmPredicate) ctx.getChild( 0 ).accept( this ),
|
||||
(SqmPredicate) ctx.getChild( 2 ).accept( this ),
|
||||
creationContext.getNodeBuilder()
|
||||
(SqmPredicate) ctx.getChild( 2 ).accept( this )
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate visitOrPredicate(HqlParser.OrPredicateContext ctx) {
|
||||
return new SqmOrPredicate(
|
||||
return junction(
|
||||
Predicate.BooleanOperator.OR,
|
||||
(SqmPredicate) ctx.getChild( 0 ).accept( this ),
|
||||
(SqmPredicate) ctx.getChild( 2 ).accept( this ),
|
||||
(SqmPredicate) ctx.getChild( 2 ).accept( this )
|
||||
);
|
||||
}
|
||||
|
||||
private SqmPredicate junction(Predicate.BooleanOperator operator, SqmPredicate lhs, SqmPredicate rhs) {
|
||||
if ( lhs instanceof SqmJunctionPredicate ) {
|
||||
final SqmJunctionPredicate junction = (SqmJunctionPredicate) lhs;
|
||||
if ( junction.getOperator() == operator ) {
|
||||
junction.getPredicates().add( rhs );
|
||||
return junction;
|
||||
}
|
||||
}
|
||||
if ( rhs instanceof SqmJunctionPredicate ) {
|
||||
final SqmJunctionPredicate junction = (SqmJunctionPredicate) rhs;
|
||||
if ( junction.getOperator() == operator ) {
|
||||
junction.getPredicates().add( 0, lhs );
|
||||
return junction;
|
||||
}
|
||||
}
|
||||
return new SqmJunctionPredicate(
|
||||
operator,
|
||||
lhs,
|
||||
rhs,
|
||||
creationContext.getNodeBuilder()
|
||||
);
|
||||
}
|
||||
|
@ -66,7 +66,6 @@
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmValues;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||
@ -75,11 +74,11 @@
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInSubQueryPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmJunctionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmLikePredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmOrPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
@ -256,9 +255,7 @@ public interface SemanticQueryWalker<T> {
|
||||
|
||||
T visitGroupedPredicate(SqmGroupedPredicate predicate);
|
||||
|
||||
T visitAndPredicate(SqmAndPredicate predicate);
|
||||
|
||||
T visitOrPredicate(SqmOrPredicate predicate);
|
||||
T visitJunctionPredicate(SqmJunctionPredicate predicate);
|
||||
|
||||
T visitComparisonPredicate(SqmComparisonPredicate predicate);
|
||||
|
||||
|
@ -51,7 +51,6 @@
|
||||
import org.hibernate.query.criteria.JpaCriteriaQuery;
|
||||
import org.hibernate.query.criteria.JpaExpression;
|
||||
import org.hibernate.query.criteria.JpaOrder;
|
||||
import org.hibernate.query.criteria.JpaParameterExpression;
|
||||
import org.hibernate.query.criteria.JpaSelection;
|
||||
import org.hibernate.query.criteria.ValueHandlingMode;
|
||||
import org.hibernate.query.spi.QueryEngine;
|
||||
@ -90,7 +89,6 @@
|
||||
import org.hibernate.query.sqm.tree.expression.SqmUnaryOperation;
|
||||
import org.hibernate.query.sqm.tree.from.SqmRoot;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||
@ -99,10 +97,10 @@
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInSubQueryPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmJunctionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmLikePredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmOrPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiationArgument;
|
||||
@ -337,13 +335,11 @@ public final SqmPredicate wrap(Expression<Boolean>... expressions) {
|
||||
return wrap( expressions[0] );
|
||||
}
|
||||
|
||||
final SqmPredicate lhs = wrap( expressions[0] );
|
||||
final SqmPredicate rhs = wrap( expressions[1] );
|
||||
SqmPredicate predicate = new SqmAndPredicate( lhs, rhs, this );
|
||||
for ( int i = 2; i < expressions.length; i++ ) {
|
||||
predicate = new SqmAndPredicate( predicate, wrap( expressions[i] ), this );
|
||||
final List<SqmPredicate> predicates = new ArrayList<>( expressions.length );
|
||||
for ( Expression<Boolean> expression : expressions ) {
|
||||
predicates.add( wrap( expression ) );
|
||||
}
|
||||
return predicate;
|
||||
return new SqmJunctionPredicate( Predicate.BooleanOperator.AND, predicates, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -1567,7 +1563,8 @@ public <R> SqmCaseSearched<R> selectCase() {
|
||||
|
||||
@Override
|
||||
public SqmPredicate and(Expression<Boolean> x, Expression<Boolean> y) {
|
||||
return new SqmAndPredicate(
|
||||
return new SqmJunctionPredicate(
|
||||
Predicate.BooleanOperator.AND,
|
||||
wrap( x ),
|
||||
wrap( y ),
|
||||
this
|
||||
@ -1580,17 +1577,17 @@ public SqmPredicate and(Predicate... restrictions) {
|
||||
return conjunction();
|
||||
}
|
||||
|
||||
SqmPredicate junction = (SqmPredicate) restrictions[0];
|
||||
for ( int i = 1; i < restrictions.length; i++ ) {
|
||||
junction = new SqmAndPredicate( junction, (SqmPredicate) restrictions[i], this );
|
||||
final List<SqmPredicate> predicates = new ArrayList<>( restrictions.length );
|
||||
for ( Predicate expression : restrictions ) {
|
||||
predicates.add( (SqmPredicate) expression );
|
||||
}
|
||||
|
||||
return junction;
|
||||
return new SqmJunctionPredicate( Predicate.BooleanOperator.AND, predicates, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate or(Expression<Boolean> x, Expression<Boolean> y) {
|
||||
return new SqmOrPredicate(
|
||||
return new SqmJunctionPredicate(
|
||||
Predicate.BooleanOperator.OR,
|
||||
wrap( x ),
|
||||
wrap( y ),
|
||||
this
|
||||
@ -1603,12 +1600,11 @@ public SqmPredicate or(Predicate... restrictions) {
|
||||
return disjunction();
|
||||
}
|
||||
|
||||
SqmPredicate junction = (SqmPredicate) restrictions[0];
|
||||
for ( int i = 1; i < restrictions.length; i++ ) {
|
||||
junction = new SqmOrPredicate( junction, (SqmPredicate) restrictions[i], this );
|
||||
final List<SqmPredicate> predicates = new ArrayList<>( restrictions.length );
|
||||
for ( Predicate expression : restrictions ) {
|
||||
predicates.add( (SqmPredicate) expression );
|
||||
}
|
||||
|
||||
return junction;
|
||||
return new SqmJunctionPredicate( Predicate.BooleanOperator.OR, predicates, this );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -73,7 +73,6 @@
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmValues;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||
@ -82,11 +81,11 @@
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInSubQueryPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmJunctionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmLikePredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmOrPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
@ -107,6 +106,8 @@
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import jakarta.persistence.criteria.Predicate;
|
||||
|
||||
/**
|
||||
* Printer for an SQM tree - for debugging purpose
|
||||
*
|
||||
@ -800,25 +801,13 @@ public Object visitGroupedPredicate(SqmGroupedPredicate predicate) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAndPredicate(SqmAndPredicate predicate) {
|
||||
public Object visitJunctionPredicate(SqmJunctionPredicate predicate) {
|
||||
processStanza(
|
||||
"and",
|
||||
predicate.getOperator() == Predicate.BooleanOperator.AND ? "and" : "or",
|
||||
() -> {
|
||||
predicate.getLeftHandPredicate().accept( this );
|
||||
predicate.getRightHandPredicate().accept( this );
|
||||
}
|
||||
);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitOrPredicate(SqmOrPredicate predicate) {
|
||||
processStanza(
|
||||
"or",
|
||||
() -> {
|
||||
predicate.getLeftHandPredicate().accept( this );
|
||||
predicate.getRightHandPredicate().accept( this );
|
||||
for ( SqmPredicate subPredicate : predicate.getPredicates() ) {
|
||||
subPredicate.accept( this );
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -72,7 +72,6 @@
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertSelectStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmValues;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||
@ -81,11 +80,11 @@
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInSubQueryPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmJunctionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmLikePredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmOrPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.SqmDynamicInstantiation;
|
||||
@ -393,16 +392,10 @@ public Object visitGroupedPredicate(SqmGroupedPredicate predicate) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitAndPredicate(SqmAndPredicate predicate) {
|
||||
predicate.getLeftHandPredicate().accept( this );
|
||||
predicate.getRightHandPredicate().accept( this );
|
||||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object visitOrPredicate(SqmOrPredicate predicate) {
|
||||
predicate.getLeftHandPredicate().accept( this );
|
||||
predicate.getRightHandPredicate().accept( this );
|
||||
public Object visitJunctionPredicate(SqmJunctionPredicate predicate) {
|
||||
for ( SqmPredicate subPredicate : predicate.getPredicates() ) {
|
||||
subPredicate.accept( this );
|
||||
}
|
||||
return predicate;
|
||||
}
|
||||
|
||||
|
@ -218,7 +218,6 @@
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmInsertValuesStatement;
|
||||
import org.hibernate.query.sqm.tree.insert.SqmValues;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmAndPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBetweenPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmBooleanExpressionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmComparisonPredicate;
|
||||
@ -227,11 +226,11 @@
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmGroupedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInListPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmInSubQueryPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmJunctionPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmLikePredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmMemberOfPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNegatedPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmNullnessPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmOrPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmPredicate;
|
||||
import org.hibernate.query.sqm.tree.predicate.SqmWhereClause;
|
||||
import org.hibernate.query.sqm.tree.select.SqmAliasedNode;
|
||||
@ -5747,77 +5746,86 @@ public GroupedPredicate visitGroupedPredicate(SqmGroupedPredicate predicate) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Junction visitAndPredicate(SqmAndPredicate predicate) {
|
||||
final Junction conjunction = new Junction( Junction.Nature.CONJUNCTION, getBooleanType() );
|
||||
conjunction.add( (Predicate) predicate.getLeftHandPredicate().accept( this ) );
|
||||
conjunction.add( (Predicate) predicate.getRightHandPredicate().accept( this ) );
|
||||
return conjunction;
|
||||
}
|
||||
public Junction visitJunctionPredicate(SqmJunctionPredicate predicate) {
|
||||
if ( predicate.getOperator() == jakarta.persistence.criteria.Predicate.BooleanOperator.AND ) {
|
||||
final List<Predicate> predicates = new ArrayList<>( predicate.getPredicates().size() );
|
||||
for ( SqmPredicate subPredicate : predicate.getPredicates() ) {
|
||||
predicates.add( (Predicate) subPredicate.accept( this ) );
|
||||
}
|
||||
return new Junction( Junction.Nature.CONJUNCTION, predicates, getBooleanType() );
|
||||
}
|
||||
final Junction disjunction = new Junction(
|
||||
Junction.Nature.DISJUNCTION,
|
||||
new ArrayList<>( predicate.getPredicates().size() ),
|
||||
getBooleanType()
|
||||
);
|
||||
final List<Map<SqmPath<?>, Set<String>>> conjunctTreatUsagesList = new ArrayList<>( predicate.getPredicates().size() );
|
||||
final Map<SqmPath<?>, Set<String>> conjunctTreatUsagesUnion = new IdentityHashMap<>();
|
||||
boolean hasAnyTreatUsage = false;
|
||||
for ( SqmPredicate subPredicate : predicate.getPredicates() ) {
|
||||
disjunction.add( (Predicate) subPredicate.accept( this ) );
|
||||
if ( conjunctTreatUsages.isEmpty() ) {
|
||||
conjunctTreatUsagesList.add( null );
|
||||
}
|
||||
else {
|
||||
hasAnyTreatUsage = true;
|
||||
for ( Map.Entry<SqmPath<?>, Set<String>> entry : conjunctTreatUsages.entrySet() ) {
|
||||
conjunctTreatUsagesUnion.computeIfAbsent( entry.getKey(), k -> new HashSet<>() )
|
||||
.addAll( entry.getValue() );
|
||||
}
|
||||
conjunctTreatUsagesList.add( new IdentityHashMap<>( conjunctTreatUsages ) );
|
||||
conjunctTreatUsages.clear();
|
||||
}
|
||||
}
|
||||
if ( !hasAnyTreatUsage ) {
|
||||
return disjunction;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Junction visitOrPredicate(SqmOrPredicate predicate) {
|
||||
final Junction disjunction = new Junction( Junction.Nature.DISJUNCTION, getBooleanType() );
|
||||
final Predicate predicate1 = (Predicate) predicate.getLeftHandPredicate().accept( this );
|
||||
final Map<SqmPath<?>, Set<String>> conjunctTreatUsages1;
|
||||
if ( conjunctTreatUsages.isEmpty() ) {
|
||||
conjunctTreatUsages1 = null;
|
||||
}
|
||||
else {
|
||||
conjunctTreatUsages1 = new IdentityHashMap<>( conjunctTreatUsages );
|
||||
conjunctTreatUsages.clear();
|
||||
}
|
||||
final Predicate predicate2 = (Predicate) predicate.getRightHandPredicate().accept( this );
|
||||
if ( conjunctTreatUsages.isEmpty() || conjunctTreatUsages1 == null ) {
|
||||
disjunction.add(
|
||||
SqlAstTreeHelper.combinePredicates(
|
||||
consumeConjunctTreatTypeRestrictions( conjunctTreatUsages1 ),
|
||||
predicate1
|
||||
)
|
||||
);
|
||||
disjunction.add( predicate2 );
|
||||
}
|
||||
else {
|
||||
// If both disjunctions have treat type restrictions build the intersection of the two,
|
||||
// so that we can push that up and infer during pruning, which entity subclasses can be omitted
|
||||
final Map<SqmPath<?>, Set<String>> conjunctTreatUsages2 = new IdentityHashMap<>( conjunctTreatUsages );
|
||||
final Iterator<Map.Entry<SqmPath<?>, Set<String>>> iterator = conjunctTreatUsages.entrySet().iterator();
|
||||
while ( iterator.hasNext() ) {
|
||||
final Map.Entry<SqmPath<?>, Set<String>> entry = iterator.next();
|
||||
final Set<String> entityNames1 = conjunctTreatUsages1.get( entry.getKey() );
|
||||
if ( entityNames1 == null ) {
|
||||
iterator.remove();
|
||||
// Build the intersection of the conjunct treat usages,
|
||||
// so that we can push that up and infer during pruning, which entity subclasses can be omitted
|
||||
conjunctTreatUsages.putAll( conjunctTreatUsagesUnion );
|
||||
|
||||
final Iterator<Map.Entry<SqmPath<?>, Set<String>>> iterator = conjunctTreatUsages.entrySet().iterator();
|
||||
while ( iterator.hasNext() ) {
|
||||
final Map.Entry<SqmPath<?>, Set<String>> entry = iterator.next();
|
||||
final Set<String> intersected = new HashSet<>( entry.getValue() );
|
||||
entry.setValue( intersected );
|
||||
boolean remove = false;
|
||||
for ( Map<SqmPath<?>, Set<String>> conjunctTreatUsages : conjunctTreatUsagesList ) {
|
||||
final Set<String> entityNames = conjunctTreatUsages.get( entry.getKey() );
|
||||
if ( entityNames == null ) {
|
||||
remove = true;
|
||||
continue;
|
||||
}
|
||||
// Intersect the two sets and transfer the common elements to the intersection
|
||||
final Set<String> entityNames2 = entry.getValue();
|
||||
final Set<String> intersected = new HashSet<>( entityNames1 );
|
||||
intersected.retainAll( entityNames2 );
|
||||
intersected.retainAll( entityNames );
|
||||
if ( intersected.isEmpty() ) {
|
||||
iterator.remove();
|
||||
remove = true;
|
||||
continue;
|
||||
}
|
||||
entry.setValue( intersected );
|
||||
entityNames1.removeAll( intersected );
|
||||
entityNames2.removeAll( intersected );
|
||||
if ( entityNames1.isEmpty() ) {
|
||||
conjunctTreatUsages1.remove( entry.getKey() );
|
||||
}
|
||||
if ( entityNames2.isEmpty() ) {
|
||||
conjunctTreatUsages2.remove( entry.getKey() );
|
||||
entityNames.removeAll( intersected );
|
||||
if ( entityNames.isEmpty() ) {
|
||||
conjunctTreatUsages.remove( entry.getKey() );
|
||||
}
|
||||
}
|
||||
disjunction.add(
|
||||
SqlAstTreeHelper.combinePredicates(
|
||||
consumeConjunctTreatTypeRestrictions( conjunctTreatUsages1 ),
|
||||
predicate1
|
||||
)
|
||||
);
|
||||
disjunction.add(
|
||||
SqlAstTreeHelper.combinePredicates(
|
||||
consumeConjunctTreatTypeRestrictions( conjunctTreatUsages2 ),
|
||||
predicate2
|
||||
)
|
||||
);
|
||||
|
||||
if ( remove ) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// Prepend the treat type usages to the respective conjuncts
|
||||
for ( int i = 0; i < conjunctTreatUsagesList.size(); i++ ) {
|
||||
final Map<SqmPath<?>, Set<String>> conjunctTreatUsages = conjunctTreatUsagesList.get( i );
|
||||
if ( conjunctTreatUsages != null ) {
|
||||
disjunction.getPredicates().set(
|
||||
i,
|
||||
SqlAstTreeHelper.combinePredicates(
|
||||
consumeConjunctTreatTypeRestrictions( conjunctTreatUsages ),
|
||||
disjunction.getPredicates().get( i )
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
return disjunction;
|
||||
}
|
||||
|
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* 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.query.sqm.tree.predicate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmAndPredicate extends AbstractSqmPredicate implements SqmJunctivePredicate {
|
||||
private final SqmPredicate leftHandPredicate;
|
||||
private final SqmPredicate rightHandPredicate;
|
||||
|
||||
public SqmAndPredicate(
|
||||
SqmPredicate leftHandPredicate,
|
||||
SqmPredicate rightHandPredicate,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( leftHandPredicate.getExpressible(), nodeBuilder );
|
||||
this.leftHandPredicate = leftHandPredicate;
|
||||
this.rightHandPredicate = rightHandPredicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmAndPredicate copy(SqmCopyContext context) {
|
||||
final SqmAndPredicate existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmAndPredicate predicate = context.registerCopy(
|
||||
this,
|
||||
new SqmAndPredicate(
|
||||
leftHandPredicate.copy( context ),
|
||||
rightHandPredicate.copy( context ),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( predicate, context );
|
||||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate getLeftHandPredicate() {
|
||||
return leftHandPredicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate getRightHandPredicate() {
|
||||
return rightHandPredicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(SemanticQueryWalker<T> walker) {
|
||||
return walker.visitAndPredicate( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public BooleanOperator getOperator() {
|
||||
return BooleanOperator.AND;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNegated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Expression<Boolean>> getExpressions() {
|
||||
return Arrays.asList( leftHandPredicate, rightHandPredicate );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate not() {
|
||||
return new SqmNegatedPredicate( this, nodeBuilder() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHqlString(StringBuilder sb) {
|
||||
if ( leftHandPredicate instanceof SqmOrPredicate ) {
|
||||
sb.append( '(' );
|
||||
leftHandPredicate.appendHqlString( sb );
|
||||
sb.append( ')' );
|
||||
}
|
||||
else {
|
||||
leftHandPredicate.appendHqlString( sb );
|
||||
}
|
||||
sb.append( " and " );
|
||||
if ( rightHandPredicate instanceof SqmOrPredicate ) {
|
||||
sb.append( '(' );
|
||||
rightHandPredicate.appendHqlString( sb );
|
||||
sb.append( ')' );
|
||||
}
|
||||
else {
|
||||
rightHandPredicate.appendHqlString( sb );
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.query.sqm.tree.predicate;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.SqmExpressible;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.sql.ast.tree.predicate.Junction;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmJunctionPredicate extends AbstractSqmPredicate {
|
||||
private final BooleanOperator booleanOperator;
|
||||
private final List<SqmPredicate> predicates;
|
||||
|
||||
public SqmJunctionPredicate(
|
||||
BooleanOperator booleanOperator,
|
||||
SqmPredicate leftHandPredicate,
|
||||
SqmPredicate rightHandPredicate,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( leftHandPredicate.getExpressible(), nodeBuilder );
|
||||
this.booleanOperator = booleanOperator;
|
||||
this.predicates = new ArrayList<>( 2 );
|
||||
this.predicates.add( leftHandPredicate );
|
||||
this.predicates.add( rightHandPredicate );
|
||||
}
|
||||
|
||||
public SqmJunctionPredicate(
|
||||
BooleanOperator booleanOperator,
|
||||
List<SqmPredicate> predicates,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( predicates.get( 0 ).getNodeType(), nodeBuilder );
|
||||
this.booleanOperator = booleanOperator;
|
||||
this.predicates = predicates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmJunctionPredicate copy(SqmCopyContext context) {
|
||||
final SqmJunctionPredicate existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final List<SqmPredicate> predicates = new ArrayList<>( this.predicates.size() );
|
||||
for ( SqmPredicate predicate : this.predicates ) {
|
||||
predicates.add( predicate.copy( context ) );
|
||||
}
|
||||
final SqmJunctionPredicate predicate = context.registerCopy(
|
||||
this,
|
||||
new SqmJunctionPredicate(
|
||||
booleanOperator,
|
||||
predicates,
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( predicate, context );
|
||||
return predicate;
|
||||
}
|
||||
|
||||
public List<SqmPredicate> getPredicates() {
|
||||
return predicates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(SemanticQueryWalker<T> walker) {
|
||||
return walker.visitJunctionPredicate( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public BooleanOperator getOperator() {
|
||||
return booleanOperator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNegated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Expression<Boolean>> getExpressions() {
|
||||
//noinspection unchecked
|
||||
return (List<Expression<Boolean>>) (List<?>) predicates;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate not() {
|
||||
return new SqmNegatedPredicate( this, nodeBuilder() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHqlString(StringBuilder sb) {
|
||||
final String separator = booleanOperator == BooleanOperator.AND
|
||||
? " and "
|
||||
: " or ";
|
||||
appendJunctionHqlString( predicates.get( 0 ), sb );
|
||||
for ( int i = 1; i < predicates.size(); i++ ) {
|
||||
sb.append( separator );
|
||||
appendJunctionHqlString( predicates.get( i ), sb );
|
||||
}
|
||||
}
|
||||
|
||||
private void appendJunctionHqlString(SqmPredicate p, StringBuilder sb) {
|
||||
if ( p instanceof SqmJunctionPredicate ) {
|
||||
final SqmJunctionPredicate junction = (SqmJunctionPredicate) p;
|
||||
// If we have the same nature, or if this is a disjunction and the operand is a conjunction,
|
||||
// then we don't need parenthesis, because the AND operator binds stronger
|
||||
if ( booleanOperator == junction.getOperator() || booleanOperator == BooleanOperator.OR ) {
|
||||
junction.appendHqlString( sb );
|
||||
}
|
||||
else {
|
||||
sb.append( '(' );
|
||||
junction.appendHqlString( sb );
|
||||
sb.append( ')' );
|
||||
}
|
||||
}
|
||||
else {
|
||||
p.appendHqlString( sb );
|
||||
}
|
||||
}
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
/*
|
||||
* 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.query.sqm.tree.predicate;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface SqmJunctivePredicate extends SqmPredicate {
|
||||
SqmPredicate getLeftHandPredicate();
|
||||
|
||||
SqmPredicate getRightHandPredicate();
|
||||
}
|
@ -1,108 +0,0 @@
|
||||
/*
|
||||
* 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.query.sqm.tree.predicate;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
import org.hibernate.query.sqm.SemanticQueryWalker;
|
||||
import org.hibernate.query.sqm.tree.SqmCopyContext;
|
||||
import org.hibernate.query.sqm.tree.expression.AbstractSqmExpression;
|
||||
|
||||
import jakarta.persistence.criteria.Expression;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmOrPredicate extends AbstractSqmExpression<Boolean> implements SqmJunctivePredicate {
|
||||
private final SqmPredicate leftHandPredicate;
|
||||
private final SqmPredicate rightHandPredicate;
|
||||
|
||||
public SqmOrPredicate(
|
||||
SqmPredicate leftHandPredicate,
|
||||
SqmPredicate rightHandPredicate,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( null, nodeBuilder );
|
||||
this.leftHandPredicate = leftHandPredicate;
|
||||
this.rightHandPredicate = rightHandPredicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmOrPredicate copy(SqmCopyContext context) {
|
||||
final SqmOrPredicate existing = context.getCopy( this );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
final SqmOrPredicate predicate = context.registerCopy(
|
||||
this,
|
||||
new SqmOrPredicate(
|
||||
leftHandPredicate.copy( context ),
|
||||
rightHandPredicate.copy( context ),
|
||||
nodeBuilder()
|
||||
)
|
||||
);
|
||||
copyTo( predicate, context );
|
||||
return predicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate getLeftHandPredicate() {
|
||||
return leftHandPredicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate getRightHandPredicate() {
|
||||
return rightHandPredicate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T accept(SemanticQueryWalker<T> walker) {
|
||||
return walker.visitOrPredicate( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPredicate not() {
|
||||
return new SqmNegatedPredicate( this, nodeBuilder() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public BooleanOperator getOperator() {
|
||||
return BooleanOperator.OR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isNegated() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Expression<Boolean>> getExpressions() {
|
||||
return Arrays.asList( leftHandPredicate, rightHandPredicate );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendHqlString(StringBuilder sb) {
|
||||
if ( leftHandPredicate instanceof SqmAndPredicate ) {
|
||||
sb.append( '(' );
|
||||
leftHandPredicate.appendHqlString( sb );
|
||||
sb.append( ')' );
|
||||
}
|
||||
else {
|
||||
leftHandPredicate.appendHqlString( sb );
|
||||
}
|
||||
sb.append( " or " );
|
||||
if ( rightHandPredicate instanceof SqmAndPredicate ) {
|
||||
sb.append( '(' );
|
||||
rightHandPredicate.appendHqlString( sb );
|
||||
sb.append( ')' );
|
||||
}
|
||||
else {
|
||||
rightHandPredicate.appendHqlString( sb );
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user