HHH-13725 Fix join fetch with alias

This commit is contained in:
Andrea Boriero 2019-11-17 15:50:27 +00:00 committed by Steve Ebersole
parent 93c6c2e7e7
commit 7db245230e
5 changed files with 68 additions and 39 deletions

View File

@ -68,11 +68,8 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor {
DomainResultCreationState creationState) {
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
TableReference tableReference = tableGroup.getPrimaryTableReference();
if ( fKeyDirection == ForeignKeyDirection.FROM_PARENT ) {
tableReference = tableGroup.resolveTableReference( keyColumnContainingTable );
}
String identificationVariable = tableReference.getIdentificationVariable();
final TableReference tableReference = tableGroup.resolveTableReference( keyColumnContainingTable );
final String identificationVariable = tableReference.getIdentificationVariable();
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
@ -107,60 +104,76 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor {
JoinType joinType,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
final TableReference lhsTableReference = getTableReference( lhs, tableGroup, keyColumnContainingTable );
ColumnReference lhsColumnReference;
lhsColumnReference = new ColumnReference(
lhsTableReference,
final TableReference keyTableReference = getTableReference( lhs, tableGroup, keyColumnContainingTable );
ColumnReference keyColumnReference;
keyColumnReference = new ColumnReference(
keyTableReference,
keyColumnExpression,
jdbcMapping,
creationContext.getSessionFactory()
);
final TableReference rhsTableKeyReference = getRhsTableReference(
lhs,
tableGroup,
targetColumnContainingTable
);
ColumnReference rhsColumnReference;
ColumnReference targetColumnReference;
if ( targetColumnContainingTable.equals( keyColumnContainingTable ) ) {
rhsColumnReference = new ColumnReference(
rhsTableKeyReference.getIdentificationVariable(),
targetColumnExpression,
jdbcMapping,
creationContext.getSessionFactory()
final TableReference targetTableKeyReference = getTableReferenceWhenTargetEqualsKey(
lhs,
tableGroup,
targetColumnContainingTable
);
}
else {
rhsColumnReference = (ColumnReference) sqlExpressionResolver.resolveSqlExpression(
targetColumnReference = (ColumnReference) sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
rhsTableKeyReference,
targetTableKeyReference,
targetColumnExpression
),
s -> new ColumnReference(
rhsTableKeyReference.getIdentificationVariable(),
targetTableKeyReference.getIdentificationVariable(),
targetColumnExpression,
jdbcMapping,
creationContext.getSessionFactory()
)
);
}
else {
final TableReference targetTableKeyReference = getTableReference(
lhs,
tableGroup,
targetColumnContainingTable
);
targetColumnReference = (ColumnReference) sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey(
targetTableKeyReference,
targetColumnExpression
),
s -> new ColumnReference(
targetTableKeyReference.getIdentificationVariable(),
targetColumnExpression,
jdbcMapping,
creationContext.getSessionFactory()
)
);
}
if ( fKeyDirection == ForeignKeyDirection.FROM_PARENT ) {
return new ComparisonPredicate(
targetColumnReference,
ComparisonOperator.EQUAL,
keyColumnReference
);
}
return new ComparisonPredicate(
lhsColumnReference,
keyColumnReference,
ComparisonOperator.EQUAL,
rhsColumnReference
targetColumnReference
);
}
protected TableReference getRhsTableReference(TableGroup lhs, TableGroup tableGroup, String table) {
protected TableReference getTableReferenceWhenTargetEqualsKey(TableGroup lhs, TableGroup tableGroup, String table) {
if ( tableGroup.getPrimaryTableReference().getTableExpression().equals( table ) ) {
return tableGroup.getPrimaryTableReference();
}
if ( lhs.getPrimaryTableReference().getTableExpression().equals( table ) ) {
return lhs.getPrimaryTableReference();
}
for ( TableReferenceJoin tableJoin : lhs.getTableReferenceJoins() ) {
if ( tableJoin.getJoinedTableReference().getTableExpression().equals( table ) ) {
return tableJoin.getJoinedTableReference();
@ -177,9 +190,6 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor {
else if ( tableGroup.getPrimaryTableReference().getTableExpression().equals( table ) ) {
return tableGroup.getPrimaryTableReference();
}
else if ( tableGroup.getPrimaryTableReference().getTableExpression().equals( table ) ) {
return tableGroup.getPrimaryTableReference();
}
for ( TableReferenceJoin tableJoin : lhs.getTableReferenceJoins() ) {
if ( tableJoin.getJoinedTableReference().getTableExpression().equals( table ) ) {
@ -190,7 +200,6 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor {
throw new IllegalStateException( "Could not resolve binding for table `" + table + "`" );
}
@Override
public JavaTypeDescriptor getJavaTypeDescriptor() {
return jdbcMapping.getJavaTypeDescriptor();

View File

@ -65,7 +65,11 @@ public class FromClauseIndex extends SimpleFromClauseAccessImpl {
if ( fetchesByPath == null ) {
fetchesByPath = new HashMap<>();
}
fetchesByPath.put( sqmJoin.getNavigablePath(), sqmJoin );
NavigablePath navigablePath = sqmJoin.getNavigablePath();
fetchesByPath.put( navigablePath, sqmJoin );
if ( containsAlias( navigablePath ) ) {
fetchesByPath.put( getPathWithoutAlias(navigablePath), sqmJoin );
}
}
public boolean isResolved(SqmFrom fromElement) {

View File

@ -20,18 +20,26 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
*/
public class SimpleFromClauseAccessImpl implements FromClauseAccess {
protected final Map<NavigablePath, TableGroup> tableGroupMap = new HashMap<>();
private final Map<NavigablePath, TableGroup> tableGroupMapNoAlias = new HashMap<>();
public SimpleFromClauseAccessImpl() {
}
@Override
public TableGroup findTableGroup(NavigablePath navigablePath) {
return tableGroupMap.get( navigablePath );
TableGroup tableGroup = tableGroupMap.get( navigablePath );
if ( tableGroup == null && !containsAlias( navigablePath ) ) {
return tableGroupMapNoAlias.get( navigablePath );
}
return tableGroup;
}
@Override
public void registerTableGroup(NavigablePath navigablePath, TableGroup tableGroup) {
final TableGroup previous = tableGroupMap.put( navigablePath, tableGroup );
if ( containsAlias( navigablePath ) ) {
tableGroupMapNoAlias.put( getPathWithoutAlias( navigablePath ), tableGroup );
}
if ( previous != null ) {
SqlTreeCreationLogger.LOGGER.debugf(
"Registration of TableGroup [%s] for NavigablePath [%s] overrode previous registration : %s",
@ -42,4 +50,13 @@ public class SimpleFromClauseAccessImpl implements FromClauseAccess {
}
}
protected boolean containsAlias(NavigablePath navigablePath) {
return navigablePath.getLocalName().endsWith( ")" );
}
protected NavigablePath getPathWithoutAlias(NavigablePath navigablePath) {
final String fullPath = navigablePath.getFullPath();
final String navigableName = fullPath.substring( fullPath.lastIndexOf( '.' ) + 1, fullPath.lastIndexOf( '(' ) );
return new NavigablePath( navigablePath.getParent(), navigableName );
}
}

View File

@ -48,7 +48,7 @@ public interface SqlExpressionResolver {
final String qualifier = tableReference.getIdentificationVariable() == null
? tableReference.getTableExpression()
: tableReference.getIdentificationVariable();
return qualifier + '.' + columnExpression;
return qualifier + columnExpression;
}
/**

View File

@ -10,7 +10,6 @@ import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.OneToOne;
import javax.persistence.Table;
import org.hibernate.Hibernate;