Fix join predicate rendering and fix support for implicit joins in the ON clause
This commit is contained in:
parent
8fc0e05930
commit
fa3101c29e
|
@ -42,6 +42,7 @@ import org.hibernate.sql.ast.tree.from.CompositeTableGroup;
|
|||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
|
@ -173,19 +174,38 @@ public abstract class AbstractCompositeIdentifierMapping
|
|||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final CompositeTableGroup compositeTableGroup = new CompositeTableGroup(
|
||||
final TableGroup tableGroup = createRootTableGroupJoin(
|
||||
navigablePath,
|
||||
this,
|
||||
lhs,
|
||||
fetched
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
null,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
|
||||
final TableGroupJoin join = new TableGroupJoin( navigablePath, SqlAstJoinType.LEFT, compositeTableGroup, null );
|
||||
final TableGroupJoin join = new TableGroupJoin( navigablePath, SqlAstJoinType.LEFT, tableGroup, null );
|
||||
lhs.addTableGroupJoin( join );
|
||||
|
||||
return join;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup createRootTableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
return new CompositeTableGroup( navigablePath, this, lhs, fetched );
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPart findSubPart(String name, EntityMappingType treatTargetType) {
|
||||
return embeddableDescriptor.findSubPart( name, treatTargetType );
|
||||
|
|
|
@ -44,6 +44,7 @@ import org.hibernate.sql.ast.tree.from.CompositeTableGroup;
|
|||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
|
@ -286,21 +287,45 @@ public class EmbeddedAttributeMapping
|
|||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final CompositeTableGroup compositeTableGroup = new CompositeTableGroup(
|
||||
final TableGroup tableGroup = createRootTableGroupJoin(
|
||||
navigablePath,
|
||||
lhs,
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
null,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
|
||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
||||
navigablePath,
|
||||
sqlAstJoinType,
|
||||
tableGroup
|
||||
);
|
||||
lhs.addTableGroupJoin( tableGroupJoin );
|
||||
|
||||
return tableGroupJoin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup createRootTableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
return new CompositeTableGroup(
|
||||
navigablePath,
|
||||
this,
|
||||
lhs,
|
||||
fetched
|
||||
);
|
||||
|
||||
TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
||||
navigablePath,
|
||||
sqlAstJoinType,
|
||||
compositeTableGroup
|
||||
);
|
||||
lhs.addTableGroupJoin( tableGroupJoin );
|
||||
|
||||
return tableGroupJoin;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.hibernate.sql.ast.tree.expression.SqlTuple;
|
|||
import org.hibernate.sql.ast.tree.from.CompositeTableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
|
@ -204,9 +205,17 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
|||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
assert lhs.getModelPart() instanceof PluralAttributeMapping;
|
||||
|
||||
final TableGroup tableGroup = new CompositeTableGroup( navigablePath, this, lhs, fetched );
|
||||
final TableGroup tableGroup = createRootTableGroupJoin(
|
||||
navigablePath,
|
||||
lhs,
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
null,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
|
||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
||||
navigablePath,
|
||||
|
@ -218,6 +227,22 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
|||
return tableGroupJoin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup createRootTableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
assert lhs.getModelPart() instanceof PluralAttributeMapping;
|
||||
|
||||
return new CompositeTableGroup( navigablePath, this, lhs, fetched );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlAliasStem() {
|
||||
return sqlAliasStem;
|
||||
|
|
|
@ -335,31 +335,16 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
|
|||
|
||||
@Override
|
||||
public Predicate generateJoinPredicate(
|
||||
TableGroup lhs,
|
||||
TableGroup tableGroup,
|
||||
TableGroup targetSideTableGroup,
|
||||
TableGroup keySideTableGroup,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
TableReference lhsTableReference;
|
||||
TableReference rhsTableKeyReference;
|
||||
if ( targetTable.equals( keyTable ) ) {
|
||||
lhsTableReference = getTableReferenceWhenTargetEqualsKey( lhs, tableGroup, keyTable );
|
||||
|
||||
rhsTableKeyReference = getTableReference(
|
||||
lhs,
|
||||
tableGroup,
|
||||
final TableReference lhsTableReference = targetSideTableGroup.getTableReference(
|
||||
targetSideTableGroup.getNavigablePath(),
|
||||
targetTable
|
||||
);
|
||||
}
|
||||
else {
|
||||
lhsTableReference = getTableReference( lhs, tableGroup, keyTable );
|
||||
|
||||
rhsTableKeyReference = getTableReference(
|
||||
lhs,
|
||||
tableGroup,
|
||||
targetTable
|
||||
);
|
||||
}
|
||||
final TableReference rhsTableKeyReference = keySideTableGroup.getTableReference( keyTable );
|
||||
|
||||
return generateJoinPredicate(
|
||||
lhsTableReference,
|
||||
|
@ -372,21 +357,12 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
|
|||
|
||||
@Override
|
||||
public Predicate generateJoinPredicate(
|
||||
TableReference lhs,
|
||||
TableReference rhs,
|
||||
TableReference targetSideReference,
|
||||
TableReference keySideReference,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final String rhsTableExpression = rhs.getTableExpression();
|
||||
final String lhsTableExpression = lhs.getTableExpression();
|
||||
if ( lhsTableExpression.equals( keyTable ) ) {
|
||||
assert rhsTableExpression.equals( targetTable );
|
||||
return getPredicate( lhs, rhs, creationContext, keySelectableMappings, targetSelectableMappings );
|
||||
}
|
||||
else {
|
||||
assert rhsTableExpression.equals( keyTable );
|
||||
return getPredicate( lhs, rhs, creationContext, targetSelectableMappings, keySelectableMappings );
|
||||
}
|
||||
return getPredicate( targetSideReference, keySideReference, creationContext, targetSelectableMappings, keySelectableMappings );
|
||||
}
|
||||
|
||||
private Predicate getPredicate(
|
||||
|
@ -417,23 +393,6 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
|
|||
return predicate;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException( "Could not resolve binding for table `" + table + "`" );
|
||||
}
|
||||
|
||||
protected TableReference getTableReference(TableGroup lhs, TableGroup tableGroup, String table) {
|
||||
if ( lhs.getPrimaryTableReference().getTableExpression().equals( table ) ) {
|
||||
return lhs.getPrimaryTableReference();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.metamodel.mapping.internal;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
|
@ -32,6 +33,7 @@ import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
|||
import org.hibernate.sql.ast.spi.SqlSelection;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.FetchOptions;
|
||||
|
@ -286,6 +288,30 @@ public class EntityCollectionPart
|
|||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup createRootTableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
return collectionDescriptor.getAttributeMapping().createRootTableGroupJoin(
|
||||
navigablePath,
|
||||
lhs,
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
predicateConsumer,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSqlAliasStem() {
|
||||
return collectionDescriptor.getAttributeMapping().getSqlAliasStem();
|
||||
|
|
|
@ -627,57 +627,17 @@ public class PluralAttributeMappingImpl
|
|||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final CollectionPersister collectionDescriptor = getCollectionDescriptor();
|
||||
if ( collectionDescriptor.isOneToMany() ) {
|
||||
return createOneToManyTableGroupJoin(
|
||||
final TableGroup tableGroup = createRootTableGroupJoin(
|
||||
navigablePath,
|
||||
lhs,
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
null,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
}
|
||||
else {
|
||||
return createCollectionTableGroupJoin(
|
||||
navigablePath,
|
||||
lhs,
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void setForeignKeyDescriptor(ForeignKeyDescriptor fkDescriptor) {
|
||||
this.fkDescriptor = fkDescriptor;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private TableGroupJoin createOneToManyTableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final TableGroup tableGroup = createOneToManyTableGroup(
|
||||
lhs.canUseInnerJoins() && sqlAstJoinType == SqlAstJoinType.INNER,
|
||||
navigablePath,
|
||||
fetched,
|
||||
explicitSourceAlias,
|
||||
aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() ),
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
|
||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
||||
navigablePath,
|
||||
sqlAstJoinType,
|
||||
|
@ -696,6 +656,60 @@ public class PluralAttributeMappingImpl
|
|||
return tableGroupJoin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup createRootTableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final CollectionPersister collectionDescriptor = getCollectionDescriptor();
|
||||
final TableGroup tableGroup;
|
||||
if ( collectionDescriptor.isOneToMany() ) {
|
||||
tableGroup = createOneToManyTableGroup(
|
||||
lhs.canUseInnerJoins() && sqlAstJoinType == SqlAstJoinType.INNER,
|
||||
navigablePath,
|
||||
fetched,
|
||||
explicitSourceAlias,
|
||||
aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() ),
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
}
|
||||
else {
|
||||
tableGroup = createCollectionTableGroup(
|
||||
lhs.canUseInnerJoins() && sqlAstJoinType == SqlAstJoinType.INNER,
|
||||
navigablePath,
|
||||
fetched,
|
||||
explicitSourceAlias,
|
||||
aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() ),
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
}
|
||||
|
||||
if ( predicateConsumer != null ) {
|
||||
predicateConsumer.accept(
|
||||
getKeyDescriptor().generateJoinPredicate(
|
||||
lhs,
|
||||
tableGroup,
|
||||
sqlAstJoinType,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
)
|
||||
);
|
||||
}
|
||||
return tableGroup;
|
||||
}
|
||||
|
||||
public void setForeignKeyDescriptor(ForeignKeyDescriptor fkDescriptor) {
|
||||
this.fkDescriptor = fkDescriptor;
|
||||
}
|
||||
|
||||
private TableGroup createOneToManyTableGroup(
|
||||
boolean canUseInnerJoins,
|
||||
NavigablePath navigablePath,
|
||||
|
@ -825,44 +839,6 @@ public class PluralAttributeMappingImpl
|
|||
);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private TableGroupJoin createCollectionTableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final TableGroup tableGroup = createCollectionTableGroup(
|
||||
lhs.canUseInnerJoins() && sqlAstJoinType == SqlAstJoinType.INNER,
|
||||
navigablePath,
|
||||
fetched,
|
||||
explicitSourceAlias,
|
||||
aliasBaseGenerator.createSqlAliasBase( getSqlAliasStem() ),
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
|
||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
||||
navigablePath,
|
||||
sqlAstJoinType,
|
||||
tableGroup,
|
||||
getKeyDescriptor().generateJoinPredicate(
|
||||
lhs,
|
||||
tableGroup,
|
||||
sqlAstJoinType,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
)
|
||||
);
|
||||
|
||||
lhs.addTableGroupJoin( tableGroupJoin );
|
||||
|
||||
return tableGroupJoin;
|
||||
}
|
||||
|
||||
private TableGroup createCollectionTableGroup(
|
||||
boolean canUseInnerJoins,
|
||||
NavigablePath navigablePath,
|
||||
|
@ -1054,8 +1030,8 @@ public class PluralAttributeMappingImpl
|
|||
joinType,
|
||||
elementAssociatedPrimaryTable,
|
||||
elementFkDescriptor.generateJoinPredicate(
|
||||
collectionTableReference,
|
||||
elementAssociatedPrimaryTable,
|
||||
collectionTableReference,
|
||||
joinType,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
|
|
|
@ -242,70 +242,40 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
|
||||
@Override
|
||||
public Predicate generateJoinPredicate(
|
||||
TableReference lhs,
|
||||
TableReference rhs,
|
||||
TableReference targetSideReference,
|
||||
TableReference keySideReference,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
if ( lhs.getTableReference( keySide.getModelPart().getContainingTableExpression() ) != null ) {
|
||||
return new ComparisonPredicate(
|
||||
new ColumnReference(
|
||||
lhs,
|
||||
keySide.getModelPart(),
|
||||
creationContext.getSessionFactory()
|
||||
),
|
||||
ComparisonOperator.EQUAL,
|
||||
new ColumnReference(
|
||||
rhs,
|
||||
targetSide.getModelPart(),
|
||||
creationContext.getSessionFactory()
|
||||
)
|
||||
);
|
||||
}
|
||||
else {
|
||||
return new ComparisonPredicate(
|
||||
new ColumnReference(
|
||||
lhs,
|
||||
targetSideReference,
|
||||
targetSide.getModelPart(),
|
||||
creationContext.getSessionFactory()
|
||||
),
|
||||
ComparisonOperator.EQUAL,
|
||||
new ColumnReference(
|
||||
rhs,
|
||||
keySideReference,
|
||||
keySide.getModelPart(),
|
||||
creationContext.getSessionFactory()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Predicate generateJoinPredicate(
|
||||
TableGroup lhs,
|
||||
TableGroup tableGroup,
|
||||
TableGroup targetSideTableGroup,
|
||||
TableGroup keySideTableGroup,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
TableReference lhsTableReference;
|
||||
TableReference rhsTableKeyReference;
|
||||
if ( targetSide.getModelPart().getContainingTableExpression().equals( keySide.getModelPart().getContainingTableExpression() ) ) {
|
||||
lhsTableReference = getTableReferenceWhenTargetEqualsKey( lhs, tableGroup, keySide.getModelPart().getContainingTableExpression() );
|
||||
|
||||
rhsTableKeyReference = getTableReference(
|
||||
lhs,
|
||||
tableGroup,
|
||||
final TableReference lhsTableReference = targetSideTableGroup.getTableReference(
|
||||
targetSideTableGroup.getNavigablePath(),
|
||||
targetSide.getModelPart().getContainingTableExpression()
|
||||
);
|
||||
}
|
||||
else {
|
||||
lhsTableReference = getTableReference( lhs, tableGroup, keySide.getModelPart().getContainingTableExpression() );
|
||||
|
||||
rhsTableKeyReference = getTableReference(
|
||||
lhs,
|
||||
tableGroup,
|
||||
targetSide.getModelPart().getContainingTableExpression()
|
||||
final TableReference rhsTableKeyReference = keySideTableGroup.getTableReference(
|
||||
keySide.getModelPart().getContainingTableExpression()
|
||||
);
|
||||
}
|
||||
|
||||
return generateJoinPredicate(
|
||||
lhsTableReference,
|
||||
|
@ -316,23 +286,6 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
throw new IllegalStateException( "Could not resolve binding for table `" + table + "`" );
|
||||
}
|
||||
|
||||
protected TableReference getTableReference(TableGroup lhs, TableGroup tableGroup, String table) {
|
||||
final NavigablePath navigablePath = lhs.getNavigablePath().append( getNavigableRole().getNavigableName() );
|
||||
if ( lhs.getPrimaryTableReference().getTableReference( navigablePath, table ) != null ) {
|
||||
|
|
|
@ -10,6 +10,7 @@ import java.util.Collections;
|
|||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
|
@ -56,6 +57,7 @@ import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
|||
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupProducer;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
|
@ -421,6 +423,10 @@ public class ToOneAttributeMapping
|
|||
return targetKeyPropertyName;
|
||||
}
|
||||
|
||||
public boolean isTargetKeyPropertyPath(String path) {
|
||||
return targetKeyPropertyNames.contains( path );
|
||||
}
|
||||
|
||||
public Cardinality getCardinality() {
|
||||
return cardinality;
|
||||
}
|
||||
|
@ -924,6 +930,59 @@ public class ToOneAttributeMapping
|
|||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
|
||||
final LazyTableGroup lazyTableGroup = createRootTableGroupJoin(
|
||||
navigablePath,
|
||||
lhs,
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
null,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
||||
navigablePath,
|
||||
sqlAstJoinType,
|
||||
lazyTableGroup,
|
||||
null
|
||||
);
|
||||
|
||||
final TableReference lhsTableReference = lhs.resolveTableReference( navigablePath, identifyingColumnsTableExpression );
|
||||
|
||||
lazyTableGroup.setTableGroupInitializerCallback(
|
||||
tableGroup -> tableGroupJoin.applyPredicate(
|
||||
foreignKeyDescriptor.generateJoinPredicate(
|
||||
sideNature == ForeignKeyDescriptor.Nature.TARGET ? lhsTableReference : tableGroup.getPrimaryTableReference(),
|
||||
sideNature == ForeignKeyDescriptor.Nature.TARGET ? tableGroup.getPrimaryTableReference() : lhsTableReference,
|
||||
sqlAstJoinType,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
)
|
||||
)
|
||||
);
|
||||
lhs.addTableGroupJoin( tableGroupJoin );
|
||||
|
||||
if ( sqlAstJoinType == SqlAstJoinType.INNER && isNullable ) {
|
||||
// Force initialization of the underlying table group join to retain cardinality
|
||||
lazyTableGroup.getPrimaryTableReference();
|
||||
}
|
||||
|
||||
return tableGroupJoin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LazyTableGroup createRootTableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( sqlAliasStem );
|
||||
final boolean canUseInnerJoin = sqlAstJoinType == SqlAstJoinType.INNER || lhs.canUseInnerJoins() && !isNullable;
|
||||
final LazyTableGroup lazyTableGroup = new LazyTableGroup(
|
||||
|
@ -967,34 +1026,31 @@ public class ToOneAttributeMapping
|
|||
lhs
|
||||
);
|
||||
|
||||
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
|
||||
if ( predicateConsumer != null ) {
|
||||
final TableReference lhsTableReference = lhs.resolveTableReference(
|
||||
navigablePath,
|
||||
sqlAstJoinType,
|
||||
lazyTableGroup,
|
||||
null
|
||||
identifyingColumnsTableExpression
|
||||
);
|
||||
|
||||
final TableReference lhsTableReference = lhs.resolveTableReference( navigablePath, identifyingColumnsTableExpression );
|
||||
|
||||
lazyTableGroup.setTableGroupInitializerCallback(
|
||||
tableGroup -> tableGroupJoin.applyPredicate(
|
||||
tableGroup -> predicateConsumer.accept(
|
||||
foreignKeyDescriptor.generateJoinPredicate(
|
||||
lhsTableReference,
|
||||
tableGroup.getPrimaryTableReference(),
|
||||
sideNature == ForeignKeyDescriptor.Nature.TARGET ? lhsTableReference : tableGroup.getPrimaryTableReference(),
|
||||
sideNature == ForeignKeyDescriptor.Nature.TARGET ? tableGroup.getPrimaryTableReference() : lhsTableReference,
|
||||
sqlAstJoinType,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
)
|
||||
)
|
||||
);
|
||||
lhs.addTableGroupJoin( tableGroupJoin );
|
||||
|
||||
if ( sqlAstJoinType == SqlAstJoinType.INNER && isNullable ) {
|
||||
// Force initialization of the underlying table group join to retain cardinality
|
||||
lazyTableGroup.getPrimaryTableReference();
|
||||
}
|
||||
}
|
||||
|
||||
return tableGroupJoin;
|
||||
return lazyTableGroup;
|
||||
}
|
||||
|
||||
private SqlAstJoinType getJoinType(NavigablePath navigablePath, TableGroup tableGroup) {
|
||||
|
|
|
@ -21,10 +21,10 @@ import org.hibernate.query.sqm.tree.from.SqmQualifiedJoin;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class QualifiedJoinPredicatePathConsumer extends BasicDotIdentifierConsumer {
|
||||
private final SqmQualifiedJoin sqmJoin;
|
||||
private final SqmQualifiedJoin<?, ?> sqmJoin;
|
||||
|
||||
public QualifiedJoinPredicatePathConsumer(
|
||||
SqmQualifiedJoin sqmJoin,
|
||||
SqmQualifiedJoin<?, ?> sqmJoin,
|
||||
SqmCreationState creationState) {
|
||||
super( creationState );
|
||||
this.sqmJoin = sqmJoin;
|
||||
|
|
|
@ -1683,6 +1683,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
// not consumed by the identifierConsumer
|
||||
join.setExplicitAlias( alias );
|
||||
|
||||
final HqlParser.QualifiedJoinPredicateContext qualifiedJoinPredicateContext = parserJoin.qualifiedJoinPredicate();
|
||||
if ( join instanceof SqmEntityJoin ) {
|
||||
//noinspection unchecked
|
||||
sqmRoot.addSqmJoin( join );
|
||||
|
@ -1690,8 +1691,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
else {
|
||||
if ( getCreationOptions().useStrictJpaCompliance() ) {
|
||||
if ( join.getExplicitAlias() != null ) {
|
||||
//noinspection rawtypes
|
||||
if ( ( (SqmAttributeJoin) join ).isFetched() ) {
|
||||
if ( ( (SqmAttributeJoin<?, ?>) join ).isFetched() ) {
|
||||
throw new StrictJpaComplianceViolation(
|
||||
"Encountered aliased fetch join, but strict JPQL compliance was requested",
|
||||
StrictJpaComplianceViolation.Type.ALIASED_FETCH_JOIN
|
||||
|
@ -1699,9 +1699,11 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
}
|
||||
}
|
||||
if ( qualifiedJoinPredicateContext != null && ( (SqmAttributeJoin<?, ?>) join ).isFetched() ) {
|
||||
throw new SemanticException( "with-clause not allowed on fetched associations; use filters" );
|
||||
}
|
||||
}
|
||||
|
||||
final HqlParser.QualifiedJoinPredicateContext qualifiedJoinPredicateContext = parserJoin.qualifiedJoinPredicate();
|
||||
if ( qualifiedJoinPredicateContext != null ) {
|
||||
dotIdentifierConsumerStack.push( new QualifiedJoinPredicatePathConsumer( join, this ) );
|
||||
try {
|
||||
|
|
|
@ -43,6 +43,11 @@ public class FromClauseAccessImpl implements FromClauseAccess {
|
|||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup findTableGroupOnLeaf(NavigablePath navigablePath) {
|
||||
return findTableGroup( navigablePath );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup findTableGroup(NavigablePath navigablePath) {
|
||||
if ( tableGroupByPath != null ) {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,6 +19,9 @@ import org.hibernate.sql.ast.tree.from.TableGroup;
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface FromClauseAccess {
|
||||
|
||||
TableGroup findTableGroupOnLeaf(NavigablePath navigablePath);
|
||||
|
||||
/**
|
||||
* Find a TableGroup by the NavigablePath it is registered under. Returns
|
||||
* {@code null} if no TableGroup is registered under that NavigablePath
|
||||
|
|
|
@ -31,6 +31,11 @@ public class SimpleFromClauseAccessImpl implements FromClauseAccess {
|
|||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup findTableGroupOnLeaf(NavigablePath navigablePath) {
|
||||
return tableGroupMap.get( navigablePath );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableGroup findTableGroup(NavigablePath navigablePath) {
|
||||
final TableGroup tableGroup = tableGroupMap.get( navigablePath );
|
||||
|
|
|
@ -59,6 +59,10 @@ public class LazyTableGroup extends AbstractColumnReferenceQualifier implements
|
|||
|
||||
}
|
||||
|
||||
public boolean isInitialized() {
|
||||
return tableGroup != null;
|
||||
}
|
||||
|
||||
public TableGroup getUnderlyingTableGroup() {
|
||||
return tableGroup;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
*/
|
||||
package org.hibernate.sql.ast.tree.from;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||
|
@ -13,6 +15,7 @@ import org.hibernate.sql.ast.spi.SqlAliasBaseGenerator;
|
|||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -55,4 +58,42 @@ public interface TableGroupJoinProducer extends TableGroupProducer {
|
|||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext);
|
||||
|
||||
/**
|
||||
* Create a TableGroup as defined for this producer
|
||||
*/
|
||||
default TableGroup createRootTableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
SqlAstCreationState creationState) {
|
||||
return createRootTableGroupJoin(
|
||||
navigablePath,
|
||||
lhs,
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
predicateConsumer,
|
||||
creationState.getSqlAliasBaseGenerator(),
|
||||
creationState.getSqlExpressionResolver(),
|
||||
creationState.getCreationContext()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a TableGroupJoin as defined for this producer
|
||||
*/
|
||||
TableGroup createRootTableGroupJoin(
|
||||
NavigablePath navigablePath,
|
||||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
Consumer<Predicate> predicateConsumer,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext);
|
||||
}
|
||||
|
|
|
@ -10,7 +10,10 @@ import java.util.ArrayList;
|
|||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.QueryException;
|
||||
import org.hibernate.dialect.DerbyDialect;
|
||||
import org.hibernate.dialect.TiDBDialect;
|
||||
import org.hibernate.query.Query;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
|
@ -25,9 +28,11 @@ import org.junit.jupiter.api.AfterEach;
|
|||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.hibernate.testing.orm.junit.ExtraAssertions.assertTyping;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* Implementation of WithClauseTest.
|
||||
|
@ -54,6 +59,26 @@ public class WithClauseTest {
|
|||
data.cleanup( scope );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithClauseFailsWithFetch(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
try {
|
||||
session.createQuery( "from Animal a inner join fetch a.offspring as o with o.bodyWeight = :someLimit" )
|
||||
.setParameter( "someLimit", 1 )
|
||||
.list();
|
||||
fail( "ad-hoc on clause allowed with fetched association" );
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
assertTyping( QueryException.class, e.getCause() );
|
||||
}
|
||||
catch ( HibernateException e ) {
|
||||
// the expected response...
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithClause(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
|
@ -85,7 +110,16 @@ public class WithClauseTest {
|
|||
.list();
|
||||
assertTrue( list.isEmpty(), "ad-hoc on did not take effect" );
|
||||
|
||||
list = session.createQuery( "from Human h inner join h.offspring o with o.mother.father = :cousin" )
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SkipForDialect(dialectClass = TiDBDialect.class, reason = "TiDB db does not support subqueries for ON condition")
|
||||
public void testWithClauseWithImplicitJoin(SessionFactoryScope scope) {
|
||||
scope.inTransaction(
|
||||
(session) -> {
|
||||
List list = session.createQuery( "from Human h inner join h.offspring o with o.mother.father = :cousin" )
|
||||
.setParameter( "cousin", session.load( Human.class, Long.valueOf( "123" ) ) )
|
||||
.list();
|
||||
assertTrue( list.isEmpty(), "ad-hoc did take effect" );
|
||||
|
|
|
@ -187,7 +187,7 @@ public class CriteriaLiteralsTest extends BaseEntityManagerFunctionalTestCase {
|
|||
1,
|
||||
sqlStatementInterceptor.getSqlQueries().size()
|
||||
);
|
||||
sqlStatementInterceptor.assertExecuted( "select a1_0.name from Book b1_0 join Author a1_0 on a1_0.book_id=b1_0.id where b1_0.name=? and a1_0.index_id=?" );
|
||||
sqlStatementInterceptor.assertExecuted( "select a1_0.name from Book b1_0 join Author a1_0 on b1_0.id=a1_0.book_id where b1_0.name=? and a1_0.index_id=?" );
|
||||
} );
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue