Fix issues with query splitting
This commit is contained in:
parent
0e780f1102
commit
bbeb7ecff1
|
@ -12,12 +12,14 @@ import java.util.Map;
|
||||||
import org.hibernate.NotYetImplementedFor6Exception;
|
import org.hibernate.NotYetImplementedFor6Exception;
|
||||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||||
import org.hibernate.internal.util.collections.Stack;
|
import org.hibernate.internal.util.collections.Stack;
|
||||||
|
import org.hibernate.internal.util.collections.StandardStack;
|
||||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||||
import org.hibernate.query.NavigablePath;
|
import org.hibernate.query.NavigablePath;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationOptions;
|
import org.hibernate.query.hql.spi.SqmCreationOptions;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
import org.hibernate.query.hql.spi.SqmCreationProcessingState;
|
||||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||||
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
import org.hibernate.query.hql.spi.SqmPathRegistry;
|
||||||
|
import org.hibernate.query.sqm.internal.SqmQuerySpecCreationProcessingStateStandardImpl;
|
||||||
import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker;
|
import org.hibernate.query.sqm.spi.BaseSemanticQueryWalker;
|
||||||
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
import org.hibernate.query.sqm.spi.SqmCreationContext;
|
||||||
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement;
|
||||||
|
@ -119,9 +121,11 @@ public class QuerySplitter {
|
||||||
private static class UnmappedPolymorphismReplacer extends BaseSemanticQueryWalker implements SqmCreationState {
|
private static class UnmappedPolymorphismReplacer extends BaseSemanticQueryWalker implements SqmCreationState {
|
||||||
private final SqmRoot unmappedPolymorphicFromElement;
|
private final SqmRoot unmappedPolymorphicFromElement;
|
||||||
private final EntityDomainType mappedDescriptor;
|
private final EntityDomainType mappedDescriptor;
|
||||||
|
private final SqmCreationContext creationContext;
|
||||||
|
private final Stack<SqmCreationProcessingState> processingStateStack = new StandardStack<>();
|
||||||
|
|
||||||
private Map<NavigablePath, SqmPath> sqmPathCopyMap = new HashMap<>();
|
private Map<NavigablePath, SqmPath> sqmPathCopyMap = new HashMap<>();
|
||||||
private Map<SqmFrom,SqmFrom> sqmFromCopyMap = new HashMap<>();
|
private Map<SqmFrom, SqmFrom> sqmFromCopyMap = new HashMap<>();
|
||||||
|
|
||||||
private UnmappedPolymorphismReplacer(
|
private UnmappedPolymorphismReplacer(
|
||||||
SqmRoot unmappedPolymorphicFromElement,
|
SqmRoot unmappedPolymorphicFromElement,
|
||||||
|
@ -130,6 +134,7 @@ public class QuerySplitter {
|
||||||
super( sessionFactory.getServiceRegistry() );
|
super( sessionFactory.getServiceRegistry() );
|
||||||
this.unmappedPolymorphicFromElement = unmappedPolymorphicFromElement;
|
this.unmappedPolymorphicFromElement = unmappedPolymorphicFromElement;
|
||||||
this.mappedDescriptor = mappedDescriptor;
|
this.mappedDescriptor = mappedDescriptor;
|
||||||
|
this.creationContext = sessionFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -155,7 +160,21 @@ public class QuerySplitter {
|
||||||
@Override
|
@Override
|
||||||
public SqmSelectStatement visitSelectStatement(SqmSelectStatement statement) {
|
public SqmSelectStatement visitSelectStatement(SqmSelectStatement statement) {
|
||||||
final SqmSelectStatement copy = new SqmSelectStatement( statement.nodeBuilder() );
|
final SqmSelectStatement copy = new SqmSelectStatement( statement.nodeBuilder() );
|
||||||
copy.setQuerySpec( visitQuerySpec( statement.getQuerySpec() ) );
|
|
||||||
|
processingStateStack.push(
|
||||||
|
new SqmQuerySpecCreationProcessingStateStandardImpl(
|
||||||
|
processingStateStack.getCurrent(),
|
||||||
|
copy,
|
||||||
|
this
|
||||||
|
)
|
||||||
|
);
|
||||||
|
try {
|
||||||
|
copy.setQuerySpec( visitQuerySpec( statement.getQuerySpec() ) );
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
processingStateStack.pop();
|
||||||
|
}
|
||||||
|
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,10 +190,14 @@ public class QuerySplitter {
|
||||||
sqmQuerySpec.setWhereClause( visitWhereClause( querySpec.getWhereClause() ) );
|
sqmQuerySpec.setWhereClause( visitWhereClause( querySpec.getWhereClause() ) );
|
||||||
sqmQuerySpec.setGroupByClause( visitGroupByClause( querySpec.getGroupByClause() ) );
|
sqmQuerySpec.setGroupByClause( visitGroupByClause( querySpec.getGroupByClause() ) );
|
||||||
sqmQuerySpec.setOrderByClause( visitOrderByClause( querySpec.getOrderByClause() ) );
|
sqmQuerySpec.setOrderByClause( visitOrderByClause( querySpec.getOrderByClause() ) );
|
||||||
sqmQuerySpec.setLimitExpression( (SqmExpression) querySpec.getLimitExpression().accept( this ) );
|
if ( querySpec.getLimitExpression() != null ) {
|
||||||
sqmQuerySpec.setOffsetExpression( (SqmExpression) querySpec.getOffsetExpression().accept( this ) );
|
sqmQuerySpec.setLimitExpression( (SqmExpression) querySpec.getLimitExpression().accept( this ) );
|
||||||
|
}
|
||||||
|
if ( querySpec.getOffsetExpression() != null ) {
|
||||||
|
sqmQuerySpec.setOffsetExpression( (SqmExpression) querySpec.getOffsetExpression().accept( this ) );
|
||||||
|
}
|
||||||
|
|
||||||
return querySpec;
|
return sqmQuerySpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
private SqmFromClause currentFromClauseCopy = null;
|
private SqmFromClause currentFromClauseCopy = null;
|
||||||
|
@ -196,6 +219,9 @@ public class QuerySplitter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmGroupByClause visitGroupByClause(SqmGroupByClause clause) {
|
public SqmGroupByClause visitGroupByClause(SqmGroupByClause clause) {
|
||||||
|
if ( clause == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final SqmGroupByClause result = new SqmGroupByClause();
|
final SqmGroupByClause result = new SqmGroupByClause();
|
||||||
clause.visitGroupings(
|
clause.visitGroupings(
|
||||||
grouping -> result.addGrouping(
|
grouping -> result.addGrouping(
|
||||||
|
@ -213,6 +239,9 @@ public class QuerySplitter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmHavingClause visitHavingClause(SqmHavingClause clause) {
|
public SqmHavingClause visitHavingClause(SqmHavingClause clause) {
|
||||||
|
if ( clause == null || clause.getPredicate() == null ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
return new SqmHavingClause(
|
return new SqmHavingClause(
|
||||||
(SqmPredicate) clause.getPredicate().accept( this )
|
(SqmPredicate) clause.getPredicate().accept( this )
|
||||||
);
|
);
|
||||||
|
@ -220,26 +249,28 @@ public class QuerySplitter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmRoot visitRootPath(SqmRoot sqmRoot) {
|
public SqmRoot visitRootPath(SqmRoot sqmRoot) {
|
||||||
|
final SqmFrom sqmFrom = sqmFromCopyMap.get( sqmRoot );
|
||||||
|
if ( sqmFrom != null ) {
|
||||||
|
return (SqmRoot) sqmFrom;
|
||||||
|
}
|
||||||
|
final EntityDomainType pathSource;
|
||||||
|
if ( sqmRoot == unmappedPolymorphicFromElement ) {
|
||||||
|
pathSource = mappedDescriptor;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
pathSource = sqmRoot.getReferencedPathSource();
|
||||||
|
}
|
||||||
|
final SqmRoot copy = new SqmRoot(
|
||||||
|
pathSource,
|
||||||
|
sqmRoot.getExplicitAlias(),
|
||||||
|
sqmRoot.nodeBuilder()
|
||||||
|
);
|
||||||
return (SqmRoot) getProcessingStateStack().getCurrent().getPathRegistry().resolvePath(
|
return (SqmRoot) getProcessingStateStack().getCurrent().getPathRegistry().resolvePath(
|
||||||
sqmRoot.getNavigablePath(),
|
copy.getNavigablePath(),
|
||||||
navigablePath -> {
|
navigablePath -> {
|
||||||
final SqmRoot copy;
|
|
||||||
if ( sqmRoot == unmappedPolymorphicFromElement ) {
|
|
||||||
copy = new SqmRoot(
|
|
||||||
mappedDescriptor,
|
|
||||||
sqmRoot.getExplicitAlias(),
|
|
||||||
sqmRoot.nodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
copy = new SqmRoot(
|
|
||||||
sqmRoot.getReferencedPathSource(),
|
|
||||||
sqmRoot.getExplicitAlias(),
|
|
||||||
sqmRoot.nodeBuilder()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
sqmFromCopyMap.put( sqmRoot, copy );
|
sqmFromCopyMap.put( sqmRoot, copy );
|
||||||
sqmPathCopyMap.put( sqmRoot.getNavigablePath(), copy );
|
sqmPathCopyMap.put( sqmRoot.getNavigablePath(), copy );
|
||||||
|
currentFromClauseCopy.addRoot( copy );
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -247,16 +278,22 @@ public class QuerySplitter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmCrossJoin visitCrossJoin(SqmCrossJoin join) {
|
public SqmCrossJoin visitCrossJoin(SqmCrossJoin join) {
|
||||||
|
final SqmFrom sqmFrom = sqmFromCopyMap.get( join );
|
||||||
|
if ( sqmFrom != null ) {
|
||||||
|
return (SqmCrossJoin) sqmFrom;
|
||||||
|
}
|
||||||
return (SqmCrossJoin) getProcessingStateStack().getCurrent().getPathRegistry().resolvePath(
|
return (SqmCrossJoin) getProcessingStateStack().getCurrent().getPathRegistry().resolvePath(
|
||||||
join.getNavigablePath(),
|
join.getNavigablePath(),
|
||||||
navigablePath -> {
|
navigablePath -> {
|
||||||
|
final SqmRoot sqmRoot = (SqmRoot) sqmFromCopyMap.get( join.findRoot() );
|
||||||
final SqmCrossJoin copy = new SqmCrossJoin(
|
final SqmCrossJoin copy = new SqmCrossJoin(
|
||||||
join.getReferencedPathSource(),
|
join.getReferencedPathSource(),
|
||||||
join.getExplicitAlias(),
|
join.getExplicitAlias(),
|
||||||
(SqmRoot) sqmFromCopyMap.get( join.findRoot() )
|
sqmRoot
|
||||||
);
|
);
|
||||||
sqmFromCopyMap.put( join, copy );
|
sqmFromCopyMap.put( join, copy );
|
||||||
sqmPathCopyMap.put( join.getNavigablePath(), copy );
|
sqmPathCopyMap.put( join.getNavigablePath(), copy );
|
||||||
|
sqmRoot.addSqmJoin( copy );
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -264,17 +301,23 @@ public class QuerySplitter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmEntityJoin visitQualifiedEntityJoin(SqmEntityJoin join) {
|
public SqmEntityJoin visitQualifiedEntityJoin(SqmEntityJoin join) {
|
||||||
|
final SqmFrom sqmFrom = sqmFromCopyMap.get( join );
|
||||||
|
if ( sqmFrom != null ) {
|
||||||
|
return (SqmEntityJoin) sqmFrom;
|
||||||
|
}
|
||||||
return (SqmEntityJoin) getProcessingStateStack().getCurrent().getPathRegistry().resolvePath(
|
return (SqmEntityJoin) getProcessingStateStack().getCurrent().getPathRegistry().resolvePath(
|
||||||
join.getNavigablePath(),
|
join.getNavigablePath(),
|
||||||
navigablePath -> {
|
navigablePath -> {
|
||||||
|
final SqmRoot sqmRoot = (SqmRoot) sqmFromCopyMap.get( join.findRoot() );
|
||||||
final SqmEntityJoin copy = new SqmEntityJoin(
|
final SqmEntityJoin copy = new SqmEntityJoin(
|
||||||
join.getReferencedPathSource(),
|
join.getReferencedPathSource(),
|
||||||
join.getExplicitAlias(),
|
join.getExplicitAlias(),
|
||||||
join.getSqmJoinType(),
|
join.getSqmJoinType(),
|
||||||
(SqmRoot) sqmFromCopyMap.get( join.findRoot() )
|
sqmRoot
|
||||||
);
|
);
|
||||||
sqmFromCopyMap.put( join, copy );
|
sqmFromCopyMap.put( join, copy );
|
||||||
sqmPathCopyMap.put( join.getNavigablePath(), copy );
|
sqmPathCopyMap.put( join.getNavigablePath(), copy );
|
||||||
|
sqmRoot.addSqmJoin( copy );
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -282,12 +325,17 @@ public class QuerySplitter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmAttributeJoin visitQualifiedAttributeJoin(SqmAttributeJoin join) {
|
public SqmAttributeJoin visitQualifiedAttributeJoin(SqmAttributeJoin join) {
|
||||||
|
SqmFrom sqmFrom = sqmFromCopyMap.get( join );
|
||||||
|
if ( sqmFrom != null ) {
|
||||||
|
return (SqmAttributeJoin) sqmFrom;
|
||||||
|
}
|
||||||
return (SqmAttributeJoin) getProcessingStateStack().getCurrent().getPathRegistry().resolvePath(
|
return (SqmAttributeJoin) getProcessingStateStack().getCurrent().getPathRegistry().resolvePath(
|
||||||
join.getNavigablePath(),
|
join.getNavigablePath(),
|
||||||
navigablePath -> {
|
navigablePath -> {
|
||||||
SqmAttributeJoin copy = join.makeCopy(getProcessingStateStack().getCurrent());
|
SqmAttributeJoin copy = join.makeCopy( getProcessingStateStack().getCurrent() );
|
||||||
sqmFromCopyMap.put( join, copy );
|
sqmFromCopyMap.put( join, copy );
|
||||||
sqmPathCopyMap.put( join.getNavigablePath(), copy );
|
sqmPathCopyMap.put( join.getNavigablePath(), copy );
|
||||||
|
( (SqmFrom<?, ?>) copy.getParent() ).addSqmJoin( copy );
|
||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -427,7 +475,7 @@ public class QuerySplitter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmWhereClause visitWhereClause(SqmWhereClause whereClause) {
|
public SqmWhereClause visitWhereClause(SqmWhereClause whereClause) {
|
||||||
if ( whereClause == null ) {
|
if ( whereClause == null || whereClause.getPredicate() == null ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new SqmWhereClause(
|
return new SqmWhereClause(
|
||||||
|
@ -535,7 +583,7 @@ public class QuerySplitter {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmOrderByClause visitOrderByClause(SqmOrderByClause orderByClause) {
|
public SqmOrderByClause visitOrderByClause(SqmOrderByClause orderByClause) {
|
||||||
if ( orderByClause == null ) {
|
if ( orderByClause == null || orderByClause.getSortSpecifications().isEmpty() ) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -620,21 +668,14 @@ public class QuerySplitter {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Override
|
|
||||||
// public SqmQuerySpecCreationProcessingState getCurrentQuerySpecProcessingState() {
|
|
||||||
// // todo (6.0) : not sure these are needed
|
|
||||||
// throw new NotYetImplementedFor6Exception( );
|
|
||||||
// }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Stack<SqmCreationProcessingState> getProcessingStateStack() {
|
public Stack<SqmCreationProcessingState> getProcessingStateStack() {
|
||||||
// todo (6.0) : not sure these are needed
|
return processingStateStack;
|
||||||
throw new NotYetImplementedFor6Exception( );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SqmCreationContext getCreationContext() {
|
public SqmCreationContext getCreationContext() {
|
||||||
throw new NotYetImplementedFor6Exception( );
|
return creationContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue