Implement support for avoiding joins when accessing FK keys

This commit is contained in:
Christian Beikov 2021-04-13 09:30:44 +02:00
parent c74e5ef595
commit df9d285f2c
110 changed files with 952 additions and 539 deletions

View File

@ -7,6 +7,7 @@
package org.hibernate.userguide.mapping.identifier.composite; package org.hibernate.userguide.mapping.identifier.composite;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.time.OffsetDateTime;
import org.hibernate.dialect.H2Dialect; import org.hibernate.dialect.H2Dialect;
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase; import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
@ -33,15 +34,16 @@ public class EmbeddedIdDatabaseGeneratedValueTest extends BaseEntityManagerFunct
@TestForIssue(jiraKey = "HHH-13096") @TestForIssue(jiraKey = "HHH-13096")
public void test() { public void test() {
final EventId eventId = doInJPA( this::entityManagerFactory, entityManager -> { final EventId eventId = doInJPA( this::entityManagerFactory, entityManager -> {
// On H2 1.4.199+ CURRENT_TIMESTAMP returns a timestamp with timezone
//tag::identifiers-composite-generated-database-example[] //tag::identifiers-composite-generated-database-example[]
Timestamp currentTimestamp = (Timestamp) entityManager OffsetDateTime currentTimestamp = (OffsetDateTime) entityManager
.createNativeQuery( .createNativeQuery(
"SELECT CURRENT_TIMESTAMP" ) "SELECT CURRENT_TIMESTAMP" )
.getSingleResult(); .getSingleResult();
EventId id = new EventId(); EventId id = new EventId();
id.setCategory( 1 ); id.setCategory( 1 );
id.setCreatedOn( currentTimestamp ); id.setCreatedOn( Timestamp.from( currentTimestamp.toInstant() ) );
Event event = new Event(); Event event = new Event();
event.setId( id ); event.setId( id );

View File

@ -101,7 +101,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
final List<Fetch> fetches = new ArrayList<>( naturalIdMapping.getNaturalIdAttributes().size() ); final List<Fetch> fetches = new ArrayList<>( naturalIdMapping.getNaturalIdAttributes().size() );
fetchParent.getReferencedMappingContainer().visitFetchables( fetchParent.getReferencedMappingContainer().visitFetchables(
fetchable -> { fetchable -> {
final NavigablePath navigablePath = fetchParent.getNavigablePath().append( fetchable.getFetchableName() ); final NavigablePath navigablePath = fetchParent.resolveNavigablePath( fetchable );
final Fetch fetch = fetchParent.generateFetchableFetch( final Fetch fetch = fetchParent.generateFetchableFetch(
fetchable, fetchable,
navigablePath, navigablePath,
@ -280,7 +280,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
SelectableMapping selectableMapping, SelectableMapping selectableMapping,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
final TableReference tableReference = rootTableGroup.getTableReference( selectableMapping.getContainingTableExpression() ); final TableReference tableReference = rootTableGroup.getTableReference( rootTableGroup.getNavigablePath(), selectableMapping.getContainingTableExpression() );
if ( tableReference == null ) { if ( tableReference == null ) {
throw new IllegalStateException( throw new IllegalStateException(
String.format( String.format(
@ -321,7 +321,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
fetchParent.getReferencedMappingContainer().visitFetchables( fetchParent.getReferencedMappingContainer().visitFetchables(
(fetchable) -> { (fetchable) -> {
final NavigablePath navigablePath = fetchParent.getNavigablePath().append( fetchable.getFetchableName() ); final NavigablePath navigablePath = fetchParent.resolveNavigablePath( fetchable );
final Fetch fetch = fetchParent.generateFetchableFetch( final Fetch fetch = fetchParent.generateFetchableFetch(
fetchable, fetchable,
navigablePath, navigablePath,

View File

@ -109,10 +109,13 @@ class DatabaseSnapshotExecutor {
domainResults.add( domainResults.add(
new QueryLiteral<>( null, IntegerType.INSTANCE ).createDomainResult( null, state ) new QueryLiteral<>( null, IntegerType.INSTANCE ).createDomainResult( null, state )
); );
final NavigablePath idNavigablePath = rootPath.append( entityDescriptor.getIdentifierMapping().getNavigableRole().getNavigableName() );
entityDescriptor.getIdentifierMapping().forEachSelectable( entityDescriptor.getIdentifierMapping().forEachSelectable(
(columnIndex, selection) -> { (columnIndex, selection) -> {
final TableReference tableReference = rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ); final TableReference tableReference = rootTableGroup.resolveTableReference(
idNavigablePath,
selection.getContainingTableExpression()
);
final JdbcParameter jdbcParameter = new JdbcParameterImpl( selection.getJdbcMapping() ); final JdbcParameter jdbcParameter = new JdbcParameterImpl( selection.getJdbcMapping() );
jdbcParameters.add( jdbcParameter ); jdbcParameters.add( jdbcParameter );

View File

@ -467,12 +467,13 @@ public class LoaderSelectBuilder {
Consumer<JdbcParameter> jdbcParameterConsumer, Consumer<JdbcParameter> jdbcParameterConsumer,
LoaderSqlAstCreationState sqlAstCreationState) { LoaderSqlAstCreationState sqlAstCreationState) {
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final NavigablePath navigablePath = rootNavigablePath.append( modelPart.getNavigableRole().getNavigableName() );
if ( numberColumns == 1 ) { if ( numberColumns == 1 ) {
modelPart.forEachSelectable( modelPart.forEachSelectable(
(columnIndex, selection) -> { (columnIndex, selection) -> {
final TableReference tableReference = rootTableGroup.resolveTableReference( final TableReference tableReference = rootTableGroup.resolveTableReference(
selection.getContainingTableExpression() ); navigablePath, selection.getContainingTableExpression() );
final ColumnReference columnRef = final ColumnReference columnRef =
(ColumnReference) sqlExpressionResolver.resolveSqlExpression( (ColumnReference) sqlExpressionResolver.resolveSqlExpression(
createColumnReferenceKey( tableReference, selection.getSelectionExpression() ), createColumnReferenceKey( tableReference, selection.getSelectionExpression() ),
@ -511,7 +512,7 @@ public class LoaderSelectBuilder {
modelPart.forEachSelectable( modelPart.forEachSelectable(
(columnIndex, selection) -> { (columnIndex, selection) -> {
final TableReference tableReference = rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ); final TableReference tableReference = rootTableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() );
columnReferences.add( columnReferences.add(
(ColumnReference) sqlExpressionResolver.resolveSqlExpression( (ColumnReference) sqlExpressionResolver.resolveSqlExpression(
createColumnReferenceKey( tableReference, selection.getSelectionExpression() ), createColumnReferenceKey( tableReference, selection.getSelectionExpression() ),
@ -629,7 +630,6 @@ public class LoaderSelectBuilder {
List<Fetch> fetches, List<Fetch> fetches,
List<String> bagRoles) { List<String> bagRoles) {
return (fetchable, isKeyFetchable) -> { return (fetchable, isKeyFetchable) -> {
final NavigablePath parentNavigablePath = fetchParent.getNavigablePath();
final NavigablePath fetchablePath; final NavigablePath fetchablePath;
if ( isKeyFetchable ) { if ( isKeyFetchable ) {
@ -659,16 +659,16 @@ public class LoaderSelectBuilder {
if ( identifierMapping != null ) { if ( identifierMapping != null ) {
fetchablePath = new EntityIdentifierNavigablePath( fetchablePath = new EntityIdentifierNavigablePath(
parentNavigablePath, fetchParent.getNavigablePath(),
attributeName( identifierMapping ) attributeName( identifierMapping )
); );
} }
else { else {
fetchablePath = parentNavigablePath.append( fetchable.getFetchableName() ); fetchablePath = fetchParent.resolveNavigablePath( fetchable );
} }
} }
else { else {
fetchablePath = parentNavigablePath.append( fetchable.getFetchableName() ); fetchablePath = fetchParent.resolveNavigablePath( fetchable );
} }
final Fetch biDirectionalFetch = fetchable.resolveCircularFetch( final Fetch biDirectionalFetch = fetchable.resolveCircularFetch(
@ -879,6 +879,7 @@ public class LoaderSelectBuilder {
final PluralAttributeMapping attributeMapping = (PluralAttributeMapping) loadable; final PluralAttributeMapping attributeMapping = (PluralAttributeMapping) loadable;
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor(); final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();
final NavigablePath navigablePath = rootNavigablePath.append( attributeMapping.getAttributeName() );
final Expression fkExpression; final Expression fkExpression;
@ -892,7 +893,7 @@ public class LoaderSelectBuilder {
simpleFkDescriptor.getSelectionExpression() simpleFkDescriptor.getSelectionExpression()
), ),
sqlAstProcessingState -> new ColumnReference( sqlAstProcessingState -> new ColumnReference(
rootTableGroup.resolveTableReference( simpleFkDescriptor.getContainingTableExpression() ), rootTableGroup.resolveTableReference( navigablePath, simpleFkDescriptor.getContainingTableExpression() ),
simpleFkDescriptor.getSelectionExpression(), simpleFkDescriptor.getSelectionExpression(),
false, false,
null, null,
@ -914,7 +915,7 @@ public class LoaderSelectBuilder {
selection.getSelectionExpression() selection.getSelectionExpression()
), ),
sqlAstProcessingState -> new ColumnReference( sqlAstProcessingState -> new ColumnReference(
rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ), rootTableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() ),
selection, selection,
this.creationContext.getSessionFactory() this.creationContext.getSessionFactory()
) )
@ -961,11 +962,12 @@ public class LoaderSelectBuilder {
loadingSqlAst.getFromClause().visitRoots( subQuery.getFromClause()::addRoot ); loadingSqlAst.getFromClause().visitRoots( subQuery.getFromClause()::addRoot );
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlExpressionResolver(); final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlExpressionResolver();
final NavigablePath navigablePath = ownerTableGroup.getNavigablePath().append( attributeMapping.getAttributeName() );
fkDescriptor.visitTargetSelectables( fkDescriptor.visitTargetSelectables(
(valuesPosition, selection) -> { (valuesPosition, selection) -> {
// for each column, resolve a SqlSelection and add it to the sub-query select-clause // for each column, resolve a SqlSelection and add it to the sub-query select-clause
final TableReference tableReference = ownerTableGroup.resolveTableReference( selection.getContainingTableExpression() ); final TableReference tableReference = ownerTableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() );
final Expression expression = sqlExpressionResolver.resolveSqlExpression( final Expression expression = sqlExpressionResolver.resolveSqlExpression(
createColumnReferenceKey( tableReference, selection.getSelectionExpression() ), createColumnReferenceKey( tableReference, selection.getSelectionExpression() ),
sqlAstProcessingState -> new ColumnReference( sqlAstProcessingState -> new ColumnReference(

View File

@ -162,6 +162,7 @@ public abstract class AbstractCompositeIdentifierMapping
TableGroup lhs, TableGroup lhs,
String explicitSourceAlias, String explicitSourceAlias,
SqlAstJoinType sqlAstJoinType, SqlAstJoinType sqlAstJoinType,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator, SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,
@ -228,12 +229,13 @@ public abstract class AbstractCompositeIdentifierMapping
SqlAstCreationState sqlAstCreationState) { SqlAstCreationState sqlAstCreationState) {
final SelectableMappings selectableMappings = getEmbeddableTypeDescriptor(); final SelectableMappings selectableMappings = getEmbeddableTypeDescriptor();
final List<ColumnReference> columnReferences = CollectionHelper.arrayList( selectableMappings.getJdbcTypeCount() ); final List<ColumnReference> columnReferences = CollectionHelper.arrayList( selectableMappings.getJdbcTypeCount() );
final TableReference defaultTableReference = tableGroup.resolveTableReference( getContainingTableExpression() ); final NavigablePath navigablePath = tableGroup.getNavigablePath().append( getNavigableRole().getNavigableName() );
final TableReference defaultTableReference = tableGroup.resolveTableReference( navigablePath, getContainingTableExpression() );
getEmbeddableTypeDescriptor().forEachSelectable( getEmbeddableTypeDescriptor().forEachSelectable(
(columnIndex, selection) -> { (columnIndex, selection) -> {
final TableReference tableReference = selection.getContainingTableExpression().equals( defaultTableReference.getTableExpression() ) final TableReference tableReference = selection.getContainingTableExpression().equals( defaultTableReference.getTableExpression() )
? defaultTableReference ? defaultTableReference
: tableGroup.resolveTableReference( selection.getContainingTableExpression() ); : tableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() );
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver() final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver()
.resolveSqlExpression( .resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( SqlExpressionResolver.createColumnReferenceKey(

View File

@ -454,6 +454,7 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectableMapp
attributeIndex, attributeIndex,
bootPropertyDescriptor, bootPropertyDescriptor,
entityPersister, entityPersister,
entityPersister,
(EntityType) subtype, (EntityType) subtype,
getRepresentationStrategy().resolvePropertyAccess( bootPropertyDescriptor ), getRepresentationStrategy().resolvePropertyAccess( bootPropertyDescriptor ),
compositeType.getCascadeStyle( attributeIndex ), compositeType.getCascadeStyle( attributeIndex ),

View File

@ -32,6 +32,8 @@ public interface ForeignKeyDescriptor extends VirtualModelPart {
ModelPart getKeyPart(); ModelPart getKeyPart();
ModelPart getTargetPart();
/** /**
* Create a DomainResult for the referring-side of the fk * Create a DomainResult for the referring-side of the fk
*/ */

View File

@ -57,7 +57,7 @@ public abstract class AbstractDomainPath implements DomainPath {
SqlAstCreationState creationState) { SqlAstCreationState creationState) {
if ( referenceModelPart instanceof BasicValuedModelPart ) { if ( referenceModelPart instanceof BasicValuedModelPart ) {
final BasicValuedModelPart selection = (BasicValuedModelPart) referenceModelPart; final BasicValuedModelPart selection = (BasicValuedModelPart) referenceModelPart;
final TableReference tableReference = tableGroup.resolveTableReference( selection.getContainingTableExpression() ); final TableReference tableReference = tableGroup.resolveTableReference( getNavigablePath(), selection.getContainingTableExpression() );
return creationState.getSqlExpressionResolver().resolveSqlExpression( return creationState.getSqlExpressionResolver().resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( SqlExpressionResolver.createColumnReferenceKey(
selection.getContainingTableExpression(), selection.getContainingTableExpression(),
@ -221,7 +221,7 @@ public abstract class AbstractDomainPath implements DomainPath {
String collation, String collation,
SortOrder sortOrder, SortOrder sortOrder,
SqlAstCreationState creationState) { SqlAstCreationState creationState) {
final TableReference tableReference = tableGroup.resolveTableReference( selection.getContainingTableExpression() ); final TableReference tableReference = tableGroup.resolveTableReference( getNavigablePath(), selection.getContainingTableExpression() );
final Expression expression = creationState.getSqlExpressionResolver().resolveSqlExpression( final Expression expression = creationState.getSqlExpressionResolver().resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( SqlExpressionResolver.createColumnReferenceKey(
selection.getContainingTableExpression(), selection.getContainingTableExpression(),

View File

@ -190,7 +190,7 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions,
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final TableGroup tableGroup = fromClauseAccess.getTableGroup( fetchablePath.getParent().getParent() ); final TableGroup tableGroup = fromClauseAccess.getTableGroup( fetchablePath.getParent().getParent() );
final TableReference tableReference = tableGroup.getTableReference( table ); final TableReference tableReference = tableGroup.getTableReference( fetchablePath, table );
final Expression columnReference = sqlExpressionResolver.resolveSqlExpression( final Expression columnReference = sqlExpressionResolver.resolveSqlExpression(
createColumnReferenceKey( tableReference, column ), createColumnReferenceKey( tableReference, column ),
processingState -> new ColumnReference( processingState -> new ColumnReference(

View File

@ -153,7 +153,7 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
.getSessionFactory(); .getSessionFactory();
final TableGroup tableGroup = fromClauseAccess.getTableGroup( fetchParent.getNavigablePath().getParent() ); final TableGroup tableGroup = fromClauseAccess.getTableGroup( fetchParent.getNavigablePath().getParent() );
final TableReference tableReference = tableGroup.getTableReference( table ); final TableReference tableReference = tableGroup.getTableReference( fetchablePath, table );
final Expression columnReference = sqlExpressionResolver.resolveSqlExpression( final Expression columnReference = sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( tableReference, column ), SqlExpressionResolver.createColumnReferenceKey( tableReference, column ),

View File

@ -202,7 +202,7 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
.getSqlExpressionResolver(); .getSqlExpressionResolver();
final TableReference rootTableReference; final TableReference rootTableReference;
try { try {
rootTableReference = tableGroup.resolveTableReference( rootTable ); rootTableReference = tableGroup.resolveTableReference( navigablePath, rootTable );
} }
catch (Exception e) { catch (Exception e) {
throw new IllegalStateException( throw new IllegalStateException(

View File

@ -217,7 +217,11 @@ public class BasicValuedSingularAttributeMapping
private SqlSelection resolveSqlSelection(TableGroup tableGroup, DomainResultCreationState creationState) { private SqlSelection resolveSqlSelection(TableGroup tableGroup, DomainResultCreationState creationState) {
final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver(); final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState().getSqlExpressionResolver();
final TableReference tableReference = tableGroup.resolveTableReference( getContainingTableExpression() ); final TableReference tableReference = tableGroup.resolveTableReference(
tableGroup.getNavigablePath()
.append( getNavigableRole().getNavigableName() ),
getContainingTableExpression()
);
final String tableAlias = tableReference.getIdentificationVariable(); final String tableAlias = tableReference.getIdentificationVariable();
return expressionResolver.resolveSqlSelection( return expressionResolver.resolveSqlSelection(
expressionResolver.resolveSqlExpression( expressionResolver.resolveSqlExpression(

View File

@ -228,12 +228,13 @@ public class EmbeddedAttributeMapping
SqmToSqlAstConverter walker, SqmToSqlAstConverter walker,
SqlAstCreationState sqlAstCreationState) { SqlAstCreationState sqlAstCreationState) {
final List<ColumnReference> columnReferences = CollectionHelper.arrayList( embeddableMappingType.getJdbcTypeCount() ); final List<ColumnReference> columnReferences = CollectionHelper.arrayList( embeddableMappingType.getJdbcTypeCount() );
final TableReference defaultTableReference = tableGroup.resolveTableReference( getContainingTableExpression() ); final NavigablePath navigablePath = tableGroup.getNavigablePath().append( getNavigableRole().getNavigableName() );
final TableReference defaultTableReference = tableGroup.resolveTableReference( navigablePath, getContainingTableExpression() );
getEmbeddableTypeDescriptor().forEachSelectable( getEmbeddableTypeDescriptor().forEachSelectable(
(columnIndex, selection) -> { (columnIndex, selection) -> {
final TableReference tableReference = selection.getContainingTableExpression().equals( defaultTableReference.getTableExpression() ) final TableReference tableReference = selection.getContainingTableExpression().equals( defaultTableReference.getTableExpression() )
? defaultTableReference ? defaultTableReference
: tableGroup.resolveTableReference( selection.getContainingTableExpression() ); : tableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() );
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression( final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( SqlExpressionResolver.createColumnReferenceKey(
tableReference, tableReference,
@ -273,6 +274,7 @@ public class EmbeddedAttributeMapping
TableGroup lhs, TableGroup lhs,
String explicitSourceAlias, String explicitSourceAlias,
SqlAstJoinType sqlAstJoinType, SqlAstJoinType sqlAstJoinType,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator, SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,

View File

@ -176,7 +176,11 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
sqlExpressionResolver.resolveSqlExpression( sqlExpressionResolver.resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( selection.getContainingTableExpression(), selection.getSelectionExpression() ), SqlExpressionResolver.createColumnReferenceKey( selection.getContainingTableExpression(), selection.getSelectionExpression() ),
sqlAstProcessingState -> new ColumnReference( sqlAstProcessingState -> new ColumnReference(
tableGroup.resolveTableReference( selection.getContainingTableExpression() ), tableGroup.resolveTableReference(
tableGroup.getNavigablePath()
.append( getNavigableRole().getNavigableName() ),
selection.getContainingTableExpression()
),
selection, selection,
sqlAstCreationState.getCreationContext().getSessionFactory() sqlAstCreationState.getCreationContext().getSessionFactory()
) )
@ -193,6 +197,7 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
TableGroup lhs, TableGroup lhs,
String explicitSourceAlias, String explicitSourceAlias,
SqlAstJoinType sqlAstJoinType, SqlAstJoinType sqlAstJoinType,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator, SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,

View File

@ -245,6 +245,7 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
tableGroup, tableGroup,
null, null,
SqlAstJoinType.INNER, SqlAstJoinType.INNER,
true,
LockMode.NONE, LockMode.NONE,
creationState.getSqlAstCreationState() creationState.getSqlAstCreationState()
); );
@ -370,7 +371,11 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
return tableGroup.getPrimaryTableReference(); return tableGroup.getPrimaryTableReference();
} }
final TableReference tableReference = lhs.resolveTableReference( table ); final TableReference tableReference = lhs.resolveTableReference(
lhs.getNavigablePath()
.append( getNavigableRole().getNavigableName() ),
table
);
if ( tableReference != null ) { if ( tableReference != null ) {
return tableReference; return tableReference;
} }
@ -407,6 +412,11 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
return keyMappingType.getEmbeddableTypeDescriptor().getEmbeddedValueMapping(); return keyMappingType.getEmbeddableTypeDescriptor().getEmbeddedValueMapping();
} }
@Override
public ModelPart getTargetPart() {
return targetMappingType.getEmbeddableTypeDescriptor().getEmbeddedValueMapping();
}
@Override @Override
public MappingType getPartMappingType() { public MappingType getPartMappingType() {
return targetMappingType.getPartMappingType(); return targetMappingType.getPartMappingType();
@ -437,6 +447,7 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
tableGroup, tableGroup,
null, null,
null, null,
true,
LockMode.NONE, LockMode.NONE,
creationState.getSqlAstCreationState() creationState.getSqlAstCreationState()
); );

View File

@ -151,7 +151,7 @@ public class EntityCollectionPart
final FromClauseAccess fromClauseAccess = creationState.getSqlAstCreationState().getFromClauseAccess(); final FromClauseAccess fromClauseAccess = creationState.getSqlAstCreationState().getFromClauseAccess();
creationState.registerVisitedAssociationKey( getForeignKeyDescriptor().getAssociationKey() ); creationState.registerVisitedAssociationKey( getForeignKeyDescriptor().getAssociationKey() );
fromClauseAccess.resolveTableGroup( TableGroup tableGroup = fromClauseAccess.resolveTableGroup(
fetchablePath, fetchablePath,
np -> { np -> {
// We need to create one. The Result will be able to find it later by path // We need to create one. The Result will be able to find it later by path
@ -166,7 +166,7 @@ public class EntityCollectionPart
} }
); );
return new EntityFetchJoinedImpl( fetchParent, this, lockMode, selected, fetchablePath, creationState ); return new EntityFetchJoinedImpl( fetchParent, this, tableGroup, lockMode, selected, fetchablePath, creationState );
} }
@Override @Override
@ -347,6 +347,7 @@ public class EntityCollectionPart
TableGroup lhs, TableGroup lhs,
String explicitSourceAlias, String explicitSourceAlias,
SqlAstJoinType sqlAstJoinType, SqlAstJoinType sqlAstJoinType,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator, SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,
@ -356,6 +357,7 @@ public class EntityCollectionPart
lhs, lhs,
explicitSourceAlias, explicitSourceAlias,
sqlAstJoinType, sqlAstJoinType,
fetched,
lockMode, lockMode,
aliasBaseGenerator, aliasBaseGenerator,
sqlExpressionResolver, sqlExpressionResolver,

View File

@ -42,7 +42,11 @@ public class EntityDiscriminatorMappingImpl extends AbstractEntityDiscriminatorM
final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState() final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState()
.getSqlExpressionResolver(); .getSqlExpressionResolver();
final TableReference tableReference = tableGroup.resolveTableReference( getContainingTableExpression() ); final TableReference tableReference = tableGroup.resolveTableReference(
tableGroup.getNavigablePath()
.append( getNavigableRole().getNavigableName() ),
getContainingTableExpression()
);
return expressionResolver.resolveSqlSelection( return expressionResolver.resolveSqlSelection(
expressionResolver.resolveSqlExpression( expressionResolver.resolveSqlExpression(

View File

@ -83,7 +83,7 @@ public class EntityRowIdMappingImpl implements EntityRowIdMapping, SelectableMap
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final TableReference columnTableReference = tableGroup.resolveTableReference( tableExpression ); final TableReference columnTableReference = tableGroup.resolveTableReference( navigablePath, tableExpression );
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection( final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression( sqlExpressionResolver.resolveSqlExpression(

View File

@ -149,7 +149,7 @@ public class EntityVersionMappingImpl implements EntityVersionMapping, FetchOpti
final TableGroup tableGroup = sqlAstCreationState.getFromClauseAccess().findTableGroup( fetchParent.getNavigablePath() ); final TableGroup tableGroup = sqlAstCreationState.getFromClauseAccess().findTableGroup( fetchParent.getNavigablePath() );
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final TableReference columnTableReference = tableGroup.resolveTableReference( columnTableExpression ); final TableReference columnTableReference = tableGroup.resolveTableReference( fetchablePath, columnTableExpression );
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection( final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression( sqlExpressionResolver.resolveSqlExpression(
@ -220,7 +220,11 @@ public class EntityVersionMappingImpl implements EntityVersionMapping, FetchOpti
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final TableReference columnTableReference = tableGroup.resolveTableReference( columnTableExpression ); final TableReference columnTableReference = tableGroup.resolveTableReference(
tableGroup.getNavigablePath()
.append( getNavigableRole().getNavigableName() ),
columnTableExpression
);
return sqlExpressionResolver.resolveSqlSelection( return sqlExpressionResolver.resolveSqlSelection(
sqlExpressionResolver.resolveSqlExpression( sqlExpressionResolver.resolveSqlExpression(

View File

@ -233,6 +233,7 @@ public class MappingModelCreationHelper {
idAttributeMappings.size(), idAttributeMappings.size(),
bootIdSubProperty, bootIdSubProperty,
attributeMappingType, attributeMappingType,
entityPersister,
keyManyToOnePropertyType, keyManyToOnePropertyType,
entityPersister.getRepresentationStrategy().resolvePropertyAccess( bootIdSubProperty ), entityPersister.getRepresentationStrategy().resolvePropertyAccess( bootIdSubProperty ),
CascadeStyles.ALL, CascadeStyles.ALL,
@ -1408,6 +1409,7 @@ public class MappingModelCreationHelper {
int stateArrayPosition, int stateArrayPosition,
Property bootProperty, Property bootProperty,
ManagedMappingType declaringType, ManagedMappingType declaringType,
EntityPersister declaringEntityPersister,
EntityType attrType, EntityType attrType,
PropertyAccess propertyAccess, PropertyAccess propertyAccess,
CascadeStyle cascadeStyle, CascadeStyle cascadeStyle,
@ -1454,6 +1456,7 @@ public class MappingModelCreationHelper {
fetchStrategy, fetchStrategy,
entityPersister, entityPersister,
declaringType, declaringType,
declaringEntityPersister,
propertyAccess propertyAccess
); );

View File

@ -417,6 +417,11 @@ public class PluralAttributeMappingImpl
return separateCollectionTable; return separateCollectionTable;
} }
@Override
public boolean containsTableReference(String tableExpression) {
return tableExpression.equals( separateCollectionTable );
}
@Override @Override
public int getStateArrayPosition() { public int getStateArrayPosition() {
return stateArrayPosition; return stateArrayPosition;
@ -494,6 +499,7 @@ public class PluralAttributeMappingImpl
lhsTableGroup, lhsTableGroup,
null, null,
SqlAstJoinType.LEFT, SqlAstJoinType.LEFT,
true,
lockMode, lockMode,
creationState.getSqlAstCreationState() creationState.getSqlAstCreationState()
); );
@ -559,6 +565,7 @@ public class PluralAttributeMappingImpl
TableGroup lhs, TableGroup lhs,
String explicitSourceAlias, String explicitSourceAlias,
SqlAstJoinType sqlAstJoinType, SqlAstJoinType sqlAstJoinType,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator, SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,
@ -570,6 +577,7 @@ public class PluralAttributeMappingImpl
lhs, lhs,
explicitSourceAlias, explicitSourceAlias,
sqlAstJoinType, sqlAstJoinType,
fetched,
lockMode, lockMode,
aliasBaseGenerator, aliasBaseGenerator,
sqlExpressionResolver, sqlExpressionResolver,
@ -582,6 +590,7 @@ public class PluralAttributeMappingImpl
lhs, lhs,
explicitSourceAlias, explicitSourceAlias,
sqlAstJoinType, sqlAstJoinType,
fetched,
lockMode, lockMode,
aliasBaseGenerator, aliasBaseGenerator,
sqlExpressionResolver, sqlExpressionResolver,
@ -600,12 +609,14 @@ public class PluralAttributeMappingImpl
TableGroup lhs, TableGroup lhs,
String explicitSourceAlias, String explicitSourceAlias,
SqlAstJoinType sqlAstJoinType, SqlAstJoinType sqlAstJoinType,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator, SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) { SqlAstCreationContext creationContext) {
final TableGroup tableGroup = createOneToManyTableGroup( final TableGroup tableGroup = createOneToManyTableGroup(
navigablePath, navigablePath,
fetched,
lockMode, lockMode,
aliasBaseGenerator, aliasBaseGenerator,
sqlExpressionResolver, sqlExpressionResolver,
@ -632,6 +643,7 @@ public class PluralAttributeMappingImpl
private TableGroup createOneToManyTableGroup( private TableGroup createOneToManyTableGroup(
NavigablePath navigablePath, NavigablePath navigablePath,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator, SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,
@ -658,6 +670,7 @@ public class PluralAttributeMappingImpl
return new StandardTableGroup( return new StandardTableGroup(
navigablePath, navigablePath,
this, this,
fetched,
lockMode, lockMode,
primaryTableReference, primaryTableReference,
true, true,
@ -680,12 +693,14 @@ public class PluralAttributeMappingImpl
TableGroup lhs, TableGroup lhs,
String explicitSourceAlias, String explicitSourceAlias,
SqlAstJoinType sqlAstJoinType, SqlAstJoinType sqlAstJoinType,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator, SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) { SqlAstCreationContext creationContext) {
final TableGroup tableGroup = createCollectionTableGroup( final TableGroup tableGroup = createCollectionTableGroup(
navigablePath, navigablePath,
fetched,
lockMode, lockMode,
aliasBaseGenerator, aliasBaseGenerator,
sqlExpressionResolver, sqlExpressionResolver,
@ -712,6 +727,7 @@ public class PluralAttributeMappingImpl
private TableGroup createCollectionTableGroup( private TableGroup createCollectionTableGroup(
NavigablePath navigablePath, NavigablePath navigablePath,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator, SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,
@ -840,6 +856,7 @@ public class PluralAttributeMappingImpl
final StandardTableGroup tableGroup = new StandardTableGroup( final StandardTableGroup tableGroup = new StandardTableGroup(
navigablePath, navigablePath,
this, this,
fetched,
lockMode, lockMode,
collectionTableReference, collectionTableReference,
true, true,
@ -931,6 +948,7 @@ public class PluralAttributeMappingImpl
if ( getCollectionDescriptor().isOneToMany() ) { if ( getCollectionDescriptor().isOneToMany() ) {
return createOneToManyTableGroup( return createOneToManyTableGroup(
navigablePath, navigablePath,
false,
lockMode, lockMode,
creationState.getSqlAliasBaseGenerator(), creationState.getSqlAliasBaseGenerator(),
creationState.getSqlExpressionResolver(), creationState.getSqlExpressionResolver(),
@ -940,6 +958,7 @@ public class PluralAttributeMappingImpl
else { else {
return createCollectionTableGroup( return createCollectionTableGroup(
navigablePath, navigablePath,
false,
lockMode, lockMode,
creationState.getSqlAliasBaseGenerator(), creationState.getSqlAliasBaseGenerator(),
creationState.getSqlExpressionResolver(), creationState.getSqlExpressionResolver(),

View File

@ -9,12 +9,10 @@ package org.hibernate.metamodel.mapping.internal;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.function.BiConsumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.function.IntFunction; import java.util.function.IntFunction;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.engine.FetchStyle; import org.hibernate.engine.FetchStyle;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -24,17 +22,13 @@ import org.hibernate.metamodel.mapping.BasicValuedModelPart;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.MappingModelExpressable;
import org.hibernate.metamodel.mapping.MappingType; import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.SelectableConsumer; import org.hibernate.metamodel.mapping.SelectableConsumer;
import org.hibernate.metamodel.mapping.SelectableMapping; import org.hibernate.metamodel.mapping.SelectableMapping;
import org.hibernate.metamodel.mapping.SelectableMappings;
import org.hibernate.metamodel.model.domain.NavigableRole; import org.hibernate.metamodel.model.domain.NavigableRole;
import org.hibernate.proxy.HibernateProxy; import org.hibernate.proxy.HibernateProxy;
import org.hibernate.query.ComparisonOperator; import org.hibernate.query.ComparisonOperator;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
import org.hibernate.sql.ast.Clause; import org.hibernate.sql.ast.Clause;
import org.hibernate.sql.ast.SqlAstJoinType; import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
@ -94,14 +88,6 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
return targetSide.getContainingTableExpression(); return targetSide.getContainingTableExpression();
} }
public BasicValuedModelPart getKeySide() {
return keySide;
}
public BasicValuedModelPart getTargetSide() {
return targetSide;
}
@Override @Override
public ForeignKeyDescriptor withKeySelectionMapping( public ForeignKeyDescriptor withKeySelectionMapping(
IntFunction<SelectableMapping> selectableMappingAccess, IntFunction<SelectableMapping> selectableMappingAccess,
@ -146,11 +132,7 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
NavigablePath collectionPath, NavigablePath collectionPath,
TableGroup tableGroup, TableGroup tableGroup,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
if ( targetSide.getContainingTableExpression() return createDomainResult( collectionPath, tableGroup, targetSide, creationState );
.equals( keySide.getContainingTableExpression() ) ) {
return createDomainResult( collectionPath, tableGroup, targetSide, creationState );
}
return createDomainResult( collectionPath, tableGroup, creationState );
} }
@Override @Override
@ -204,7 +186,10 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState(); final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver(); final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
final TableReference tableReference = tableGroup.resolveTableReference( selectableMapping.getContainingTableExpression() ); final TableReference tableReference = tableGroup.resolveTableReference(
navigablePath.append( getNavigableRole().getNavigableName() ),
selectableMapping.getContainingTableExpression()
);
final String identificationVariable = tableReference.getIdentificationVariable(); final String identificationVariable = tableReference.getIdentificationVariable();
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection( final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
@ -333,7 +318,11 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
return tableGroup.getPrimaryTableReference(); return tableGroup.getPrimaryTableReference();
} }
final TableReference tableReference = lhs.resolveTableReference( table ); final TableReference tableReference = lhs.resolveTableReference(
lhs.getNavigablePath()
.append( getNavigableRole().getNavigableName() ),
table
);
if ( tableReference != null ) { if ( tableReference != null ) {
return tableReference; return tableReference;
} }
@ -342,10 +331,15 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
} }
@Override @Override
public ModelPart getKeyPart() { public BasicValuedModelPart getKeyPart() {
return keySide; return keySide;
} }
@Override
public BasicValuedModelPart getTargetPart() {
return targetSide;
}
@Override @Override
public MappingType getPartMappingType() { public MappingType getPartMappingType() {
return targetSide.getMappedType(); return targetSide.getMappedType();

View File

@ -6,6 +6,10 @@
*/ */
package org.hibernate.metamodel.mapping.internal; package org.hibernate.metamodel.mapping.internal;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.FetchStrategy; import org.hibernate.engine.FetchStrategy;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
@ -16,14 +20,13 @@ import org.hibernate.mapping.ManyToOne;
import org.hibernate.mapping.OneToOne; import org.hibernate.mapping.OneToOne;
import org.hibernate.mapping.ToOne; import org.hibernate.mapping.ToOne;
import org.hibernate.metamodel.mapping.AssociationKey; import org.hibernate.metamodel.mapping.AssociationKey;
import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.CollectionPart;
import org.hibernate.metamodel.mapping.EntityAssociationMapping; import org.hibernate.metamodel.mapping.EntityAssociationMapping;
import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityIdentifierMapping;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.JdbcMapping;
import org.hibernate.metamodel.mapping.ManagedMappingType; import org.hibernate.metamodel.mapping.ManagedMappingType;
import org.hibernate.metamodel.mapping.MappingType;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping;
import org.hibernate.metamodel.mapping.SelectableConsumer; import org.hibernate.metamodel.mapping.SelectableConsumer;
@ -42,15 +45,16 @@ import org.hibernate.sql.ast.spi.SqlAliasStemHelper;
import org.hibernate.sql.ast.spi.SqlAstCreationContext; import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver; import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.from.LazyTableGroup;
import org.hibernate.sql.ast.tree.from.StandardTableGroup; import org.hibernate.sql.ast.tree.from.StandardTableGroup;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin; import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer; 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.from.TableReference;
import org.hibernate.sql.results.graph.DomainResult; import org.hibernate.sql.results.graph.DomainResult;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchOptions;
import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParent;
import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable; import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
import org.hibernate.sql.results.graph.entity.EntityFetch; import org.hibernate.sql.results.graph.entity.EntityFetch;
@ -63,6 +67,9 @@ import org.hibernate.sql.results.graph.entity.internal.EntityResultImpl;
import org.hibernate.sql.results.graph.entity.internal.EntityResultJoinedSubclassImpl; import org.hibernate.sql.results.graph.entity.internal.EntityResultJoinedSubclassImpl;
import org.hibernate.sql.results.internal.domain.CircularBiDirectionalFetchImpl; import org.hibernate.sql.results.internal.domain.CircularBiDirectionalFetchImpl;
import org.hibernate.sql.results.internal.domain.CircularFetchImpl; import org.hibernate.sql.results.internal.domain.CircularFetchImpl;
import org.hibernate.tuple.IdentifierProperty;
import org.hibernate.type.ComponentType;
import org.hibernate.type.Type;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -85,9 +92,12 @@ public class ToOneAttributeMapping
private final EntityMappingType entityMappingType; private final EntityMappingType entityMappingType;
private final String referencedPropertyName; private final String referencedPropertyName;
private final String targetKeyPropertyName;
private final Set<String> targetKeyPropertyNames;
private final Cardinality cardinality; private final Cardinality cardinality;
private final String bidirectionalAttributeName; private final String bidirectionalAttributeName;
private final TableGroupProducer declaringTableGroupProducer;
private ForeignKeyDescriptor foreignKeyDescriptor; private ForeignKeyDescriptor foreignKeyDescriptor;
private String identifyingColumnsTableExpression; private String identifyingColumnsTableExpression;
@ -102,6 +112,7 @@ public class ToOneAttributeMapping
FetchStrategy mappedFetchStrategy, FetchStrategy mappedFetchStrategy,
EntityMappingType entityMappingType, EntityMappingType entityMappingType,
ManagedMappingType declaringType, ManagedMappingType declaringType,
EntityPersister declaringEntityPersister,
PropertyAccess propertyAccess) { PropertyAccess propertyAccess) {
super( super(
name, name,
@ -192,6 +203,35 @@ public class ToOneAttributeMapping
} }
this.navigableRole = navigableRole; this.navigableRole = navigableRole;
final CollectionPart.Nature nature = CollectionPart.Nature.fromName(
getNavigableRole().getParent().getLocalName()
);
if ( nature == null ) {
// This is a simple to-one association
this.declaringTableGroupProducer = declaringEntityPersister;
}
else {
// This is a collection part i.e. to-many association
final String collectionRoleName = getNavigableRole().getParent().getParent().getLocalName();
this.declaringTableGroupProducer = ( (PluralAttributeMapping) declaringEntityPersister.findAttributeMapping(
collectionRoleName.substring( collectionRoleName.lastIndexOf( '.' ) + 1 )
) );
}
if ( referencedPropertyName == null ) {
final IdentifierProperty identifierProperty = getEntityMappingType()
.getEntityPersister()
.getEntityMetamodel()
.getIdentifierProperty();
this.targetKeyPropertyName = identifierProperty.getName();
final Set<String> targetKeyPropertyNames = new HashSet<>( 2 );
targetKeyPropertyNames.add( EntityIdentifierMapping.ROLE_LOCAL_NAME );
addPrefixedPropertyNames( targetKeyPropertyNames, targetKeyPropertyName, identifierProperty.getType() );
this.targetKeyPropertyNames = targetKeyPropertyNames;
}
else {
this.targetKeyPropertyName = referencedPropertyName;
this.targetKeyPropertyNames = Collections.singleton( targetKeyPropertyName );
}
} }
private ToOneAttributeMapping(ToOneAttributeMapping original) { private ToOneAttributeMapping(ToOneAttributeMapping original) {
@ -209,8 +249,33 @@ public class ToOneAttributeMapping
this.unwrapProxy = original.unwrapProxy; this.unwrapProxy = original.unwrapProxy;
this.entityMappingType = original.entityMappingType; this.entityMappingType = original.entityMappingType;
this.referencedPropertyName = original.referencedPropertyName; this.referencedPropertyName = original.referencedPropertyName;
this.targetKeyPropertyName = original.targetKeyPropertyName;
this.targetKeyPropertyNames = original.targetKeyPropertyNames;
this.cardinality = original.cardinality; this.cardinality = original.cardinality;
this.bidirectionalAttributeName = original.bidirectionalAttributeName; this.bidirectionalAttributeName = original.bidirectionalAttributeName;
this.declaringTableGroupProducer = original.declaringTableGroupProducer;
}
private static void addPrefixedPropertyNames(
Set<String> targetKeyPropertyNames,
String prefix,
Type type) {
if ( type.isComponentType() ) {
targetKeyPropertyNames.add( prefix );
final ComponentType componentType = (ComponentType) type;
final String[] propertyNames = componentType.getPropertyNames();
final Type[] componentTypeSubtypes = componentType.getSubtypes();
for ( int i = 0, propertyNamesLength = propertyNames.length; i < propertyNamesLength; i++ ) {
addPrefixedPropertyNames(
targetKeyPropertyNames,
prefix + "." + propertyNames[i],
componentTypeSubtypes[i]
);
}
}
else {
targetKeyPropertyNames.add( prefix );
}
} }
public ToOneAttributeMapping copy() { public ToOneAttributeMapping copy() {
@ -233,10 +298,18 @@ public class ToOneAttributeMapping
return this.foreignKeyDescriptor; return this.foreignKeyDescriptor;
} }
public boolean canJoinForeignKey(EntityIdentifierMapping identifierMapping) {
return isKeyReferringSide && identifierMapping == getForeignKeyDescriptor().getTargetPart();
}
public String getReferencedPropertyName() { public String getReferencedPropertyName() {
return referencedPropertyName; return referencedPropertyName;
} }
public String getTargetKeyPropertyName() {
return targetKeyPropertyName;
}
public Cardinality getCardinality() { public Cardinality getCardinality() {
return cardinality; return cardinality;
} }
@ -256,6 +329,21 @@ public class ToOneAttributeMapping
return navigableRole; return navigableRole;
} }
@Override
public ModelPart findSubPart(String name) {
return findSubPart( name, null );
}
@Override
public ModelPart findSubPart(String name, EntityMappingType targetType) {
// Prefer resolving the key part of the foreign key rather than the target part if possible
// This way, we don't have to register table groups the target entity type
if ( name.equals( targetKeyPropertyName ) ) {
return foreignKeyDescriptor.getKeyPart();
}
return EntityValuedFetchable.super.findSubPart( name, targetType );
}
@Override @Override
public Fetch resolveCircularFetch( public Fetch resolveCircularFetch(
NavigablePath fetchablePath, NavigablePath fetchablePath,
@ -476,21 +564,23 @@ public class ToOneAttributeMapping
assert parentNavigablePath.equals( fetchParent.getNavigablePath() ); assert parentNavigablePath.equals( fetchParent.getNavigablePath() );
if ( fetchTiming == FetchTiming.IMMEDIATE && selected ) { if ( fetchTiming == FetchTiming.IMMEDIATE && selected ) {
final TableGroup tableGroup;
if ( fetchParent instanceof EntityResultJoinedSubclassImpl && if ( fetchParent instanceof EntityResultJoinedSubclassImpl &&
( (EntityPersister) fetchParent.getReferencedModePart() ).findDeclaredAttributeMapping( getPartName() ) == null ) { ( (EntityPersister) fetchParent.getReferencedModePart() ).findDeclaredAttributeMapping( getPartName() ) == null ) {
final TableGroup tableGroupJoin = createTableGroupJoin( tableGroup = createTableGroupJoin(
fetchablePath, fetchablePath,
true,
lockMode, lockMode,
creationState, creationState,
parentTableGroup parentTableGroup
); );
fromClauseAccess.registerTableGroup( fetchablePath, tableGroupJoin ); fromClauseAccess.registerTableGroup( fetchablePath, tableGroup );
} }
else { else {
fromClauseAccess.resolveTableGroup( tableGroup = fromClauseAccess.resolveTableGroup(
fetchablePath, fetchablePath,
np -> np ->
createTableGroupJoin( fetchablePath, lockMode, creationState, parentTableGroup ) createTableGroupJoin( fetchablePath, true, lockMode, creationState, parentTableGroup )
); );
} }
@ -498,6 +588,7 @@ public class ToOneAttributeMapping
return new EntityFetchJoinedImpl( return new EntityFetchJoinedImpl(
fetchParent, fetchParent,
this, this,
tableGroup,
lockMode, lockMode,
true, true,
fetchablePath, fetchablePath,
@ -578,6 +669,7 @@ public class ToOneAttributeMapping
tableGroup, tableGroup,
null, null,
tableGroup.isInnerJoinPossible() ? SqlAstJoinType.INNER : SqlAstJoinType.LEFT, tableGroup.isInnerJoinPossible() ? SqlAstJoinType.INNER : SqlAstJoinType.LEFT,
true,
null, null,
creationState.getSqlAstCreationState() creationState.getSqlAstCreationState()
); );
@ -600,7 +692,7 @@ public class ToOneAttributeMapping
return new EntityResultImpl( return new EntityResultImpl(
navigablePath, navigablePath,
this, this,
null, tableGroup, null,
creationState creationState
); );
} }
@ -608,6 +700,7 @@ public class ToOneAttributeMapping
private TableGroup createTableGroupJoin( private TableGroup createTableGroupJoin(
NavigablePath fetchablePath, NavigablePath fetchablePath,
boolean fetched,
LockMode lockMode, LockMode lockMode,
DomainResultCreationState creationState, DomainResultCreationState creationState,
TableGroup parentTableGroup) { TableGroup parentTableGroup) {
@ -628,6 +721,7 @@ public class ToOneAttributeMapping
parentTableGroup, parentTableGroup,
null, null,
sqlAstJoinType, sqlAstJoinType,
fetched,
lockMode, lockMode,
creationState.getSqlAstCreationState() creationState.getSqlAstCreationState()
); );
@ -646,22 +740,101 @@ public class ToOneAttributeMapping
TableGroup lhs, TableGroup lhs,
String explicitSourceAlias, String explicitSourceAlias,
SqlAstJoinType sqlAstJoinType, SqlAstJoinType sqlAstJoinType,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator, SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) { SqlAstCreationContext creationContext) {
final String aliasRoot = explicitSourceAlias == null ? sqlAliasStem : explicitSourceAlias; final String aliasRoot = explicitSourceAlias == null ? sqlAliasStem : explicitSourceAlias;
final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( aliasRoot ); final SqlAliasBase sqlAliasBase = aliasBaseGenerator.createSqlAliasBase( aliasRoot );
// We can only use the parent table group if the FK is located there
// If this is false, the FK is on a join table
final boolean canUseParentTableGroup = isKeyReferringSide && declaringTableGroupProducer.containsTableReference(
identifyingColumnsTableExpression );
final LazyTableGroup lazyTableGroup = new LazyTableGroup(
navigablePath,
() -> createTableGroupJoinInternal(
navigablePath,
fetched,
null,
sqlAliasBase,
sqlExpressionResolver,
creationContext
),
np -> {
if ( !canUseParentTableGroup ) {
return false;
}
NavigablePath path = np.getParent();
// Fast path
if ( path != null && navigablePath.equals( path ) ) {
return targetKeyPropertyNames.contains( np.getUnaliasedLocalName() );
}
final StringBuilder sb = new StringBuilder( np.getFullPath().length() );
sb.append( np.getUnaliasedLocalName() );
while ( path != null && !navigablePath.equals( path ) ) {
sb.insert( 0, '.' );
sb.insert( 0, path.getUnaliasedLocalName() );
path = path.getParent();
}
return path != null && navigablePath.equals( path ) && targetKeyPropertyNames.contains(
sb.toString()
);
},
this,
null,
sqlAliasBase,
creationContext.getSessionFactory(),
lhs
);
final TableReference lhsTableReference = lhs.resolveTableReference( navigablePath, identifyingColumnsTableExpression );
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
navigablePath,
sqlAstJoinType,
lazyTableGroup,
null
);
lazyTableGroup.setTableGroupInitializerCallback(
tableGroup -> tableGroupJoin.applyPredicate(
foreignKeyDescriptor.generateJoinPredicate(
lhsTableReference,
tableGroup.getPrimaryTableReference(),
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;
}
public TableGroup createTableGroupJoinInternal(
NavigablePath navigablePath,
boolean fetched,
LockMode lockMode,
final SqlAliasBase sqlAliasBase,
SqlExpressionResolver sqlExpressionResolver,
SqlAstCreationContext creationContext) {
final TableReference primaryTableReference = getEntityMappingType().createPrimaryTableReference( final TableReference primaryTableReference = getEntityMappingType().createPrimaryTableReference(
sqlAliasBase, sqlAliasBase,
sqlExpressionResolver, sqlExpressionResolver,
creationContext creationContext
); );
final TableGroup tableGroup = new StandardTableGroup( return new StandardTableGroup(
navigablePath, navigablePath,
this, this,
fetched,
lockMode, lockMode,
primaryTableReference, primaryTableReference,
false, false,
@ -676,25 +849,6 @@ public class ToOneAttributeMapping
), ),
creationContext.getSessionFactory() creationContext.getSessionFactory()
); );
final TableReference lhsTableReference = lhs.resolveTableReference( identifyingColumnsTableExpression );
final TableGroupJoin tableGroupJoin = new TableGroupJoin(
navigablePath,
sqlAstJoinType,
tableGroup,
foreignKeyDescriptor.generateJoinPredicate(
lhsTableReference,
primaryTableReference,
sqlAstJoinType,
sqlExpressionResolver,
creationContext
)
);
lhs.addTableGroupJoin( tableGroupJoin );
return tableGroupJoin;
} }
@Override @Override

View File

@ -117,7 +117,7 @@ public class ColumnReference implements OrderingExpression, SequencePart {
final int tableNumber = abstractEntityPersister.determineTableNumberForColumn( columnExpression ); final int tableNumber = abstractEntityPersister.determineTableNumberForColumn( columnExpression );
final String tableName = abstractEntityPersister.getTableName( tableNumber ); final String tableName = abstractEntityPersister.getTableName( tableNumber );
return tableGroup.getTableReference( tableName ); return tableGroup.getTableReference( tableGroup.getNavigablePath(), tableName );
} }
else { else {
return tableGroup.getPrimaryTableReference(); return tableGroup.getPrimaryTableReference();

View File

@ -16,7 +16,6 @@ import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.metamodel.model.domain.SimpleDomainType; import org.hibernate.metamodel.model.domain.SimpleDomainType;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.internal.SqmMappingModelHelper; import org.hibernate.query.sqm.internal.SqmMappingModelHelper;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
@ -128,14 +127,14 @@ public abstract class AbstractPluralAttribute<D,C,E>
} }
@Override @Override
public SqmPath<E> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) { public SqmPath<E> createSqmPath(SqmPath<?> lhs) {
final NavigablePath navigablePath = lhs.getNavigablePath().append( getPathName() ); final NavigablePath navigablePath = lhs.getNavigablePath().append( getPathName() );
//noinspection unchecked //noinspection unchecked
return new SqmPluralValuedSimplePath( return new SqmPluralValuedSimplePath(
navigablePath, navigablePath,
this, this,
lhs, lhs,
creationState.getCreationContext().getNodeBuilder() lhs.nodeBuilder()
); );
} }
} }

View File

@ -6,11 +6,10 @@
*/ */
package org.hibernate.metamodel.model.domain.internal; package org.hibernate.metamodel.model.domain.internal;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.model.domain.AnyMappingDomainType; import org.hibernate.metamodel.model.domain.AnyMappingDomainType;
import org.hibernate.metamodel.model.domain.BasicDomainType; import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmAnyValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmAnyValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
@ -20,7 +19,7 @@ import static javax.persistence.metamodel.Bindable.BindableType.SINGULAR_ATTRIBU
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class AnyMappingSqmPathSource<J> extends AbstractSqmPathSource<J> { public class AnyMappingSqmPathSource<J> extends AbstractSqmPathSource<J> {
private SqmPathSource<?> keyPathSource; private final SqmPathSource<?> keyPathSource;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
public AnyMappingSqmPathSource( public AnyMappingSqmPathSource(
@ -47,13 +46,9 @@ public class AnyMappingSqmPathSource<J> extends AbstractSqmPathSource<J> {
} }
@Override @Override
public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) { public SqmPath<J> createSqmPath(SqmPath<?> lhs) {
return new SqmAnyValuedSimplePath<>( final NavigablePath navigablePath = lhs.getNavigablePath().append( getPathName() );
lhs.getNavigablePath().append( getPathName() ), return new SqmAnyValuedSimplePath( navigablePath, this, lhs, lhs.nodeBuilder() );
this,
lhs,
creationState.getCreationContext().getQueryEngine().getCriteriaBuilder()
);
} }
} }

View File

@ -12,7 +12,6 @@ import org.hibernate.metamodel.model.domain.BasicDomainType;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.sqm.IllegalPathUsageException; import org.hibernate.query.sqm.IllegalPathUsageException;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
@ -42,13 +41,13 @@ public class BasicSqmPathSource<J>
} }
@Override @Override
public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) { public SqmPath<J> createSqmPath(SqmPath<?> lhs) {
final NavigablePath navigablePath = lhs.getNavigablePath().append( getPathName() ); final NavigablePath navigablePath = lhs.getNavigablePath().append( getPathName() );
return new SqmBasicValuedSimplePath<>( return new SqmBasicValuedSimplePath<>(
navigablePath, navigablePath,
this, this,
lhs, lhs,
creationState.getCreationContext().getNodeBuilder() lhs.nodeBuilder()
); );
} }

View File

@ -9,7 +9,6 @@ package org.hibernate.metamodel.model.domain.internal;
import org.hibernate.metamodel.model.domain.AllowableParameterType; import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
@ -49,12 +48,12 @@ public class EmbeddedSqmPathSource<J>
} }
@Override @Override
public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) { public SqmPath<J> createSqmPath(SqmPath<?> lhs) {
return new SqmEmbeddedValuedSimplePath<>( return new SqmEmbeddedValuedSimplePath<>(
lhs.getNavigablePath().append( getPathName() ), lhs.getNavigablePath().append( getPathName() ),
this, this,
lhs, lhs,
creationState.getCreationContext().getNodeBuilder() lhs.nodeBuilder()
); );
} }
} }

View File

@ -7,7 +7,6 @@
package org.hibernate.metamodel.model.domain.internal; package org.hibernate.metamodel.model.domain.internal;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmEntityValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
@ -36,12 +35,12 @@ public class EntitySqmPathSource<J> extends AbstractSqmPathSource<J> {
} }
@Override @Override
public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) { public SqmPath<J> createSqmPath(SqmPath<?> lhs) {
return new SqmEntityValuedSimplePath<>( return new SqmEntityValuedSimplePath<>(
lhs.getNavigablePath().append( getPathName() ), lhs.getNavigablePath().append( getPathName() ),
this, this,
lhs, lhs,
creationState.getCreationContext().getNodeBuilder() lhs.nodeBuilder()
); );
} }
} }

View File

@ -21,7 +21,6 @@ import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
import org.hibernate.metamodel.model.domain.JpaMetamodel; import org.hibernate.metamodel.model.domain.JpaMetamodel;
import org.hibernate.metamodel.model.domain.PersistentAttribute; import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.IllegalPathUsageException; import org.hibernate.query.sqm.IllegalPathUsageException;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath; import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
@ -86,12 +85,12 @@ public class EntityTypeImpl<J>
} }
@Override @Override
public SqmPath<?> createSqmPath(SqmPath lhs, SqmCreationState creationState) { public SqmPath<?> createSqmPath(SqmPath lhs) {
return new SqmBasicValuedSimplePath( return new SqmBasicValuedSimplePath(
lhs.getNavigablePath().append( EntityDiscriminatorMapping.ROLE_NAME ), lhs.getNavigablePath().append( EntityDiscriminatorMapping.ROLE_NAME ),
this, this,
lhs, lhs,
creationState.getCreationContext().getNodeBuilder() lhs.nodeBuilder()
); );
} }
@ -223,8 +222,7 @@ public class EntityTypeImpl<J>
@Override @Override
public SqmPath<J> createSqmPath( public SqmPath<J> createSqmPath(
SqmPath<?> lhs, SqmPath<?> lhs) {
SqmCreationState creationState) {
throw new UnsupportedOperationException( throw new UnsupportedOperationException(
"EntityType cannot be used to create an SqmPath - that would be an SqmFrom which are created directly" "EntityType cannot be used to create an SqmPath - that would be an SqmFrom which are created directly"
); );

View File

@ -6,13 +6,10 @@
*/ */
package org.hibernate.metamodel.model.domain.internal; package org.hibernate.metamodel.model.domain.internal;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.metamodel.model.domain.ManagedDomainType; import org.hibernate.metamodel.model.domain.ManagedDomainType;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.IllegalPathUsageException; import org.hibernate.query.sqm.IllegalPathUsageException;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.tree.domain.NonAggregatedCompositeSimplePath; import org.hibernate.query.sqm.tree.domain.NonAggregatedCompositeSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
import org.hibernate.query.sqm.tree.domain.SqmPath; import org.hibernate.query.sqm.tree.domain.SqmPath;
/** /**
@ -39,12 +36,12 @@ public class NonAggregatedCompositeSqmPathSource extends AbstractSqmPathSource i
} }
@Override @Override
public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) { public SqmPath createSqmPath(SqmPath lhs) {
return new NonAggregatedCompositeSimplePath( return new NonAggregatedCompositeSimplePath(
lhs.getNavigablePath().append( getPathName() ), lhs.getNavigablePath().append( getPathName() ),
this, this,
lhs, lhs,
creationState.getCreationContext().getNodeBuilder() lhs.nodeBuilder()
); );
} }
} }

View File

@ -221,10 +221,8 @@ public class SingularAttributeImpl<D,J>
} }
@Override @Override
public SqmPath<J> createSqmPath( public SqmPath<J> createSqmPath(SqmPath lhs) {
SqmPath lhs, return sqmPathSource.createSqmPath( lhs );
SqmCreationState creationState) {
return sqmPathSource.createSqmPath( lhs, creationState );
} }
private class DelayedKeyTypeAccess implements Supplier<SimpleDomainType<J>>, Serializable { private class DelayedKeyTypeAccess implements Supplier<SimpleDomainType<J>>, Serializable {

View File

@ -1950,7 +1950,7 @@ public abstract class AbstractCollectionPersister
tableReference = tableGroup.getPrimaryTableReference(); tableReference = tableGroup.getPrimaryTableReference();
} }
else if ( elementPersister instanceof Joinable ) { else if ( elementPersister instanceof Joinable ) {
tableReference = tableGroup.getTableReference( ( (Joinable) elementPersister ).getTableName() ); tableReference = tableGroup.getTableReference( tableGroup.getNavigablePath(), ( (Joinable) elementPersister ).getTableName() );
} }
if ( tableReference != null ) { if ( tableReference != null ) {

View File

@ -1267,7 +1267,7 @@ public abstract class AbstractEntityPersister
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
//noinspection unchecked //noinspection unchecked
return new EntityResultImpl( navigablePath, this, resultVariable, creationState ); return new EntityResultImpl( navigablePath, this, tableGroup, resultVariable, creationState );
} }
@Override @Override
@ -6613,6 +6613,7 @@ public abstract class AbstractEntityPersister
stateArrayPosition, stateArrayPosition,
bootProperty, bootProperty,
this, this,
this,
(EntityType) attrType, (EntityType) attrType,
propertyAccess, propertyAccess,
tupleAttrDefinition.getCascadeStyle(), tupleAttrDefinition.getCascadeStyle(),

View File

@ -1294,7 +1294,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
if ( hasSubclasses() ) { if ( hasSubclasses() ) {
//noinspection unchecked //noinspection unchecked
return new EntityResultJoinedSubclassImpl( navigablePath, this, resultVariable, creationState ); return new EntityResultJoinedSubclassImpl( navigablePath, this, tableGroup, resultVariable, creationState );
} }
else { else {
return super.createDomainResult( navigablePath, tableGroup, resultVariable, creationState ); return super.createDomainResult( navigablePath, tableGroup, resultVariable, creationState );
@ -1358,11 +1358,11 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
boolean addPrimaryTableCaseAsLastCaseExpression = false; boolean addPrimaryTableCaseAsLastCaseExpression = false;
for ( String tableName : discriminatorValuesByTableName.keySet() ) { for ( String tableName : discriminatorValuesByTableName.keySet() ) {
if ( !primaryTableReference.getTableExpression().equals( tableName ) ) { if ( !primaryTableReference.getTableExpression().equals( tableName ) ) {
TableReference tableReference = entityTableGroup.getTableReference( tableName ); TableReference tableReference = entityTableGroup.getTableReference( entityTableGroup.getNavigablePath(), tableName );
if ( tableReference == null ) { if ( tableReference == null ) {
// we have not yet created a TableReference for this sub-class table, but we need to because // we have not yet created a TableReference for this sub-class table, but we need to because
// it has a discriminator value associated with it // it has a discriminator value associated with it
tableReference = entityTableGroup.resolveTableReference( tableName ); tableReference = entityTableGroup.resolveTableReference( entityTableGroup.getNavigablePath(), tableName );
} }
final ColumnReference identifierColumnReference = getIdentifierColumnReference( tableReference ); final ColumnReference identifierColumnReference = getIdentifierColumnReference( tableReference );

View File

@ -51,9 +51,11 @@ import org.hibernate.sql.ast.spi.SqlAstCreationContext;
import org.hibernate.sql.ast.spi.SqlAstCreationState; import org.hibernate.sql.ast.spi.SqlAstCreationState;
import org.hibernate.sql.ast.spi.SqlExpressionResolver; import org.hibernate.sql.ast.spi.SqlExpressionResolver;
import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.ColumnReference;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.QueryLiteral; import org.hibernate.sql.ast.tree.expression.QueryLiteral;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate; import org.hibernate.sql.ast.tree.predicate.ComparisonPredicate;
import org.hibernate.sql.ast.tree.predicate.InListPredicate;
import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.type.AssociationType; import org.hibernate.type.AssociationType;
import org.hibernate.type.BasicType; import org.hibernate.type.BasicType;
@ -636,7 +638,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
frag.addValues( decodeTreatAsRequests( treatAsDeclarations ) ); frag.addValues( decodeTreatAsRequests( treatAsDeclarations ) );
} }
else { else {
frag.addValues( fullDiscriminatorValues() ); frag.addValues( fullDiscriminatorSQLValues() );
} }
return frag.toFragmentString(); return frag.toFragmentString();
@ -672,10 +674,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
return ArrayHelper.toStringArray( values ); return ArrayHelper.toStringArray( values );
} }
private String[] fullDiscriminatorValues; private String[] fullDiscriminatorSQLValues;
private String[] fullDiscriminatorValues() { private String[] fullDiscriminatorSQLValues() {
if ( fullDiscriminatorValues == null ) { String[] fullDiscriminatorSQLValues = this.fullDiscriminatorSQLValues;
if ( fullDiscriminatorSQLValues == null ) {
// first access; build it // first access; build it
final List<String> values = new ArrayList<>(); final List<String> values = new ArrayList<>();
for ( String subclass : getSubclassClosure() ) { for ( String subclass : getSubclassClosure() ) {
@ -684,7 +687,26 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
values.add( queryable.getDiscriminatorSQLValue() ); values.add( queryable.getDiscriminatorSQLValue() );
} }
} }
fullDiscriminatorValues = ArrayHelper.toStringArray( values ); this.fullDiscriminatorSQLValues = fullDiscriminatorSQLValues = ArrayHelper.toStringArray( values );
}
return fullDiscriminatorSQLValues;
}
private Object[] fullDiscriminatorValues;
private Object[] fullDiscriminatorValues() {
Object[] fullDiscriminatorValues = this.fullDiscriminatorValues;
if ( fullDiscriminatorValues == null ) {
// first access; build it
final List<Object> values = new ArrayList<>();
for ( String subclass : getSubclassClosure() ) {
final Queryable queryable = (Queryable) getFactory().getMetamodel().entityPersister( subclass );
if ( !queryable.isAbstract() ) {
values.add( queryable.getDiscriminatorValue() );
}
}
this.fullDiscriminatorValues = fullDiscriminatorValues = values.toArray(new Object[0]);
} }
return fullDiscriminatorValues; return fullDiscriminatorValues;
@ -946,23 +968,34 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
getDiscriminatorColumnName() getDiscriminatorColumnName()
); );
} }
final BasicType<?> discriminatorType = (BasicType<?>) getDiscriminatorType();
final Expression sqlExpression = sqlExpressionResolver.resolveSqlExpression(
columnReferenceKey,
sqlAstProcessingState -> new ColumnReference(
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
discriminatorExpression,
isDiscriminatorFormula(),
null,
null,
(discriminatorType).getJdbcMapping(),
getFactory()
)
);
if ( hasSubclasses() ) {
final Object[] discriminatorValues = fullDiscriminatorValues();
final List<Expression> values = new ArrayList<>( discriminatorValues.length );
for ( Object discriminatorValue : discriminatorValues ) {
values.add( new QueryLiteral<>( discriminatorValue, discriminatorType ) );
}
return new InListPredicate( sqlExpression, values );
}
return new ComparisonPredicate( return new ComparisonPredicate(
sqlExpressionResolver.resolveSqlExpression( sqlExpression,
columnReferenceKey,
sqlAstProcessingState -> new ColumnReference(
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
discriminatorExpression,
isDiscriminatorFormula(),
null,
null,
( (BasicType<?>) getDiscriminatorType() ).getJdbcMapping(),
getFactory()
)
),
ComparisonOperator.EQUAL, ComparisonOperator.EQUAL,
new QueryLiteral<>( new QueryLiteral<>(
getDiscriminatorValue(), getDiscriminatorValue(),
( (BasicType<?>) getDiscriminatorType() ) discriminatorType
) )
); );
} }

View File

@ -139,20 +139,12 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
} }
} }
final SqmFrom pathRootByExposedNavigable = sqmPathRegistry.findFromExposing( identifier ); final SqmFrom<?, ?> pathRootByExposedNavigable = sqmPathRegistry.findFromExposing( identifier );
if ( pathRootByExposedNavigable != null ) { if ( pathRootByExposedNavigable != null ) {
// identifier is an "unqualified attribute reference" // identifier is an "unqualified attribute reference"
validateAsRoot( pathRootByExposedNavigable ); validateAsRoot( pathRootByExposedNavigable );
SqmPath sqmPath = pathRootByExposedNavigable.getImplicitJoinPath( identifier ); SqmPath<?> sqmPath = (SqmPath<?>) pathRootByExposedNavigable.get( identifier );
if ( sqmPath == null ) {
final SqmPathSource subPathSource = pathRootByExposedNavigable.getReferencedPathSource()
.findSubPathSource( identifier );
sqmPath = subPathSource.createSqmPath( pathRootByExposedNavigable, creationState );
if ( !isTerminal ) {
pathRootByExposedNavigable.registerImplicitJoinPath( sqmPath );
}
}
if ( isTerminal ) { if ( isTerminal ) {
return sqmPath; return sqmPath;
} }

View File

@ -7,7 +7,6 @@
package org.hibernate.query.hql.internal; package org.hibernate.query.hql.internal;
import org.hibernate.NotYetImplementedFor6Exception; import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.query.SemanticException;
import org.hibernate.query.hql.HqlLogging; import org.hibernate.query.hql.HqlLogging;
import org.hibernate.query.hql.spi.SemanticPathPart; import org.hibernate.query.hql.spi.SemanticPathPart;
import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.hql.spi.SqmCreationState;
@ -43,18 +42,6 @@ public class DomainPathPart implements SemanticPathPart {
currentPath, currentPath,
name name
); );
final SqmPath<?> lhs = currentPath;
final SqmPathSource subPathSource = lhs.getReferencedPathSource().findSubPathSource( name );
if ( subPathSource == null ) {
throw new SemanticException( "Cannot resolve path (`" + name + "`) relative to `" + lhs.getNavigablePath() + "`" );
}
//noinspection unchecked
final SqmPath<?> existingImplicitJoinPath = lhs.getImplicitJoinPath( name );
if ( existingImplicitJoinPath != null ) {
currentPath = existingImplicitJoinPath;
return this;
}
// if we want to allow re-use of matched unaliased SqmFrom nodes // if we want to allow re-use of matched unaliased SqmFrom nodes
// //
// final SqmPathRegistry pathRegistry = creationState.getCurrentProcessingState().getPathRegistry(); // final SqmPathRegistry pathRegistry = creationState.getCurrentProcessingState().getPathRegistry();
@ -70,13 +57,11 @@ public class DomainPathPart implements SemanticPathPart {
// } // }
// } // }
// } // }
// currentPath = (SqmPath<?>) currentPath.get( name );
currentPath = subPathSource.createSqmPath( lhs, creationState );
if ( isTerminal ) { if ( isTerminal ) {
return currentPath; return currentPath;
} }
else { else {
lhs.registerImplicitJoinPath( currentPath );
return this; return this;
} }
} }

View File

@ -1925,8 +1925,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
if ( sqmPathType instanceof IdentifiableDomainType ) { if ( sqmPathType instanceof IdentifiableDomainType ) {
//noinspection unchecked //noinspection unchecked
final SqmPath idPath = ( (IdentifiableDomainType) sqmPathType ).getIdentifierDescriptor().createSqmPath( final SqmPath idPath = ( (IdentifiableDomainType) sqmPathType ).getIdentifierDescriptor().createSqmPath(
sqmPath, sqmPath
this
); );
if ( ctx.pathContinuation() == null ) { if ( ctx.pathContinuation() == null ) {
@ -1960,7 +1959,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
} }
//noinspection unchecked //noinspection unchecked
return versionAttribute.createSqmPath( sqmPath, this ); return versionAttribute.createSqmPath( sqmPath );
} }
throw new SemanticException( "Path does not reference an identifiable-type : " + sqmPath.getNavigablePath().getFullPath() ); throw new SemanticException( "Path does not reference an identifiable-type : " + sqmPath.getNavigablePath().getFullPath() );
@ -3832,8 +3831,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
//noinspection unchecked //noinspection unchecked
return ( (PluralPersistentAttribute<?, ?, ?>) pluralAttribute ).getIndexPathSource().createSqmPath( return ( (PluralPersistentAttribute<?, ?, ?>) pluralAttribute ).getIndexPathSource().createSqmPath(
sqmFrom, sqmFrom
this
); );
} }
@ -4143,8 +4141,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
//noinspection unchecked //noinspection unchecked
SqmPath result = attribute.getElementPathSource().createSqmPath( SqmPath result = attribute.getElementPathSource().createSqmPath(
pluralAttributePath, pluralAttributePath
this
); );
if ( ctx.pathContinuation() != null ) { if ( ctx.pathContinuation() != null ) {
@ -4162,15 +4159,15 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
if ( sqmPath instanceof SqmMapJoin ) { if ( sqmPath instanceof SqmMapJoin ) {
final SqmMapJoin sqmMapJoin = (SqmMapJoin) sqmPath; final SqmMapJoin sqmMapJoin = (SqmMapJoin) sqmPath;
return sqmMapJoin.getReferencedPathSource().getIndexPathSource().createSqmPath( sqmMapJoin, this ); return sqmMapJoin.getReferencedPathSource().getIndexPathSource().createSqmPath( sqmMapJoin );
} }
else { else {
assert sqmPath instanceof SqmPluralValuedSimplePath; assert sqmPath instanceof SqmPluralValuedSimplePath;
final SqmPluralValuedSimplePath mapPath = (SqmPluralValuedSimplePath) sqmPath; final SqmPluralValuedSimplePath mapPath = (SqmPluralValuedSimplePath) sqmPath;
final SqmPath keyPath = mapPath.getReferencedPathSource() final SqmPath keyPath = mapPath.getReferencedPathSource()
.getIndexPathSource() .getIndexPathSource()
.createSqmPath( mapPath, this ); .createSqmPath( mapPath );
mapPath.registerImplicitJoinPath( keyPath ); mapPath.registerReusablePath( keyPath );
return keyPath; return keyPath;
} }
} }

View File

@ -29,8 +29,6 @@ import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.QueryParameterImplementor; import org.hibernate.query.spi.QueryParameterImplementor;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.java.JavaTypedExpressable; import org.hibernate.type.descriptor.java.JavaTypedExpressable;
import org.hibernate.type.descriptor.java.MutabilityPlan;
import org.hibernate.type.descriptor.java.MutabilityPlanExposer;
import org.hibernate.type.spi.TypeConfiguration; import org.hibernate.type.spi.TypeConfiguration;
/** /**
@ -94,7 +92,7 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
} }
@SuppressWarnings({"WeakerAccess" }) @SuppressWarnings({"WeakerAccess" })
protected QueryParameterBinding<?> makeBinding(QueryParameterImplementor<?> queryParameter) { protected <T> QueryParameterBinding<T> makeBinding(QueryParameterImplementor<T> queryParameter) {
if ( parameterBindingMap == null ) { if ( parameterBindingMap == null ) {
parameterBindingMap = new IdentityHashMap<>(); parameterBindingMap = new IdentityHashMap<>();
} }
@ -108,7 +106,7 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
); );
} }
final QueryParameterBinding<?> binding = new QueryParameterBindingImpl<>( queryParameter, sessionFactory, null, queryParametersValidationEnabled ); final QueryParameterBinding<T> binding = new QueryParameterBindingImpl<>( queryParameter, sessionFactory, null, queryParametersValidationEnabled );
parameterBindingMap.put( queryParameter, binding ); parameterBindingMap.put( queryParameter, binding );
return binding; return binding;
@ -122,8 +120,7 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
@Override @Override
public <P> QueryParameterBinding<P> getBinding(QueryParameterImplementor<P> parameter) { public <P> QueryParameterBinding<P> getBinding(QueryParameterImplementor<P> parameter) {
if ( parameterBindingMap == null ) { if ( parameterBindingMap == null ) {
//noinspection unchecked return makeBinding( parameter );
return (QueryParameterBinding<P>) makeBinding( parameter );
} }
QueryParameterBinding<?> binding = parameterBindingMap.get( parameter ); QueryParameterBinding<?> binding = parameterBindingMap.get( parameter );

View File

@ -315,7 +315,7 @@ public class DomainResultCreationStateImpl
final Consumer<Fetchable> fetchableConsumer = fetchable -> { final Consumer<Fetchable> fetchableConsumer = fetchable -> {
final String fetchableName = fetchable.getFetchableName(); final String fetchableName = fetchable.getFetchableName();
final NavigablePath fetchPath = fetchParent.getNavigablePath().append( fetchableName ); final NavigablePath fetchPath = fetchParent.resolveNavigablePath( fetchable );
final NavigablePath relativePath = relativePathStack.isEmpty() final NavigablePath relativePath = relativePathStack.isEmpty()
? new NavigablePath( fetchableName ) ? new NavigablePath( fetchableName )
: relativePathStack.getCurrent().append( fetchableName ); : relativePathStack.getCurrent().append( fetchableName );

View File

@ -9,7 +9,6 @@ package org.hibernate.query.results;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
@ -113,18 +112,12 @@ public class TableGroupImpl implements TableGroup {
} }
@Override @Override
public TableReference resolveTableReference( public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
String tableExpression, Supplier<TableReference> creator) {
return primaryTableReference; return primaryTableReference;
} }
@Override @Override
public TableReference resolveTableReference(String tableExpression) { public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
return primaryTableReference;
}
@Override
public TableReference getTableReference(String tableExpression) {
return primaryTableReference; return primaryTableReference;
} }

View File

@ -68,7 +68,7 @@ public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder, Mode
final String mappedColumn = referencedModelPart.getSelectionExpression(); final String mappedColumn = referencedModelPart.getSelectionExpression();
final TableGroup tableGroup = creationState.getFromClauseAccess().getTableGroup( parent.getNavigablePath() ); final TableGroup tableGroup = creationState.getFromClauseAccess().getTableGroup( parent.getNavigablePath() );
final TableReference tableReference = tableGroup.getTableReference( mappedTable ); final TableReference tableReference = tableGroup.getTableReference( navigablePath, mappedTable );
final String selectedAlias; final String selectedAlias;
final int jdbcPosition; final int jdbcPosition;

View File

@ -62,7 +62,7 @@ public class CompleteResultBuilderBasicModelPart
final DomainResultCreationStateImpl creationStateImpl = impl( domainResultCreationState ); final DomainResultCreationStateImpl creationStateImpl = impl( domainResultCreationState );
final TableGroup tableGroup = creationStateImpl.getFromClauseAccess().getTableGroup( navigablePath.getParent() ); final TableGroup tableGroup = creationStateImpl.getFromClauseAccess().getTableGroup( navigablePath.getParent() );
final TableReference tableReference = tableGroup.getTableReference( modelPart.getContainingTableExpression() ); final TableReference tableReference = tableGroup.getTableReference( navigablePath, modelPart.getContainingTableExpression() );
final String mappedColumn = modelPart.getSelectionExpression(); final String mappedColumn = modelPart.getSelectionExpression();
final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias ); final int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );

View File

@ -59,7 +59,7 @@ public class ImplicitFetchBuilderBasic implements ImplicitFetchBuilder {
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition ); final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
final Expression expression = creationStateImpl.resolveSqlExpression( final Expression expression = creationStateImpl.resolveSqlExpression(
createColumnReferenceKey( parentTableGroup.getTableReference( table ), column ), createColumnReferenceKey( parentTableGroup.getTableReference( fetchPath, table ), column ),
processingState -> new SqlSelectionImpl( valuesArrayPosition, fetchable ) processingState -> new SqlSelectionImpl( valuesArrayPosition, fetchable )
); );

View File

@ -17,13 +17,10 @@ import org.hibernate.query.NavigablePath;
import org.hibernate.query.results.Builders; import org.hibernate.query.results.Builders;
import org.hibernate.query.results.DomainResultCreationStateImpl; import org.hibernate.query.results.DomainResultCreationStateImpl;
import org.hibernate.query.results.FetchBuilder; import org.hibernate.query.results.FetchBuilder;
import org.hibernate.query.results.SqlSelectionImpl;
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy; import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
import org.hibernate.sql.ast.SqlAstJoinType; import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin; import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableReference;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetch; import org.hibernate.sql.results.graph.Fetch;
import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParent;
@ -31,7 +28,6 @@ import org.hibernate.sql.results.graph.embeddable.EmbeddableValuedFetchable;
import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata; import org.hibernate.sql.results.jdbc.spi.JdbcValuesMetadata;
import static org.hibernate.query.results.ResultsHelper.impl; import static org.hibernate.query.results.ResultsHelper.impl;
import static org.hibernate.query.results.ResultsHelper.jdbcPositionToValuesArrayPosition;
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey; import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
/** /**
@ -92,6 +88,7 @@ public class ImplicitFetchBuilderEmbeddable implements ImplicitFetchBuilder {
parentTableGroup, parentTableGroup,
null, null,
SqlAstJoinType.INNER, SqlAstJoinType.INNER,
true,
LockMode.READ, LockMode.READ,
creationStateImpl creationStateImpl
); );

View File

@ -65,6 +65,7 @@ public class ImplicitModelPartResultBuilderEmbeddable
parentTableGroup, parentTableGroup,
null, null,
SqlAstJoinType.INNER, SqlAstJoinType.INNER,
true,
LockMode.READ, LockMode.READ,
creationStateImpl creationStateImpl
); );

View File

@ -720,7 +720,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
@SuppressWarnings( {"unchecked", "rawtypes"} ) @SuppressWarnings( {"unchecked", "rawtypes"} )
public Set<Parameter<?>> getParameters() { public Set<Parameter<?>> getParameters() {
getSession().checkOpen( false ); getSession().checkOpen( false );
return (Set) ( (ParameterMetadata) getParameterMetadata() ).getRegistrations(); return (Set) getParameterMetadata().getRegistrations();
} }
@Override @Override
@ -821,16 +821,16 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
return getQueryParameterBindings().getBinding( parameter ); return getQueryParameterBindings().getBinding( parameter );
} }
@SuppressWarnings( {"WeakerAccess", "unchecked"} ) @SuppressWarnings( {"WeakerAccess"} )
protected <P> QueryParameterBinding<P> locateBinding(String name) { protected <P> QueryParameterBinding<P> locateBinding(String name) {
getSession().checkOpen(); getSession().checkOpen();
return (QueryParameterBinding<P>) getQueryParameterBindings().getBinding( name ); return getQueryParameterBindings().getBinding( name );
} }
@SuppressWarnings( {"WeakerAccess", "unchecked"} ) @SuppressWarnings( {"WeakerAccess"} )
protected <P> QueryParameterBinding<P> locateBinding(int position) { protected <P> QueryParameterBinding<P> locateBinding(int position) {
getSession().checkOpen(); getSession().checkOpen();
return (QueryParameterBinding<P>) getQueryParameterBindings().getBinding( position ); return getQueryParameterBindings().getBinding( position );
} }
@Override @Override

View File

@ -45,7 +45,7 @@ public interface SqmPathSource<J> extends SqmExpressable<J>, Bindable<J> {
/** /**
* Create an SQM path for this source relative to the given left-hand side * Create an SQM path for this source relative to the given left-hand side
*/ */
SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState); SqmPath<J> createSqmPath(SqmPath<?> lhs);
default <X extends DomainType> X sqmAs(Class<X> targetType) { default <X extends DomainType> X sqmAs(Class<X> targetType) {
if ( targetType.isInstance( this ) ) { if ( targetType.isInstance( this ) ) {

View File

@ -231,7 +231,9 @@ public class QuerySqmImpl<R>
final Object value = jpaCriteriaParameter.getValue(); final Object value = jpaCriteriaParameter.getValue();
// We don't set a null value, unless the type is also null which is the case when using HibernateCriteriaBuilder.value // We don't set a null value, unless the type is also null which is the case when using HibernateCriteriaBuilder.value
if ( value != null || jpaCriteriaParameter.getNodeType() == null ) { if ( value != null || jpaCriteriaParameter.getNodeType() == null ) {
setParameter( jpaCriteriaParameter, value ); // Use the anticipated type for binding the value if possible
getQueryParameterBindings().getBinding( jpaCriteriaParameter )
.setBindValue( value, jpaCriteriaParameter.getAnticipatedType() );
} }
} }
} }

View File

@ -87,7 +87,10 @@ public class MatchingIdSelectionHelper {
targetEntityDescriptor.getIdentifierMapping().forEachSelectable( targetEntityDescriptor.getIdentifierMapping().forEachSelectable(
(position, selection) -> { (position, selection) -> {
final TableReference tableReference = mutatingTableGroup.resolveTableReference( selection.getContainingTableExpression() ); final TableReference tableReference = mutatingTableGroup.resolveTableReference(
mutatingTableGroup.getNavigablePath(),
selection.getContainingTableExpression()
);
final Expression expression = sqmConverter.getSqlExpressionResolver().resolveSqlExpression( final Expression expression = sqmConverter.getSqlExpressionResolver().resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( tableReference, selection.getSelectionExpression() ), SqlExpressionResolver.createColumnReferenceKey( tableReference, selection.getSelectionExpression() ),
sqlAstProcessingState -> new ColumnReference( sqlAstProcessingState -> new ColumnReference(
@ -153,7 +156,10 @@ public class MatchingIdSelectionHelper {
targetEntityDescriptor.getIdentifierMapping().forEachSelectable( targetEntityDescriptor.getIdentifierMapping().forEachSelectable(
(position, selection) -> { (position, selection) -> {
final TableReference tableReference = mutatingTableGroup.resolveTableReference( selection.getContainingTableExpression() ); final TableReference tableReference = mutatingTableGroup.resolveTableReference(
mutatingTableGroup.getNavigablePath(),
selection.getContainingTableExpression()
);
final Expression expression = sqmConverter.getSqlExpressionResolver().resolveSqlExpression( final Expression expression = sqmConverter.getSqlExpressionResolver().resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( tableReference, selection.getSelectionExpression() ), SqlExpressionResolver.createColumnReferenceKey( tableReference, selection.getSelectionExpression() ),
sqlAstProcessingState -> new ColumnReference( sqlAstProcessingState -> new ColumnReference(

View File

@ -101,7 +101,10 @@ public class CteDeleteHandler extends AbstractCteMutationHandler implements Dele
idSelectCte.getCteTable().getCteColumns(), idSelectCte.getCteTable().getCteColumns(),
factory factory
); );
final TableReference dmlTableReference = updatingTableGroup.resolveTableReference( tableExpression ); final TableReference dmlTableReference = updatingTableGroup.resolveTableReference(
updatingTableGroup.getNavigablePath(),
tableExpression
);
final List<ColumnReference> columnReferences = new ArrayList<>( idSelectCte.getCteTable().getCteColumns().size() ); final List<ColumnReference> columnReferences = new ArrayList<>( idSelectCte.getCteTable().getCteColumns().size() );
tableColumnsVisitationSupplier.get().accept( tableColumnsVisitationSupplier.get().accept(
(index, selectable) -> columnReferences.add( (index, selectable) -> columnReferences.add(

View File

@ -69,7 +69,10 @@ public class CteUpdateHandler extends AbstractCteMutationHandler implements Upda
final EntityPersister rootEntityDescriptor = factory.getDomainModel().getEntityDescriptor( rootEntityName ); final EntityPersister rootEntityDescriptor = factory.getDomainModel().getEntityDescriptor( rootEntityName );
final String hierarchyRootTableName = ( (Joinable) rootEntityDescriptor ).getTableName(); final String hierarchyRootTableName = ( (Joinable) rootEntityDescriptor ).getTableName();
final TableReference hierarchyRootTableReference = updatingTableGroup.resolveTableReference( hierarchyRootTableName ); final TableReference hierarchyRootTableReference = updatingTableGroup.resolveTableReference(
updatingTableGroup.getNavigablePath(),
hierarchyRootTableName
);
assert hierarchyRootTableReference != null; assert hierarchyRootTableReference != null;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -144,7 +147,10 @@ public class CteUpdateHandler extends AbstractCteMutationHandler implements Upda
if ( assignmentList == null ) { if ( assignmentList == null ) {
return; return;
} }
final TableReference dmlTableReference = updatingTableGroup.resolveTableReference( tableExpression ); final TableReference dmlTableReference = updatingTableGroup.resolveTableReference(
updatingTableGroup.getNavigablePath(),
tableExpression
);
final List<ColumnReference> columnReferences = new ArrayList<>( idSelectCte.getCteTable().getCteColumns().size() ); final List<ColumnReference> columnReferences = new ArrayList<>( idSelectCte.getCteTable().getCteColumns().size() );
tableColumnsVisitationSupplier.get().accept( tableColumnsVisitationSupplier.get().accept(
(index, selectable) -> columnReferences.add( (index, selectable) -> columnReferences.add(

View File

@ -87,7 +87,10 @@ public final class ExecuteWithIdTableHelper {
mutatingEntityDescriptor.getIdentifierMapping().forEachSelectable( mutatingEntityDescriptor.getIdentifierMapping().forEachSelectable(
(jdbcPosition, selection) -> { (jdbcPosition, selection) -> {
final TableReference tableReference = mutatingTableGroup.resolveTableReference( selection.getContainingTableExpression() ); final TableReference tableReference = mutatingTableGroup.resolveTableReference(
mutatingTableGroup.getNavigablePath(),
selection.getContainingTableExpression()
);
matchingIdSelection.getSelectClause().addSqlSelection( matchingIdSelection.getSelectClause().addSqlSelection(
new SqlSelectionImpl( new SqlSelectionImpl(
jdbcPosition, jdbcPosition,

View File

@ -124,7 +124,10 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle
final TableGroup deletingTableGroup = converter.getMutatingTableGroup(); final TableGroup deletingTableGroup = converter.getMutatingTableGroup();
final TableReference hierarchyRootTableReference = deletingTableGroup.resolveTableReference( hierarchyRootTableName ); final TableReference hierarchyRootTableReference = deletingTableGroup.resolveTableReference(
deletingTableGroup.getNavigablePath(),
hierarchyRootTableName
);
assert hierarchyRootTableReference != null; assert hierarchyRootTableReference != null;
final Map<SqmParameter, List<List<JdbcParameter>>> parameterResolutions; final Map<SqmParameter, List<List<JdbcParameter>>> parameterResolutions;
@ -213,7 +216,10 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle
final MutableInteger rows = new MutableInteger(); final MutableInteger rows = new MutableInteger();
final String rootTableName = ( (Joinable) rootEntityPersister ).getTableName(); final String rootTableName = ( (Joinable) rootEntityPersister ).getTableName();
final TableReference rootTableReference = tableGroup.resolveTableReference( rootTableName ); final TableReference rootTableReference = tableGroup.resolveTableReference(
tableGroup.getNavigablePath(),
rootTableName
);
final QuerySpec matchingIdSubQuerySpec = ExecuteWithoutIdTableHelper.createIdMatchingSubQuerySpec( final QuerySpec matchingIdSubQuerySpec = ExecuteWithoutIdTableHelper.createIdMatchingSubQuerySpec(
tableGroup.getNavigablePath(), tableGroup.getNavigablePath(),
@ -251,7 +257,7 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle
} }
else { else {
deleteFromNonRootTableWithoutIdTable( deleteFromNonRootTableWithoutIdTable(
tableGroup.resolveTableReference( tableExpression ), tableGroup.resolveTableReference( tableGroup.getNavigablePath(), tableExpression ),
tableKeyColumnVisitationSupplier, tableKeyColumnVisitationSupplier,
sqlExpressionResolver, sqlExpressionResolver,
tableGroup, tableGroup,

View File

@ -133,7 +133,10 @@ public class TableBasedUpdateHandler
final TableGroup updatingTableGroup = converterDelegate.getMutatingTableGroup(); final TableGroup updatingTableGroup = converterDelegate.getMutatingTableGroup();
final TableReference hierarchyRootTableReference = updatingTableGroup.resolveTableReference( hierarchyRootTableName ); final TableReference hierarchyRootTableReference = updatingTableGroup.resolveTableReference(
updatingTableGroup.getNavigablePath(),
hierarchyRootTableName
);
assert hierarchyRootTableReference != null; assert hierarchyRootTableReference != null;
final Map<SqmParameter, List<List<JdbcParameter>>> parameterResolutions; final Map<SqmParameter, List<List<JdbcParameter>>> parameterResolutions;

View File

@ -211,7 +211,10 @@ public class UpdateExecutionDelegate implements TableBasedUpdateHandler.Executio
return tableReferenceByQualifier; return tableReferenceByQualifier;
} }
final TableReference tableReferenceByName = updatingTableGroup.resolveTableReference( columnReference.getQualifier() ); final TableReference tableReferenceByName = updatingTableGroup.resolveTableReference(
updatingTableGroup.getNavigablePath(),
columnReference.getQualifier()
);
if ( tableReferenceByName != null ) { if ( tableReferenceByName != null ) {
return tableReferenceByName; return tableReferenceByName;
} }
@ -224,7 +227,7 @@ public class UpdateExecutionDelegate implements TableBasedUpdateHandler.Executio
Supplier<Consumer<SelectableConsumer>> tableKeyColumnVisitationSupplier, Supplier<Consumer<SelectableConsumer>> tableKeyColumnVisitationSupplier,
QuerySpec idTableSubQuery, QuerySpec idTableSubQuery,
ExecutionContext executionContext) { ExecutionContext executionContext) {
final TableReference updatingTableReference = updatingTableGroup.resolveTableReference( tableExpression ); final TableReference updatingTableReference = updatingTableGroup.resolveTableReference( updatingTableGroup.getNavigablePath(), tableExpression );
final List<Assignment> assignments = assignmentsByTable.get( updatingTableReference ); final List<Assignment> assignments = assignmentsByTable.get( updatingTableReference );
if ( assignments == null || assignments.isEmpty() ) { if ( assignments == null || assignments.isEmpty() ) {

View File

@ -646,11 +646,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
private void applyManipulationImplicitJoins(SqmPath<?> sqmPath, TableGroup correspondingTableGroup) { private void applyManipulationImplicitJoins(SqmPath<?> sqmPath, TableGroup correspondingTableGroup) {
consumeImplicitJoins( consumeReusablePaths( sqmPath, correspondingTableGroup, BaseSqmToSqlAstConverter::verifyManipulationImplicitJoin );
sqmPath,
correspondingTableGroup,
BaseSqmToSqlAstConverter::verifyManipulationImplicitJoin
);
} }
private static void verifyManipulationImplicitJoin(SqmPath<?> joinedPath) { private static void verifyManipulationImplicitJoin(SqmPath<?> joinedPath) {
@ -1772,7 +1768,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
log.tracef( "Resolved SqmRoot [%s] to correlated TableGroup [%s]", sqmRoot, tableGroup ); log.tracef( "Resolved SqmRoot [%s] to correlated TableGroup [%s]", sqmRoot, tableGroup );
consumeExplicitJoins( sqmRoot, tableGroup ); consumeExplicitJoins( sqmRoot, tableGroup );
consumeImplicitJoins( sqmRoot, tableGroup ); consumeReusablePaths( sqmRoot, tableGroup );
return; return;
} }
else { else {
@ -1786,6 +1782,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
creationContext creationContext
); );
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping(); final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
final NavigablePath navigablePath = sqmRoot.getNavigablePath().append( identifierMapping.getNavigableRole().getNavigableName() );
final int jdbcTypeCount = identifierMapping.getJdbcTypeCount(); final int jdbcTypeCount = identifierMapping.getJdbcTypeCount();
if ( jdbcTypeCount == 1 ) { if ( jdbcTypeCount == 1 ) {
identifierMapping.forEachSelectable( identifierMapping.forEachSelectable(
@ -1793,13 +1790,13 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
additionalRestrictions, additionalRestrictions,
new ComparisonPredicate( new ComparisonPredicate(
new ColumnReference( new ColumnReference(
parentTableGroup.getTableReference( selectable.getContainingTableExpression() ), parentTableGroup.getTableReference( navigablePath, selectable.getContainingTableExpression() ),
selectable, selectable,
sessionFactory sessionFactory
), ),
ComparisonOperator.EQUAL, ComparisonOperator.EQUAL,
new ColumnReference( new ColumnReference(
tableGroup.getTableReference( selectable.getContainingTableExpression() ), tableGroup.getTableReference( navigablePath, selectable.getContainingTableExpression() ),
selectable, selectable,
sessionFactory sessionFactory
) )
@ -1814,14 +1811,14 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
(index, selectable) -> { (index, selectable) -> {
lhs.add( lhs.add(
new ColumnReference( new ColumnReference(
parentTableGroup.getTableReference( selectable.getContainingTableExpression() ), parentTableGroup.getTableReference( navigablePath, selectable.getContainingTableExpression() ),
selectable, selectable,
sessionFactory sessionFactory
) )
); );
rhs.add( rhs.add(
new ColumnReference( new ColumnReference(
tableGroup.getTableReference( selectable.getContainingTableExpression() ), tableGroup.getTableReference( navigablePath, selectable.getContainingTableExpression() ),
selectable, selectable,
sessionFactory sessionFactory
) )
@ -1860,7 +1857,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
currentQuerySpec().getFromClause().addRoot( tableGroup ); currentQuerySpec().getFromClause().addRoot( tableGroup );
consumeExplicitJoins( sqmRoot, tableGroup ); consumeExplicitJoins( sqmRoot, tableGroup );
consumeImplicitJoins( sqmRoot, tableGroup ); consumeReusablePaths( sqmRoot, tableGroup );
} }
private EntityPersister resolveEntityPersister(EntityDomainType<?> entityDomainType) { private EntityPersister resolveEntityPersister(EntityDomainType<?> entityDomainType) {
@ -1929,6 +1926,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
lhsTableGroup, lhsTableGroup,
sqmJoin.getExplicitAlias(), sqmJoin.getExplicitAlias(),
sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(), sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(),
sqmJoin.isFetched(),
determineLockMode( sqmJoin.getExplicitAlias() ), determineLockMode( sqmJoin.getExplicitAlias() ),
this this
); );
@ -1943,6 +1941,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
lhsTableGroup, lhsTableGroup,
sqmJoin.getExplicitAlias(), sqmJoin.getExplicitAlias(),
sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(), sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(),
sqmJoin.isFetched(),
determineLockMode( sqmJoin.getExplicitAlias() ), determineLockMode( sqmJoin.getExplicitAlias() ),
this this
); );
@ -1969,7 +1968,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
consumeExplicitJoins( sqmJoin, joinedTableGroup ); consumeExplicitJoins( sqmJoin, joinedTableGroup );
consumeImplicitJoins( sqmJoin, joinedTableGroup ); consumeReusablePaths( sqmJoin, joinedTableGroup );
} }
private NavigablePath getJoinNavigablePath( private NavigablePath getJoinNavigablePath(
@ -2015,7 +2014,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
getFromClauseIndex().register( sqmJoin, tableGroup ); getFromClauseIndex().register( sqmJoin, tableGroup );
consumeExplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() ); consumeExplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() );
consumeImplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() ); consumeReusablePaths( sqmJoin, tableGroupJoin.getJoinedGroup() );
} }
private void consumeEntityJoin(SqmEntityJoin sqmJoin, TableGroup lhsTableGroup) { private void consumeEntityJoin(SqmEntityJoin sqmJoin, TableGroup lhsTableGroup) {
@ -2043,7 +2042,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
lhsTableGroup.addTableGroupJoin( tableGroupJoin ); lhsTableGroup.addTableGroupJoin( tableGroupJoin );
consumeExplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() ); consumeExplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() );
consumeImplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() ); consumeReusablePaths( sqmJoin, tableGroupJoin.getJoinedGroup() );
// add any additional join restrictions // add any additional join restrictions
if ( sqmJoin.getJoinPredicate() != null ) { if ( sqmJoin.getJoinPredicate() != null ) {
@ -2054,58 +2053,58 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
} }
private void consumeImplicitJoins(SqmPath<?> sqmPath, TableGroup tableGroup) { private void consumeReusablePaths(SqmPath<?> sqmPath, TableGroup tableGroup) {
consumeImplicitJoins( consumeReusablePaths( sqmPath, tableGroup, (sqmSubPath) -> {} );
sqmPath,
tableGroup,
(sqmSubPath) -> {}
);
} }
private void consumeImplicitJoins( private void consumeReusablePaths(
SqmPath<?> sqmPath, SqmPath<?> sqmPath,
TableGroup tableGroup, TableGroup parentTableGroup,
Consumer<SqmPath<?>> implicitJoinChecker) { Consumer<SqmPath<?>> implicitJoinChecker) {
if ( log.isTraceEnabled() ) { if ( log.isTraceEnabled() ) {
log.tracef( "Visiting implicit joins for `%s`", sqmPath.getNavigablePath() ); log.tracef( "Visiting implicit joins for `%s`", sqmPath.getNavigablePath() );
} }
sqmPath.visitImplicitJoinPaths( sqmPath.visitReusablePaths(
joinedPath -> { joinedPath -> {
if ( log.isTraceEnabled() ) { if ( log.isTraceEnabled() ) {
log.tracef( "Starting implicit join handling for `%s`", joinedPath.getNavigablePath() ); log.tracef( "Starting implicit join handling for `%s`", joinedPath.getNavigablePath() );
} }
// No need to create a table group for this path if no sub-paths exist
if ( joinedPath.getReusablePaths().isEmpty() ) {
return;
}
implicitJoinChecker.accept( joinedPath ); final SqmPath<?> lhsPath = joinedPath.getLhs();
final FromClauseIndex fromClauseIndex = getFromClauseIndex(); final FromClauseIndex fromClauseIndex = getFromClauseIndex();
assert fromClauseIndex.findTableGroup( joinedPath.getLhs().getNavigablePath() ) == tableGroup; final ModelPart subPart = parentTableGroup.getModelPart().findSubPart(
final ModelPart subPart = tableGroup.getModelPart().findSubPart(
joinedPath.getReferencedPathSource().getPathName(), joinedPath.getReferencedPathSource().getPathName(),
sqmPath instanceof SqmTreatedPath lhsPath instanceof SqmTreatedPath
? resolveEntityPersister( ( (SqmTreatedPath) sqmPath ).getTreatTarget() ) ? resolveEntityPersister( ( (SqmTreatedPath<?, ?>) lhsPath ).getTreatTarget() )
: null : null
); );
final TableGroup tableGroup;
if ( subPart instanceof TableGroupJoinProducer ) { if ( subPart instanceof TableGroupJoinProducer ) {
implicitJoinChecker.accept( joinedPath );
final TableGroupJoinProducer joinProducer = (TableGroupJoinProducer) subPart; final TableGroupJoinProducer joinProducer = (TableGroupJoinProducer) subPart;
final TableGroupJoin tableGroupJoin = joinProducer.createTableGroupJoin( final TableGroupJoin tableGroupJoin = joinProducer.createTableGroupJoin(
joinedPath.getNavigablePath(), joinedPath.getNavigablePath(),
tableGroup, parentTableGroup,
null, null,
tableGroup.isInnerJoinPossible() ? SqlAstJoinType.INNER : SqlAstJoinType.LEFT, parentTableGroup.isInnerJoinPossible() ? SqlAstJoinType.INNER : SqlAstJoinType.LEFT,
false,
null, null,
this this
); );
fromClauseIndex.register( joinedPath, tableGroupJoin.getJoinedGroup() ); fromClauseIndex.register( joinedPath, tableGroupJoin.getJoinedGroup() );
tableGroup = tableGroupJoin.getJoinedGroup();
consumeImplicitJoins( joinedPath, tableGroupJoin.getJoinedGroup(), implicitJoinChecker );
} }
else { else {
fromClauseIndex.register( joinedPath, tableGroup ); tableGroup = null;
} }
consumeReusablePaths( joinedPath, tableGroup, implicitJoinChecker );
} }
); );
} }
@ -2555,7 +2554,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
if ( sqmParameter.getAnticipatedType() == null ) { if ( sqmParameter.getAnticipatedType() == null ) {
// this should indicate the condition that the user query did not define an // this should indicate the condition that the user query did not define an
// explicit type in regard to this parameter. Here we should prefer the // explicit type in regard to this parameter. Here we should prefer the
// inferable type and fallback to the binding type // inferrable type and fallback to the binding type
final Supplier<MappingModelExpressable> currentExpressableSupplier = inferrableTypeAccessStack.getCurrent(); final Supplier<MappingModelExpressable> currentExpressableSupplier = inferrableTypeAccessStack.getCurrent();
if ( currentExpressableSupplier != null ) { if ( currentExpressableSupplier != null ) {
final MappingModelExpressable inferredMapping = currentExpressableSupplier.get(); final MappingModelExpressable inferredMapping = currentExpressableSupplier.get();
@ -2697,6 +2696,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
parentTableGroup, parentTableGroup,
null, null,
SqlAstJoinType.INNER, SqlAstJoinType.INNER,
false,
LockMode.READ, LockMode.READ,
sqlAliasBaseManager, sqlAliasBaseManager,
getSqlExpressionResolver(), getSqlExpressionResolver(),
@ -3907,12 +3907,12 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
? mappingModelExpressable.getIndexDescriptor() ? mappingModelExpressable.getIndexDescriptor()
: mappingModelExpressable.getElementDescriptor(); : mappingModelExpressable.getElementDescriptor();
final List<SqlAstNode> arguments = new ArrayList<>( 1 ); final List<SqlAstNode> arguments = new ArrayList<>( 1 );
final NavigablePath navigablePath = pluralPartPath.getNavigablePath();
collectionPart.forEachSelectable( collectionPart.forEachSelectable(
(selectionIndex, selectionMapping) -> { (selectionIndex, selectionMapping) -> {
arguments.add( arguments.add(
new ColumnReference( new ColumnReference(
tableGroup.getTableReference( selectionMapping.getContainingTableExpression() ), tableGroup.getTableReference( navigablePath, selectionMapping.getContainingTableExpression() ),
selectionMapping, selectionMapping,
creationContext.getSessionFactory() creationContext.getSessionFactory()
) )
@ -4150,6 +4150,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
tableGroup, tableGroup,
sqmPluralPath.getExplicitAlias(), sqmPluralPath.getExplicitAlias(),
SqlAstJoinType.INNER, SqlAstJoinType.INNER,
false,
LockMode.NONE, LockMode.NONE,
sqlAliasBaseManager, sqlAliasBaseManager,
subQueryState, subQueryState,
@ -4451,7 +4452,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
final List<String> bagRoles = new ArrayList<>(); final List<String> bagRoles = new ArrayList<>();
final BiConsumer<Fetchable, Boolean> fetchableBiConsumer = (fetchable, isKeyFetchable) -> { final BiConsumer<Fetchable, Boolean> fetchableBiConsumer = (fetchable, isKeyFetchable) -> {
final NavigablePath fetchablePath = fetchParent.getNavigablePath().append( fetchable.getFetchableName() ); final NavigablePath fetchablePath = fetchParent.resolveNavigablePath( fetchable );
final Fetch biDirectionalFetch = fetchable.resolveCircularFetch( final Fetch biDirectionalFetch = fetchable.resolveCircularFetch(
fetchablePath, fetchablePath,
@ -4594,6 +4595,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
lhs, lhs,
alias, alias,
SqlAstJoinType.LEFT, SqlAstJoinType.LEFT,
true,
LockMode.NONE, LockMode.NONE,
this this
); );

View File

@ -46,7 +46,10 @@ public class BasicValuedPathInterpretation<T> extends AbstractSqmPathInterpretat
throw new SemanticException( "`" + sqmPath.getNavigablePath().getFullPath() + "` did not reference a known model part" ); throw new SemanticException( "`" + sqmPath.getNavigablePath().getFullPath() + "` did not reference a known model part" );
} }
final TableReference tableReference = tableGroup.resolveTableReference( mapping.getContainingTableExpression() ); final TableReference tableReference = tableGroup.resolveTableReference(
sqmPath.getNavigablePath(),
mapping.getContainingTableExpression()
);
final Expression expression = sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression( final Expression expression = sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( SqlExpressionResolver.createColumnReferenceKey(

View File

@ -43,7 +43,7 @@ public class DiscriminatedAssociationPathInterpretation<T> extends AbstractSqmPa
mapping.forEachSelectable( mapping.forEachSelectable(
(selectionIndex, selectableMapping) -> { (selectionIndex, selectableMapping) -> {
final TableReference tableReference = tableGroup.resolveTableReference( selectableMapping.getContainingTableExpression() ); final TableReference tableReference = tableGroup.resolveTableReference( sqmPath.getNavigablePath(), selectableMapping.getContainingTableExpression() );
final Expression expression = converter.getSqlExpressionResolver().resolveSqlExpression( final Expression expression = converter.getSqlExpressionResolver().resolveSqlExpression(
SqlExpressionResolver.createColumnReferenceKey( tableReference, selectableMapping.getSelectionExpression() ), SqlExpressionResolver.createColumnReferenceKey( tableReference, selectableMapping.getSelectionExpression() ),
processingState -> new ColumnReference( processingState -> new ColumnReference(

View File

@ -61,7 +61,10 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
if ( mapping instanceof EntityAssociationMapping ) { if ( mapping instanceof EntityAssociationMapping ) {
final EntityAssociationMapping associationMapping = (EntityAssociationMapping) mapping; final EntityAssociationMapping associationMapping = (EntityAssociationMapping) mapping;
final ForeignKeyDescriptor keyDescriptor = associationMapping.getForeignKeyDescriptor(); final ForeignKeyDescriptor keyDescriptor = associationMapping.getForeignKeyDescriptor();
final TableReference tableReference = tableGroup.resolveTableReference( keyDescriptor.getKeyTable() ); final TableReference tableReference = tableGroup.resolveTableReference(
sqmPath.getNavigablePath(),
keyDescriptor.getKeyTable()
);
if ( keyDescriptor instanceof SimpleForeignKeyDescriptor ) { if ( keyDescriptor instanceof SimpleForeignKeyDescriptor ) {
final SimpleForeignKeyDescriptor simpleKeyDescriptor = (SimpleForeignKeyDescriptor) keyDescriptor; final SimpleForeignKeyDescriptor simpleKeyDescriptor = (SimpleForeignKeyDescriptor) keyDescriptor;
@ -98,7 +101,10 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
if ( identifierMapping instanceof BasicEntityIdentifierMapping ) { if ( identifierMapping instanceof BasicEntityIdentifierMapping ) {
final BasicEntityIdentifierMapping simpleIdMapping = (BasicEntityIdentifierMapping) identifierMapping; final BasicEntityIdentifierMapping simpleIdMapping = (BasicEntityIdentifierMapping) identifierMapping;
final TableReference tableReference = tableGroup.resolveTableReference( simpleIdMapping.getContainingTableExpression() ); final TableReference tableReference = tableGroup.resolveTableReference(
sqmPath.getNavigablePath(),
simpleIdMapping.getContainingTableExpression()
);
assert tableReference != null : "Could not resolve table-group : " + simpleIdMapping.getContainingTableExpression(); assert tableReference != null : "Could not resolve table-group : " + simpleIdMapping.getContainingTableExpression();
sqlExpression = sqlExprResolver.resolveSqlExpression( sqlExpression = sqlExprResolver.resolveSqlExpression(
@ -189,6 +195,7 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
parentTableGroup, parentTableGroup,
null, null,
SqlAstJoinType.INNER, SqlAstJoinType.INNER,
false,
LockMode.READ, LockMode.READ,
sqlAstCreationState sqlAstCreationState
); );

View File

@ -121,7 +121,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
throw UnknownPathException.unknownSubPath( this, name ); throw UnknownPathException.unknownSubPath( this, name );
} }
return subSource.createSqmPath( this, creationState ); return subSource.createSqmPath( this );
} }
); );
} }

View File

@ -10,9 +10,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.function.BiFunction;
import java.util.function.Consumer; import java.util.function.Consumer;
import javax.persistence.metamodel.MapAttribute; import javax.persistence.metamodel.MapAttribute;
import javax.persistence.metamodel.PluralAttribute; import javax.persistence.metamodel.PluralAttribute;
@ -21,11 +19,8 @@ import javax.persistence.metamodel.SingularAttribute;
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping; import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
import org.hibernate.metamodel.model.domain.DomainType; import org.hibernate.metamodel.model.domain.DomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.metamodel.model.domain.MapPersistentAttribute; import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.IllegalPathUsageException; import org.hibernate.query.sqm.IllegalPathUsageException;
import org.hibernate.query.sqm.NodeBuilder; import org.hibernate.query.sqm.NodeBuilder;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
@ -39,23 +34,14 @@ import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
*/ */
public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implements SqmPath<T> { public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implements SqmPath<T> {
private final NavigablePath navigablePath; private final NavigablePath navigablePath;
private final SqmPath lhs; private final SqmPath<?> lhs;
/** /**
* Note that this field is only really used to support Criteria building. * For HQL and Criteria processing - used to track reusable paths relative to this path.
* For HQL processing the {@link org.hibernate.query.hql.spi.SqmPathRegistry} * E.g., given `p.mate.mate` the SqmRoot identified by `p` would
* serves the same purpose. * have a reusable path for the `p.mate` path.
*/ */
private Map<String, SqmPath> attributePathRegistry; private Map<String, SqmPath<?>> reusablePaths;
/**
* For HQL processing - used to track implicit-join paths relative to this
* path. E.g., given `p.mate.mate` the SqmRoot identified by `p` would
* have an implicit-join for the `p.mate` path. Note however that the SqmPath
* for `p.mate` would not have one for `p.mate.mate` *unless* `p.mate.mate` were
* de-referenced somewhere else in the query.
*/
private Map<String,SqmPath<?>> implicitJoinPaths;
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected AbstractSqmPath( protected AbstractSqmPath(
@ -79,7 +65,7 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
} }
@SuppressWarnings("WeakerAccess") @SuppressWarnings("WeakerAccess")
protected AbstractSqmPath(SqmPathSource<T> referencedPathSource, SqmPath lhs, NodeBuilder nodeBuilder) { protected AbstractSqmPath(SqmPathSource<T> referencedPathSource, SqmPath<?> lhs, NodeBuilder nodeBuilder) {
this( this(
lhs == null lhs == null
? new NavigablePath( referencedPathSource.getPathName() ) ? new NavigablePath( referencedPathSource.getPathName() )
@ -101,43 +87,43 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
} }
@Override @Override
public List<SqmPath<?>> getImplicitJoinPaths() { public List<SqmPath<?>> getReusablePaths() {
if ( implicitJoinPaths == null ) { if ( reusablePaths == null ) {
return Collections.emptyList(); return Collections.emptyList();
} }
return new ArrayList<>( implicitJoinPaths.values() ); return new ArrayList<>( reusablePaths.values() );
} }
@Override @Override
public void visitImplicitJoinPaths(Consumer<SqmPath<?>> consumer) { public void visitReusablePaths(Consumer<SqmPath<?>> consumer) {
if ( implicitJoinPaths != null ) { if ( reusablePaths != null ) {
implicitJoinPaths.values().forEach( consumer ); reusablePaths.values().forEach( consumer );
} }
} }
@Override @Override
public void registerImplicitJoinPath(SqmPath<?> path) { public void registerReusablePath(SqmPath<?> path) {
assert path.getLhs() == this; assert path.getLhs() == this;
if ( implicitJoinPaths == null ) { if ( reusablePaths == null ) {
implicitJoinPaths = new HashMap<>(); reusablePaths = new HashMap<>();
} }
final String relativeName = path.getNavigablePath().getLocalName(); final String relativeName = path.getNavigablePath().getLocalName();
final SqmPath<?> previous = implicitJoinPaths.put( relativeName, path ); final SqmPath<?> previous = reusablePaths.put( relativeName, path );
if ( previous != null && previous != path ) { if ( previous != null && previous != path ) {
throw new IllegalStateException( "Implicit-join path registration unexpectedly overrode previous registration - " + relativeName ); throw new IllegalStateException( "Implicit-join path registration unexpectedly overrode previous registration - " + relativeName );
} }
} }
@Override @Override
public SqmPath<?> getImplicitJoinPath(String name) { public SqmPath<?> getReusablePath(String name) {
if ( implicitJoinPaths == null ) { if ( reusablePaths == null ) {
return null; return null;
} }
return implicitJoinPaths.get( name ); return reusablePaths.get( name );
} }
@Override @Override
@ -185,7 +171,7 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
} }
@Override @Override
public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) { public SqmPath createSqmPath(SqmPath lhs) {
return new SqmBasicValuedSimplePath( discriminatorNavigablePath, this, AbstractSqmPath.this, nodeBuilder() ); return new SqmBasicValuedSimplePath( discriminatorNavigablePath, this, AbstractSqmPath.this, nodeBuilder() );
} }
@ -195,7 +181,7 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
} }
@Override @Override
public Class getBindableJavaType() { public Class<?> getBindableJavaType() {
return null; return null;
} }
@ -234,111 +220,49 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
throw new IllegalStateException( "Cannot resolve path `" + attributeName + "` relative to a basic-valued path: `" + getNavigablePath() + "`" ); throw new IllegalStateException( "Cannot resolve path `" + attributeName + "` relative to a basic-valued path: `" + getNavigablePath() + "`" );
} }
return resolvePath( final SqmPathSource<?> subNavigable = getReferencedPathSource().findSubPathSource( attributeName );
attributeName,
(pathSource, name) -> {
final SqmPathSource<?> subNavigable = getReferencedPathSource().findSubPathSource( attributeName );
if ( subNavigable == null ) { if ( subNavigable == null ) {
throw new IllegalArgumentException( "Could not resolve attribute named `" + attributeName + "` relative to `" + getNavigablePath() + "`" ); throw new IllegalArgumentException( "Could not resolve attribute named `" + attributeName + "` relative to `" + getNavigablePath() + "`" );
}
if ( subNavigable instanceof SingularPersistentAttribute ) {
return createSingularPath( (SingularPersistentAttribute<?,?>) subNavigable );
}
else {
assert subNavigable instanceof PluralPersistentAttribute;
return createPluralPath( (PluralPersistentAttribute<?,?,?>) subNavigable );
}
}
);
}
@SuppressWarnings("unchecked")
private SqmPath createSingularPath(SingularPersistentAttribute attribute) {
final NavigablePath subNavPath = getNavigablePath().append( attribute.getPathName() );
switch ( attribute.getAttributeClassification() ) {
case BASIC: {
return new SqmBasicValuedSimplePath( subNavPath, attribute, this, nodeBuilder() );
}
case EMBEDDED: {
return new SqmEmbeddedValuedSimplePath( subNavPath, attribute, this, nodeBuilder() );
}
case ANY: {
return new SqmAnyValuedSimplePath( subNavPath, attribute, this, nodeBuilder() );
}
case ONE_TO_ONE:
case MANY_TO_ONE: {
return new SqmEntityValuedSimplePath( subNavPath, attribute, this, nodeBuilder() );
}
default: {
throw new UnsupportedOperationException(
String.format(
Locale.ROOT,
"Cannot create SqmPath from singular attribute [%s#%s] - unknown classification : %s",
attribute.getDeclaringType().getTypeName(),
attribute.getName(),
attribute.getAttributeClassification()
)
);
}
} }
return resolvePath( attributeName, subNavigable );
} }
private SqmPath createPluralPath(PluralPersistentAttribute pluralAttribute) { private SqmPath<?> resolvePath(PersistentAttribute<?, ?> attribute) {
return new SqmPluralValuedSimplePath( return resolvePath( attribute.getName(), (SqmPathSource<?>) attribute );
getNavigablePath().append( pluralAttribute.getPathName() ),
pluralAttribute,
this,
nodeBuilder()
);
} }
private SqmPath<?> resolvePath(String attributeName, SqmPathSource<?> pathSource) {
private SqmPath resolvePath(String attributeName, BiFunction<SqmPath, String, SqmPath> creator) { if ( reusablePaths == null ) {
final SqmPath pathSource = getLhs(); reusablePaths = new HashMap<>();
final SqmPath<?> path = pathSource.createSqmPath( this );
if ( attributePathRegistry == null ) { reusablePaths.put( attributeName, path );
attributePathRegistry = new HashMap<>();
final SqmPath path = creator.apply( pathSource, attributeName );
attributePathRegistry.put( attributeName, path );
return path; return path;
} }
else { else {
return attributePathRegistry.computeIfAbsent( return reusablePaths.computeIfAbsent(
attributeName, attributeName,
name -> creator.apply( pathSource, attributeName ) name -> pathSource.createSqmPath( this )
); );
} }
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public SqmPath get(SingularAttribute jpaAttribute) { public <Y> SqmPath<Y> get(SingularAttribute<? super T, Y> jpaAttribute) {
final SingularPersistentAttribute attribute = (SingularPersistentAttribute) jpaAttribute; return (SqmPath<Y>) resolvePath( (PersistentAttribute<?, ?>) jpaAttribute );
return resolvePath(
attribute.getName(),
(pathSource, name) -> createSingularPath( attribute )
);
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public SqmPath get(PluralAttribute attribute) { public <E, C extends java.util.Collection<E>> SqmPath<C> get(PluralAttribute<T, C, E> attribute) {
return resolvePath( return (SqmPath<C>) resolvePath( (PersistentAttribute<?, ?>) attribute );
attribute.getName(),
(pathSource, name) -> createPluralPath( (PluralPersistentAttribute) attribute )
);
} }
@Override @Override
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public SqmPath get(MapAttribute map) { public <K, V, M extends java.util.Map<K, V>> SqmPath<M> get(MapAttribute<T, K, V> map) {
return resolvePath( return (SqmPath<M>) resolvePath( (PersistentAttribute<?, ?>) map );
map.getName(),
(pathSource, name) -> createPluralPath( (MapPersistentAttribute) map )
);
} }
@Override @Override

View File

@ -43,7 +43,7 @@ public class NonAggregatedCompositeSimplePath<T> extends SqmEntityValuedSimplePa
throw UnknownPathException.unknownSubPath( this, name ); throw UnknownPathException.unknownSubPath( this, name );
} }
return subPathSource.createSqmPath( this, creationState ); return subPathSource.createSqmPath( this );
} }
@Override @Override

View File

@ -25,7 +25,7 @@ public class SqmAnyValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
public SqmAnyValuedSimplePath( public SqmAnyValuedSimplePath(
NavigablePath navigablePath, NavigablePath navigablePath,
SqmPathSource<T> referencedPathSource, SqmPathSource<T> referencedPathSource,
SqmPath lhs, SqmPath<?> lhs,
NodeBuilder nodeBuilder) { NodeBuilder nodeBuilder) {
super( navigablePath, referencedPathSource, lhs, nodeBuilder ); super( navigablePath, referencedPathSource, lhs, nodeBuilder );
@ -36,7 +36,7 @@ public class SqmAnyValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
public SqmAnyValuedSimplePath( public SqmAnyValuedSimplePath(
NavigablePath navigablePath, NavigablePath navigablePath,
SqmPathSource<T> referencedPathSource, SqmPathSource<T> referencedPathSource,
SqmPath lhs, SqmPath<?> lhs,
String explicitAlias, String explicitAlias,
NodeBuilder nodeBuilder) { NodeBuilder nodeBuilder) {
super( navigablePath, referencedPathSource, lhs, explicitAlias, nodeBuilder ); super( navigablePath, referencedPathSource, lhs, explicitAlias, nodeBuilder );
@ -64,7 +64,7 @@ public class SqmAnyValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
throw UnknownPathException.unknownSubPath( this, name ); throw UnknownPathException.unknownSubPath( this, name );
} }
return subPathSource.createSqmPath( this, creationState ); return subPathSource.createSqmPath( this );
} }

View File

@ -6,6 +6,7 @@
*/ */
package org.hibernate.query.sqm.tree.domain; package org.hibernate.query.sqm.tree.domain;
import org.hibernate.metamodel.model.domain.AllowableParameterType;
import org.hibernate.metamodel.model.domain.EmbeddableDomainType; import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.metamodel.model.domain.EntityDomainType;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
@ -16,11 +17,12 @@ import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.query.sqm.UnknownPathException; import org.hibernate.query.sqm.UnknownPathException;
import org.hibernate.query.sqm.SemanticQueryWalker; import org.hibernate.query.sqm.SemanticQueryWalker;
import org.hibernate.query.hql.spi.SqmCreationState; import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class SqmEmbeddedValuedSimplePath<T> extends AbstractSqmSimplePath<T> { public class SqmEmbeddedValuedSimplePath<T> extends AbstractSqmSimplePath<T> implements AllowableParameterType<T> {
public SqmEmbeddedValuedSimplePath( public SqmEmbeddedValuedSimplePath(
NavigablePath navigablePath, NavigablePath navigablePath,
SqmPathSource<T> referencedPathSource, SqmPathSource<T> referencedPathSource,
@ -53,7 +55,7 @@ public class SqmEmbeddedValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
throw UnknownPathException.unknownSubPath( this, name ); throw UnknownPathException.unknownSubPath( this, name );
} }
return subPathSource.createSqmPath( this, creationState ); return subPathSource.createSqmPath( this );
} }
@Override @Override
@ -72,7 +74,22 @@ public class SqmEmbeddedValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
throw new PathException( "Embeddable paths cannot be TREAT-ed" ); throw new PathException( "Embeddable paths cannot be TREAT-ed" );
} }
// @Override @Override
public JavaTypeDescriptor<T> getExpressableJavaTypeDescriptor() {
return getJavaTypeDescriptor();
}
@Override
public PersistenceType getPersistenceType() {
return PersistenceType.EMBEDDABLE;
}
@Override
public Class<T> getJavaType() {
return getJavaTypeDescriptor().getJavaTypeClass();
}
// @Override
// public DomainResult createDomainResult( // public DomainResult createDomainResult(
// String resultVariable, // String resultVariable,
// DomainResultCreationState creationState, // DomainResultCreationState creationState,

View File

@ -41,7 +41,7 @@ public class SqmEntityValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
.findPath( getLhs().getNavigablePath() ) != null; .findPath( getLhs().getNavigablePath() ) != null;
//noinspection unchecked //noinspection unchecked
return subPathSource.createSqmPath( this, creationState ); return subPathSource.createSqmPath( this );
} }
@Override @Override

View File

@ -61,7 +61,7 @@ public class SqmIndexedCollectionAccessPath<T> extends AbstractSqmPath<T> implem
SqmCreationState creationState) { SqmCreationState creationState) {
final SqmPathSource subPathSource = getReferencedPathSource().getElementPathSource().findSubPathSource( name ); final SqmPathSource subPathSource = getReferencedPathSource().getElementPathSource().findSubPathSource( name );
//noinspection unchecked //noinspection unchecked
return subPathSource.createSqmPath( this, creationState ); return subPathSource.createSqmPath( this );
} }
@Override @Override

View File

@ -36,7 +36,7 @@ public class SqmMaxElementPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
SqmCreationState creationState) { SqmCreationState creationState) {
if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) { if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) {
//noinspection unchecked //noinspection unchecked
return getPluralAttribute().getElementPathSource().createSqmPath( this, creationState ); return getPluralAttribute().getElementPathSource().createSqmPath( this );
} }
throw new SemanticException( "Collection element cannot be de-referenced : " + getPluralDomainPath().getNavigablePath() ); throw new SemanticException( "Collection element cannot be de-referenced : " + getPluralDomainPath().getNavigablePath() );

View File

@ -48,7 +48,7 @@ public class SqmMaxIndexPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
String name, String name,
boolean isTerminal, boolean isTerminal,
SqmCreationState creationState) { SqmCreationState creationState) {
return indexPathSource.createSqmPath( this, creationState ); return indexPathSource.createSqmPath( this );
} }
@Override @Override

View File

@ -36,7 +36,7 @@ public class SqmMinElementPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
SqmCreationState creationState) { SqmCreationState creationState) {
if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) { if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) {
//noinspection unchecked //noinspection unchecked
return getPluralAttribute().getElementPathSource().createSqmPath( this, creationState ); return getPluralAttribute().getElementPathSource().createSqmPath( this );
} }
throw new SemanticException( "Collection element cannot be de-referenced : " + getPluralDomainPath().getNavigablePath() ); throw new SemanticException( "Collection element cannot be de-referenced : " + getPluralDomainPath().getNavigablePath() );

View File

@ -48,7 +48,7 @@ public class SqmMinIndexPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
String name, String name,
boolean isTerminal, boolean isTerminal,
SqmCreationState creationState) { SqmCreationState creationState) {
return indexPathSource.createSqmPath( this, creationState ); return indexPathSource.createSqmPath( this );
} }
@Override @Override

View File

@ -63,21 +63,21 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
SqmPath<?> getLhs(); SqmPath<?> getLhs();
/** /**
* Returns an immutable List of implicit-join paths * Returns an immutable List of reusable paths
*/ */
List<SqmPath<?>> getImplicitJoinPaths(); List<SqmPath<?>> getReusablePaths();
/** /**
* Visit each implicit-join path relative to this path * Visit each reusable path relative to this path
*/ */
void visitImplicitJoinPaths(Consumer<SqmPath<?>> consumer); void visitReusablePaths(Consumer<SqmPath<?>> consumer);
/** /**
* Register an implicit-join path relative to this path * Register a reusable path relative to this path
*/ */
void registerImplicitJoinPath(SqmPath<?> path); void registerReusablePath(SqmPath<?> path);
SqmPath<?> getImplicitJoinPath(String name); SqmPath<?> getReusablePath(String name);
/** /**
* This node's type is its "referenced path source" * This node's type is its "referenced path source"

View File

@ -86,26 +86,24 @@ public class SqmPluralValuedSimplePath<E> extends AbstractSqmSimplePath<E> {
if ( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( name ) ) { if ( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( name ) ) {
return referencedPathSource.getElementPathSource().createSqmPath( return referencedPathSource.getElementPathSource().createSqmPath(
this, this
creationState
); );
} }
if ( CollectionPropertyNames.COLLECTION_INDEX.equals( name ) if ( CollectionPropertyNames.COLLECTION_INDEX.equals( name )
|| CollectionPropertyNames.COLLECTION_INDICES.equals( name ) ) { || CollectionPropertyNames.COLLECTION_INDICES.equals( name ) ) {
if ( referencedPathSource instanceof MapPersistentAttribute ) { if ( referencedPathSource instanceof MapPersistentAttribute ) {
return ( (MapPersistentAttribute) referencedPathSource ).getKeyPathSource().createSqmPath( this, creationState ); return ( (MapPersistentAttribute) referencedPathSource ).getKeyPathSource().createSqmPath( this );
} }
else if ( referencedPathSource instanceof ListPersistentAttribute ) { else if ( referencedPathSource instanceof ListPersistentAttribute ) {
return referencedPathSource.getIndexPathSource().createSqmPath( this, creationState ); return referencedPathSource.getIndexPathSource().createSqmPath( this );
} }
throw new UnsupportedOperationException( ); throw new UnsupportedOperationException( );
} }
return referencedPathSource.getElementPathSource().createSqmPath( return referencedPathSource.getElementPathSource().createSqmPath(
this, this
creationState
); );
} }
); );

View File

@ -33,7 +33,6 @@ import org.hibernate.metamodel.model.domain.PersistentAttribute;
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute; import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
import org.hibernate.metamodel.model.domain.SimpleDomainType; import org.hibernate.metamodel.model.domain.SimpleDomainType;
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute; import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
import org.hibernate.query.hql.spi.SqmCreationState;
import org.hibernate.query.sqm.SqmPathSource; import org.hibernate.query.sqm.SqmPathSource;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor; import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
@ -374,7 +373,7 @@ public class SqmPolymorphicRootDescriptor<T> implements EntityDomainType<T> {
} }
@Override @Override
public SqmPath<T> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) { public SqmPath<T> createSqmPath(SqmPath<?> lhs) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }

View File

@ -12,6 +12,7 @@ import org.hibernate.sql.ast.tree.SqlAstTreeLogger;
import org.hibernate.sql.ast.tree.Statement; import org.hibernate.sql.ast.tree.Statement;
import org.hibernate.sql.ast.tree.delete.DeleteStatement; import org.hibernate.sql.ast.tree.delete.DeleteStatement;
import org.hibernate.sql.ast.tree.from.FromClause; import org.hibernate.sql.ast.tree.from.FromClause;
import org.hibernate.sql.ast.tree.from.LazyTableGroup;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin; import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableReferenceJoin; import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
@ -106,6 +107,13 @@ public class SqlTreePrinter {
} }
private void logTableGroupDetails(TableGroup tableGroup) { private void logTableGroupDetails(TableGroup tableGroup) {
if (tableGroup instanceof LazyTableGroup ) {
TableGroup underlyingTableGroup = ( (LazyTableGroup) tableGroup ).getUnderlyingTableGroup();
if ( underlyingTableGroup != null ) {
logTableGroupDetails( underlyingTableGroup );
}
return;
}
logWithIndentation( logWithIndentation(
"primaryTableReference : %s as %s", "primaryTableReference : %s as %s",
tableGroup.getPrimaryTableReference().getTableExpression(), tableGroup.getPrimaryTableReference().getTableExpression(),

View File

@ -99,6 +99,7 @@ import org.hibernate.sql.ast.tree.expression.Summarization;
import org.hibernate.sql.ast.tree.expression.TrimSpecification; import org.hibernate.sql.ast.tree.expression.TrimSpecification;
import org.hibernate.sql.ast.tree.expression.UnaryOperation; import org.hibernate.sql.ast.tree.expression.UnaryOperation;
import org.hibernate.sql.ast.tree.from.FromClause; import org.hibernate.sql.ast.tree.from.FromClause;
import org.hibernate.sql.ast.tree.from.LazyTableGroup;
import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin; import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableReference; import org.hibernate.sql.ast.tree.from.TableReference;
@ -2683,7 +2684,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
if ( joinedGroup instanceof VirtualTableGroup ) { if ( joinedGroup instanceof VirtualTableGroup ) {
processTableGroupJoins( tableGroupJoin.getJoinedGroup() ); processTableGroupJoins( tableGroupJoin.getJoinedGroup() );
} }
else { else if ( !( joinedGroup instanceof LazyTableGroup ) || ( (LazyTableGroup) joinedGroup ).getUnderlyingTableGroup() != null ) {
appendSql( EMPTY_STRING ); appendSql( EMPTY_STRING );
SqlAstJoinType joinType = tableGroupJoin.getJoinType(); SqlAstJoinType joinType = tableGroupJoin.getJoinType();
if ( !joinedGroup.isRealTableGroup() && joinType == SqlAstJoinType.INNER && !joinedGroup.getTableReferenceJoins().isEmpty() ) { if ( !joinedGroup.isRealTableGroup() && joinType == SqlAstJoinType.INNER && !joinedGroup.getTableReferenceJoins().isEmpty() ) {

View File

@ -9,7 +9,6 @@ package org.hibernate.sql.ast.tree.cte;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
@ -62,7 +61,7 @@ public class CteTableGroup implements TableGroup {
} }
@Override @Override
public TableReference getTableReference(String tableExpression) { public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
if ( cteTableReference.getTableExpression().equals( tableExpression ) ) { if ( cteTableReference.getTableExpression().equals( tableExpression ) ) {
return cteTableReference; return cteTableReference;
} }
@ -70,14 +69,7 @@ public class CteTableGroup implements TableGroup {
} }
@Override @Override
public TableReference resolveTableReference(String tableExpression) { public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
return cteTableReference;
}
@Override
public TableReference resolveTableReference(
String tableExpression,
Supplier<TableReference> creator) {
return cteTableReference; return cteTableReference;
} }

View File

@ -7,9 +7,9 @@
package org.hibernate.sql.ast.tree.from; package org.hibernate.sql.ast.tree.from;
import java.util.List; import java.util.List;
import java.util.function.Supplier;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.NavigablePath;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
@ -25,20 +25,10 @@ public abstract class AbstractColumnReferenceQualifier implements ColumnReferenc
// TableReference handling // TableReference handling
@Override @Override
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) { public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
final TableReference existing = getTableReferenceInternal( tableExpression );
if ( existing != null ) {
return existing;
}
return creator.get();
}
@Override
public TableReference resolveTableReference(String tableExpression) {
assert tableExpression != null; assert tableExpression != null;
final TableReference tableReference = getTableReferenceInternal( tableExpression ); final TableReference tableReference = getTableReferenceInternal( navigablePath, tableExpression );
if ( tableReference == null ) { if ( tableReference == null ) {
throw new IllegalStateException( "Could not resolve binding for table `" + tableExpression + "`" ); throw new IllegalStateException( "Could not resolve binding for table `" + tableExpression + "`" );
} }
@ -47,18 +37,24 @@ public abstract class AbstractColumnReferenceQualifier implements ColumnReferenc
} }
@Override @Override
public TableReference getTableReference(String tableExpression) { public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
return getTableReferenceInternal( tableExpression ); return getTableReferenceInternal( navigablePath, tableExpression );
} }
protected TableReference getTableReferenceInternal(String tableExpression) { protected TableReference getTableReferenceInternal(
if ( getPrimaryTableReference().getTableReference( tableExpression ) != null) { NavigablePath navigablePath,
return getPrimaryTableReference(); String tableExpression) {
final TableReference primaryTableReference = getPrimaryTableReference().getTableReference( navigablePath , tableExpression );
if ( primaryTableReference != null) {
return primaryTableReference;
} }
for ( TableReferenceJoin tableJoin : getTableReferenceJoins() ) { for ( TableReferenceJoin tableJoin : getTableReferenceJoins() ) {
if ( tableJoin.getJoinedTableReference().getTableReference( tableExpression ) != null) { final TableReference tableReference = tableJoin.getJoinedTableReference().getTableReference(
return tableJoin.getJoinedTableReference(); navigablePath,
tableExpression );
if ( tableReference != null) {
return tableReference;
} }
} }

View File

@ -6,13 +6,15 @@
*/ */
package org.hibernate.sql.ast.tree.from; package org.hibernate.sql.ast.tree.from;
import java.util.function.Supplier; import org.hibernate.query.NavigablePath;
/** /**
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public interface ColumnReferenceQualifier { public interface ColumnReferenceQualifier {
TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator); TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression);
TableReference resolveTableReference(String tableExpression); TableReference getTableReference(NavigablePath navigablePath, String tableExpression);
TableReference getTableReference(String tableExpression); default TableReference getTableReference(String tableExpression) {
return getTableReference( null, tableExpression );
}
} }

View File

@ -10,7 +10,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart; import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
@ -110,26 +109,19 @@ public class CompositeTableGroup implements VirtualTableGroup {
} }
@Override @Override
public TableReference getTableReference(String tableExpression) { public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
return underlyingTableGroup.getTableReference( tableExpression ); return underlyingTableGroup.getTableReference( tableExpression );
} }
@Override @Override
public TableReference resolveTableReference( public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
String tableExpression, TableReference tableReference = underlyingTableGroup.getTableReference( navigablePath, tableExpression );
Supplier<TableReference> creator) {
return underlyingTableGroup.resolveTableReference( tableExpression, creator );
}
@Override
public TableReference resolveTableReference(String tableExpression) {
TableReference tableReference = underlyingTableGroup.getTableReference( tableExpression );
if ( tableReference != null ) { if ( tableReference != null ) {
return tableReference; return tableReference;
} }
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) { for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference(); final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference().getTableReference( navigablePath, tableExpression );
if ( primaryTableReference.getTableExpression().equals( tableExpression ) ) { if ( primaryTableReference != null ) {
return primaryTableReference; return primaryTableReference;
} }
} }

View File

@ -12,6 +12,7 @@ import java.util.function.Consumer;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.SqlAstJoinType; import org.hibernate.sql.ast.SqlAstJoinType;
import org.hibernate.sql.ast.spi.SqlAliasBase; import org.hibernate.sql.ast.spi.SqlAliasBase;
import org.hibernate.sql.ast.tree.predicate.Predicate; import org.hibernate.sql.ast.tree.predicate.Predicate;
@ -59,20 +60,23 @@ public class CorrelatedTableGroup extends AbstractTableGroup {
} }
@Override @Override
protected TableReference getTableReferenceInternal(String tableExpression) { protected TableReference getTableReferenceInternal(
final TableReference primaryTableReference = correlatedTableGroup.getPrimaryTableReference(); NavigablePath navigablePath,
if ( tableExpression.equals( primaryTableReference.getTableExpression() ) ) { String tableExpression) {
final TableReference primaryTableReference = correlatedTableGroup.getPrimaryTableReference().getTableReference( navigablePath, tableExpression );
if ( primaryTableReference != null ) {
return primaryTableReference; return primaryTableReference;
} }
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) { for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
final TableReference groupTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference(); final TableReference groupTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference().getTableReference( navigablePath, tableExpression );
if ( groupTableReference.getTableReference( tableExpression ) != null ) { if ( groupTableReference != null ) {
return groupTableReference; return groupTableReference;
} }
} }
for ( TableReferenceJoin tableReferenceJoin : correlatedTableGroup.getTableReferenceJoins() ) { for ( TableReferenceJoin tableReferenceJoin : correlatedTableGroup.getTableReferenceJoins() ) {
if ( tableExpression.equals( tableReferenceJoin.getJoinedTableReference().getTableExpression() ) ) { final TableReference tableReference = tableReferenceJoin.getJoinedTableReference().getTableReference( navigablePath, tableExpression );
return tableReferenceJoin.getJoinedTableReference(); if ( tableReference != null ) {
return tableReference;
} }
} }
return null; return null;

View File

@ -0,0 +1,171 @@
/*
* 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.sql.ast.tree.from;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;
import org.hibernate.LockMode;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.metamodel.mapping.ModelPart;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.spi.SqlAliasBase;
/**
* @author Christian Beikov
*/
public class LazyTableGroup extends AbstractColumnReferenceQualifier implements TableGroup {
private final NavigablePath navigablePath;
private final TableGroupProducer producer;
private final LockMode lockMode;
private final SqlAliasBase sqlAliasBase;
private final SessionFactoryImplementor sessionFactory;
private final Supplier<TableGroup> tableGroupSupplier;
private final TableGroup parentTableGroup;
private final Predicate<NavigablePath> navigablePathChecker;
private Consumer<TableGroup> tableGroupConsumer;
private TableGroup tableGroup;
public LazyTableGroup(
NavigablePath navigablePath,
Supplier<TableGroup> tableGroupSupplier,
Predicate<NavigablePath> navigablePathChecker,
TableGroupProducer tableGroupProducer,
LockMode lockMode,
SqlAliasBase sqlAliasBase,
SessionFactoryImplementor sessionFactory,
TableGroup parentTableGroup) {
this.navigablePath = navigablePath;
this.producer = tableGroupProducer;
this.lockMode = lockMode;
this.sqlAliasBase = sqlAliasBase;
this.tableGroupSupplier = tableGroupSupplier;
this.navigablePathChecker = navigablePathChecker;
this.parentTableGroup = parentTableGroup;
this.sessionFactory = sessionFactory;
}
public TableGroup getUnderlyingTableGroup() {
return tableGroup;
}
private TableGroup getTableGroup() {
if ( tableGroup != null ) {
return tableGroup;
}
tableGroup = tableGroupSupplier.get();
if ( tableGroupConsumer != null ) {
tableGroupConsumer.accept( tableGroup );
}
return tableGroup;
}
public void setTableGroupInitializerCallback(Consumer<TableGroup> tableGroupConsumer) {
this.tableGroupConsumer = tableGroupConsumer;
}
@Override
public void applyAffectedTableNames(Consumer<String> nameCollector) {
if ( tableGroup != null ) {
tableGroup.applyAffectedTableNames( nameCollector );
}
}
@Override
public TableReference getPrimaryTableReference() {
return getTableGroup().getPrimaryTableReference();
}
@Override
public List<TableReferenceJoin> getTableReferenceJoins() {
return tableGroup == null ? Collections.emptyList() : tableGroup.getTableReferenceJoins();
}
@Override
public List<TableGroupJoin> getTableGroupJoins() {
return tableGroup == null ? Collections.emptyList() : tableGroup.getTableGroupJoins();
}
@Override
public boolean hasTableGroupJoins() {
return tableGroup != null && tableGroup.hasTableGroupJoins();
}
@Override
public void addTableGroupJoin(TableGroupJoin join) {
getTableGroup().addTableGroupJoin( join );
}
@Override
public void visitTableGroupJoins(Consumer<TableGroupJoin> consumer) {
if ( tableGroup != null ) {
tableGroup.visitTableGroupJoins( consumer );
}
}
@Override
public NavigablePath getNavigablePath() {
return navigablePath;
}
@Override
public String getGroupAlias() {
return sqlAliasBase.getAliasStem();
}
@Override
public TableGroupProducer getModelPart() {
return producer;
}
@Override
public ModelPart getExpressionType() {
return getModelPart();
}
@Override
public LockMode getLockMode() {
return lockMode;
}
@Override
protected SessionFactoryImplementor getSessionFactory() {
return sessionFactory;
}
@Override
public boolean isInnerJoinPossible() {
return false;
}
@Override
public boolean isRealTableGroup() {
return false;
}
@Override
public TableReference getTableReferenceInternal(
NavigablePath navigablePath,
String tableExpression) {
if ( navigablePath == null || navigablePathChecker.test( navigablePath ) ) {
final TableReference reference = parentTableGroup.getTableReference(
navigablePath,
tableExpression
);
if ( reference != null ) {
return reference;
}
}
return getTableGroup().getTableReference( navigablePath, tableExpression );
}
}

View File

@ -9,7 +9,6 @@ package org.hibernate.sql.ast.tree.from;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
@ -62,20 +61,15 @@ public class MutatingTableReferenceGroupWrapper implements VirtualTableGroup {
} }
@Override @Override
public TableReference getTableReference(String tableExpression) { public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
return mutatingTableReference.getTableExpression().equals( tableExpression ) return mutatingTableReference.getTableExpression().equals( tableExpression )
? mutatingTableReference ? mutatingTableReference
: null; : null;
} }
@Override @Override
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) { public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
return resolveTableReference( tableExpression ); return getTableReference( navigablePath, tableExpression );
}
@Override
public TableReference resolveTableReference(String tableExpression) {
return getTableReference( tableExpression );
} }
@Override @Override

View File

@ -26,6 +26,7 @@ public class StandardTableGroup extends AbstractTableGroup {
private final Predicate<String> tableReferenceJoinNameChecker; private final Predicate<String> tableReferenceJoinNameChecker;
private final BiFunction<String,TableGroup,TableReferenceJoin> tableReferenceJoinCreator; private final BiFunction<String,TableGroup,TableReferenceJoin> tableReferenceJoinCreator;
private final boolean realTableGroup; private final boolean realTableGroup;
private final boolean fetched;
private List<TableReferenceJoin> tableJoins; private List<TableReferenceJoin> tableJoins;
@ -39,6 +40,7 @@ public class StandardTableGroup extends AbstractTableGroup {
super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory ); super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory );
this.primaryTableReference = primaryTableReference; this.primaryTableReference = primaryTableReference;
this.realTableGroup = false; this.realTableGroup = false;
this.fetched = false;
this.tableJoins = Collections.emptyList(); this.tableJoins = Collections.emptyList();
this.tableReferenceJoinCreator = null; this.tableReferenceJoinCreator = null;
this.tableReferenceJoinNameChecker = s -> { this.tableReferenceJoinNameChecker = s -> {
@ -64,6 +66,27 @@ public class StandardTableGroup extends AbstractTableGroup {
super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory ); super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory );
this.primaryTableReference = primaryTableReference; this.primaryTableReference = primaryTableReference;
this.realTableGroup = realTableGroup; this.realTableGroup = realTableGroup;
this.fetched = false;
this.tableJoins = null;
this.tableReferenceJoinNameChecker = tableReferenceJoinNameChecker;
this.tableReferenceJoinCreator = tableReferenceJoinCreator;
}
public StandardTableGroup(
NavigablePath navigablePath,
TableGroupProducer tableGroupProducer,
boolean fetched,
LockMode lockMode,
TableReference primaryTableReference,
boolean realTableGroup,
SqlAliasBase sqlAliasBase,
Predicate<String> tableReferenceJoinNameChecker,
BiFunction<String, TableGroup, TableReferenceJoin> tableReferenceJoinCreator,
SessionFactoryImplementor sessionFactory) {
super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory );
this.primaryTableReference = primaryTableReference;
this.realTableGroup = realTableGroup;
this.fetched = fetched;
this.tableJoins = null; this.tableJoins = null;
this.tableReferenceJoinNameChecker = tableReferenceJoinNameChecker; this.tableReferenceJoinNameChecker = tableReferenceJoinNameChecker;
this.tableReferenceJoinCreator = tableReferenceJoinCreator; this.tableReferenceJoinCreator = tableReferenceJoinCreator;
@ -78,11 +101,6 @@ public class StandardTableGroup extends AbstractTableGroup {
} }
} }
@Override
public TableReference getTableReference(String tableExpression) {
return getTableReferenceInternal( tableExpression );
}
@Override @Override
public TableReference getPrimaryTableReference() { public TableReference getPrimaryTableReference() {
return primaryTableReference; return primaryTableReference;
@ -98,6 +116,11 @@ public class StandardTableGroup extends AbstractTableGroup {
return realTableGroup; return realTableGroup;
} }
@Override
public boolean isFetched() {
return fetched;
}
public void addTableReferenceJoin(TableReferenceJoin join) { public void addTableReferenceJoin(TableReferenceJoin join) {
if ( tableJoins == null ) { if ( tableJoins == null ) {
tableJoins = new ArrayList<>(); tableJoins = new ArrayList<>();
@ -106,8 +129,10 @@ public class StandardTableGroup extends AbstractTableGroup {
} }
@Override @Override
public TableReference getTableReferenceInternal(String tableExpression) { public TableReference getTableReferenceInternal(
TableReference tableReference = primaryTableReference.getTableReference( tableExpression ); NavigablePath navigablePath,
String tableExpression) {
TableReference tableReference = primaryTableReference.getTableReference( navigablePath, tableExpression );
if ( tableReference != null ) { if ( tableReference != null ) {
return tableReference; return tableReference;
} }
@ -118,7 +143,7 @@ public class StandardTableGroup extends AbstractTableGroup {
final TableReferenceJoin join = tableJoins.get( i ); final TableReferenceJoin join = tableJoins.get( i );
assert join != null; assert join != null;
final TableReference resolveTableReference = join.getJoinedTableReference() final TableReference resolveTableReference = join.getJoinedTableReference()
.getTableReference( tableExpression ); .getTableReference( navigablePath, tableExpression );
if ( resolveTableReference != null ) { if ( resolveTableReference != null ) {
return resolveTableReference; return resolveTableReference;
} }
@ -130,7 +155,7 @@ public class StandardTableGroup extends AbstractTableGroup {
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) { for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference(); final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference();
if ( primaryTableReference.getTableReference( tableExpression ) != null ) { if ( primaryTableReference.getTableReference( navigablePath, tableExpression ) != null ) {
return primaryTableReference; return primaryTableReference;
} }
} }

View File

@ -91,4 +91,8 @@ public interface TableGroup extends SqlAstNode, ColumnReferenceQualifier, SqmPat
default boolean isRealTableGroup() { default boolean isRealTableGroup() {
return false; return false;
} }
default boolean isFetched() {
return false;
}
} }

View File

@ -26,13 +26,15 @@ public interface TableGroupJoinProducer extends TableGroupProducer {
TableGroup lhs, TableGroup lhs,
String explicitSourceAlias, String explicitSourceAlias,
SqlAstJoinType sqlAstJoinType, SqlAstJoinType sqlAstJoinType,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAstCreationState creationState) { SqlAstCreationState creationState) {
return createTableGroupJoin( return createTableGroupJoin(
navigablePath, navigablePath,
lhs, lhs,
explicitSourceAlias, explicitSourceAlias,
sqlAstJoinType, sqlAstJoinType,
fetched,
lockMode, lockMode,
creationState.getSqlAliasBaseGenerator(), creationState.getSqlAliasBaseGenerator(),
creationState.getSqlExpressionResolver(), creationState.getSqlExpressionResolver(),
@ -48,6 +50,7 @@ public interface TableGroupJoinProducer extends TableGroupProducer {
TableGroup lhs, TableGroup lhs,
String explicitSourceAlias, String explicitSourceAlias,
SqlAstJoinType sqlAstJoinType, SqlAstJoinType sqlAstJoinType,
boolean fetched,
LockMode lockMode, LockMode lockMode,
SqlAliasBaseGenerator aliasBaseGenerator, SqlAliasBaseGenerator aliasBaseGenerator,
SqlExpressionResolver sqlExpressionResolver, SqlExpressionResolver sqlExpressionResolver,

View File

@ -7,9 +7,9 @@
package org.hibernate.sql.ast.tree.from; package org.hibernate.sql.ast.tree.from;
import java.util.Objects; import java.util.Objects;
import java.util.function.Supplier;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.SqlAstWalker; import org.hibernate.sql.ast.SqlAstWalker;
import org.hibernate.sql.ast.tree.SqlAstNode; import org.hibernate.sql.ast.tree.SqlAstNode;
@ -52,12 +52,7 @@ public class TableReference implements SqlAstNode, ColumnReferenceQualifier {
} }
@Override @Override
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) { public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
throw new UnsupportedOperationException( "Cannot create a TableReference relative to a TableReference" );
}
@Override
public TableReference resolveTableReference(String tableExpression) {
if ( tableExpression.equals( getTableExpression() ) ) { if ( tableExpression.equals( getTableExpression() ) ) {
return this; return this;
} }
@ -65,7 +60,7 @@ public class TableReference implements SqlAstNode, ColumnReferenceQualifier {
} }
@Override @Override
public TableReference getTableReference(String tableExpression) { public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
if ( this.tableExpression.equals( tableExpression ) ) { if ( this.tableExpression.equals( tableExpression ) ) {
return this; return this;
} }

View File

@ -10,7 +10,6 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
@ -109,19 +108,13 @@ public class UnionTableGroup implements VirtualTableGroup {
} }
@Override @Override
public TableReference getTableReference(String tableExpression) { public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
// assert tableReference.getTableExpression().equals( tableExpression ); // assert tableReference.getTableExpression().equals( tableExpression );
return tableReference; return tableReference;
} }
@Override @Override
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) { public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
assert tableReference.getTableExpression().equals( tableExpression );
return tableReference;
}
@Override
public TableReference resolveTableReference(String tableExpression) {
// assert tableReference.getTableExpression().equals( tableExpression ); // assert tableReference.getTableExpression().equals( tableExpression );
return tableReference; return tableReference;
} }

View File

@ -7,6 +7,7 @@
package org.hibernate.sql.ast.tree.from; package org.hibernate.sql.ast.tree.from;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.query.NavigablePath;
/** /**
* @author Andrea Boriero * @author Andrea Boriero
@ -25,7 +26,7 @@ public class UnionTableReference extends TableReference {
this.subclassTableSpaceExpressions = subclassTableSpaceExpressions; this.subclassTableSpaceExpressions = subclassTableSpaceExpressions;
} }
public TableReference resolveTableReference(String tableExpression) { public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
if ( hasTableExpression( tableExpression ) ) { if ( hasTableExpression( tableExpression ) ) {
return this; return this;
} }
@ -33,7 +34,7 @@ public class UnionTableReference extends TableReference {
} }
@Override @Override
public TableReference getTableReference(String tableExpression) { public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
if ( hasTableExpression( tableExpression ) ) { if ( hasTableExpression( tableExpression ) ) {
return this; return this;
} }

View File

@ -42,6 +42,10 @@ public interface FetchParent extends DomainResultGraphNode {
return null; return null;
} }
default NavigablePath resolveNavigablePath(Fetchable fetchable) {
return getNavigablePath().append( fetchable.getFetchableName() );
}
/** /**
* Whereas {@link #getReferencedMappingContainer} and {@link #getReferencedMappingType} return the * Whereas {@link #getReferencedMappingContainer} and {@link #getReferencedMappingType} return the
* referenced container type, this method returns the referenced part. * referenced container type, this method returns the referenced part.

View File

@ -8,7 +8,6 @@ package org.hibernate.sql.results.graph.collection.internal;
import java.util.List; import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Supplier;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPart;
@ -103,18 +102,13 @@ public class EntityCollectionPartTableGroup implements TableGroup {
} }
@Override @Override
public TableReference getTableReference(String tableExpression) { public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
return collectionTableGroup.getTableReference( tableExpression ); return collectionTableGroup.getTableReference( tableExpression );
} }
@Override @Override
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) { public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
return collectionTableGroup.resolveTableReference( tableExpression, creator ); return collectionTableGroup.resolveTableReference( navigablePath, tableExpression );
}
@Override
public TableReference resolveTableReference(String tableExpression) {
return collectionTableGroup.resolveTableReference( tableExpression );
} }
@Override @Override

View File

@ -66,6 +66,7 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab
lhsTableGroup, lhsTableGroup,
null, null,
nullable ? SqlAstJoinType.LEFT : SqlAstJoinType.INNER, nullable ? SqlAstJoinType.LEFT : SqlAstJoinType.INNER,
true,
LockMode.NONE, LockMode.NONE,
creationState.getSqlAstCreationState() creationState.getSqlAstCreationState()
); );

View File

@ -61,12 +61,22 @@ public class EmbeddableForeignKeyResultImpl<T>
LockMode lockMode, LockMode lockMode,
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
final boolean shouldSelect;
if ( fetchable instanceof ToOneAttributeMapping ) {
// We need to make sure to-ones are always delayed to avoid cycles while resolving entity keys
final ToOneAttributeMapping toOne = (ToOneAttributeMapping) fetchable;
shouldSelect = selected && !creationState.isAssociationKeyVisited(
toOne.getForeignKeyDescriptor().getAssociationKey()
);
}
else {
shouldSelect = selected;
}
return fetchable.generateFetch( return fetchable.generateFetch(
this, this,
fetchablePath, fetchablePath,
fetchTiming, fetchTiming,
// We need to make sure to-ones are always delayed to avoid cycles while resolving entity keys shouldSelect,
selected && !( fetchable instanceof ToOneAttributeMapping ),
lockMode, lockMode,
resultVariable, resultVariable,
creationState creationState

View File

@ -52,6 +52,7 @@ public class EmbeddableResultImpl<T> extends AbstractFetchParent implements Embe
fromClauseAccess.findTableGroup( navigablePath.getParent() ), fromClauseAccess.findTableGroup( navigablePath.getParent() ),
resultVariable, resultVariable,
SqlAstJoinType.INNER, SqlAstJoinType.INNER,
true,
LockMode.NONE, LockMode.NONE,
creationState.getSqlAstCreationState() creationState.getSqlAstCreationState()
); );

View File

@ -73,6 +73,16 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
identifierResult = null; identifierResult = null;
visitIdentifierMapping( identifierNavigablePath, creationState, identifierMapping, entityTableGroup ); visitIdentifierMapping( identifierNavigablePath, creationState, identifierMapping, entityTableGroup );
} }
else if ( referencedModelPart instanceof ToOneAttributeMapping
&& ( (ToOneAttributeMapping) referencedModelPart ).canJoinForeignKey( identifierMapping ) ) {
// If we don't do this here, LazyTableGroup#getTableReferenceInternal would have to use the target table in case {id} is encountered
identifierResult = ( (ToOneAttributeMapping) referencedModelPart ).getForeignKeyDescriptor().createDomainResult(
navigablePath,
creationState.getSqlAstCreationState().getFromClauseAccess().findTableGroup( navigablePath.getParent() ),
null,
creationState
);
}
else { else {
identifierResult = identifierMapping.createDomainResult( identifierResult = identifierMapping.createDomainResult(
identifierNavigablePath, identifierNavigablePath,

View File

@ -9,6 +9,7 @@ package org.hibernate.sql.results.graph.entity.internal;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.engine.FetchTiming; import org.hibernate.engine.FetchTiming;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.FetchParent; import org.hibernate.sql.results.graph.FetchParent;
@ -29,6 +30,7 @@ public class EntityFetchJoinedImpl extends AbstractNonLazyEntityFetch {
public EntityFetchJoinedImpl( public EntityFetchJoinedImpl(
FetchParent fetchParent, FetchParent fetchParent,
EntityValuedFetchable fetchedAttribute, EntityValuedFetchable fetchedAttribute,
TableGroup tableGroup,
LockMode lockMode, LockMode lockMode,
boolean nullable, boolean nullable,
NavigablePath navigablePath, NavigablePath navigablePath,
@ -38,6 +40,7 @@ public class EntityFetchJoinedImpl extends AbstractNonLazyEntityFetch {
entityResult = new EntityResultImpl( entityResult = new EntityResultImpl(
navigablePath, navigablePath,
fetchedAttribute, fetchedAttribute,
tableGroup,
null, null,
creationState creationState
); );

View File

@ -9,9 +9,13 @@ package org.hibernate.sql.results.graph.entity.internal;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.EntityValuedModelPart; import org.hibernate.metamodel.mapping.EntityValuedModelPart;
import org.hibernate.query.NavigablePath; import org.hibernate.query.NavigablePath;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
import org.hibernate.sql.ast.tree.from.TableGroupProducer;
import org.hibernate.sql.results.graph.AssemblerCreationState; import org.hibernate.sql.results.graph.AssemblerCreationState;
import org.hibernate.sql.results.graph.DomainResultAssembler; import org.hibernate.sql.results.graph.DomainResultAssembler;
import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.sql.results.graph.DomainResultCreationState;
import org.hibernate.sql.results.graph.Fetchable;
import org.hibernate.sql.results.graph.FetchableContainer; import org.hibernate.sql.results.graph.FetchableContainer;
import org.hibernate.sql.results.graph.entity.AbstractEntityResultGraphNode; import org.hibernate.sql.results.graph.entity.AbstractEntityResultGraphNode;
import org.hibernate.sql.results.graph.entity.EntityInitializer; import org.hibernate.sql.results.graph.entity.EntityInitializer;
@ -24,19 +28,22 @@ import org.hibernate.sql.results.graph.entity.EntityResult;
*/ */
public class EntityResultImpl extends AbstractEntityResultGraphNode implements EntityResult { public class EntityResultImpl extends AbstractEntityResultGraphNode implements EntityResult {
private final TableGroup tableGroup;
private final String resultVariable; private final String resultVariable;
public EntityResultImpl( public EntityResultImpl(
NavigablePath navigablePath, NavigablePath navigablePath,
EntityValuedModelPart entityValuedModelPart, EntityValuedModelPart entityValuedModelPart,
TableGroup tableGroup,
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
this( navigablePath, entityValuedModelPart, resultVariable, null, creationState ); this( navigablePath, entityValuedModelPart, tableGroup, resultVariable, null, creationState );
} }
public EntityResultImpl( public EntityResultImpl(
NavigablePath navigablePath, NavigablePath navigablePath,
EntityValuedModelPart entityValuedModelPart, EntityValuedModelPart entityValuedModelPart,
TableGroup tableGroup,
String resultVariable, String resultVariable,
EntityMappingType targetType, EntityMappingType targetType,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
@ -46,12 +53,27 @@ public class EntityResultImpl extends AbstractEntityResultGraphNode implements E
navigablePath, navigablePath,
creationState creationState
); );
this.tableGroup = tableGroup;
this.resultVariable = resultVariable; this.resultVariable = resultVariable;
afterInitialize( creationState ); afterInitialize( creationState );
} }
@Override
public NavigablePath resolveNavigablePath(Fetchable fetchable) {
// todo: this is not ideal yet as we could potentially resolve a path that we did not intend
// to fix this, we'd need to know if the table group is for a fetch
if ( fetchable instanceof TableGroupProducer &&
!getNavigablePath().getUnaliasedLocalName().equals( getNavigablePath().getLocalName() ) ) {
for ( TableGroupJoin tableGroupJoin : tableGroup.getTableGroupJoins() ) {
if ( tableGroupJoin.getJoinedGroup().isFetched() && tableGroupJoin.getJoinedGroup().getModelPart() == fetchable ) {
return tableGroupJoin.getNavigablePath();
}
}
}
return super.resolveNavigablePath( fetchable );
}
@Override @Override
public FetchableContainer getReferencedMappingType() { public FetchableContainer getReferencedMappingType() {
return getReferencedMappingContainer(); return getReferencedMappingContainer();

View File

@ -24,9 +24,10 @@ public class EntityResultJoinedSubclassImpl extends EntityResultImpl {
public EntityResultJoinedSubclassImpl( public EntityResultJoinedSubclassImpl(
NavigablePath navigablePath, NavigablePath navigablePath,
EntityValuedModelPart entityValuedModelPart, EntityValuedModelPart entityValuedModelPart,
TableGroup tableGroup,
String resultVariable, String resultVariable,
DomainResultCreationState creationState) { DomainResultCreationState creationState) {
super( navigablePath, entityValuedModelPart, resultVariable, creationState ); super( navigablePath, entityValuedModelPart, tableGroup, resultVariable, creationState );
} }
@Override @Override

View File

@ -29,6 +29,7 @@ import org.hibernate.type.descriptor.jdbc.RealTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.SmallIntTypeDescriptor; import org.hibernate.type.descriptor.jdbc.SmallIntTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.TimeTypeDescriptor; import org.hibernate.type.descriptor.jdbc.TimeTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.TimestampTypeDescriptor; import org.hibernate.type.descriptor.jdbc.TimestampTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.TimestampWithTimeZoneDescriptor;
import org.hibernate.type.descriptor.jdbc.TinyIntTypeDescriptor; import org.hibernate.type.descriptor.jdbc.TinyIntTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.VarbinaryTypeDescriptor; import org.hibernate.type.descriptor.jdbc.VarbinaryTypeDescriptor;
import org.hibernate.type.descriptor.jdbc.VarcharTypeDescriptor; import org.hibernate.type.descriptor.jdbc.VarcharTypeDescriptor;
@ -57,6 +58,7 @@ public class JdbcTypeDescriptorBaseline {
target.addDescriptor( DateTypeDescriptor.INSTANCE ); target.addDescriptor( DateTypeDescriptor.INSTANCE );
target.addDescriptor( TimestampTypeDescriptor.INSTANCE ); target.addDescriptor( TimestampTypeDescriptor.INSTANCE );
target.addDescriptor( TimestampWithTimeZoneDescriptor.INSTANCE );
target.addDescriptor( TimeTypeDescriptor.INSTANCE ); target.addDescriptor( TimeTypeDescriptor.INSTANCE );
target.addDescriptor( BinaryTypeDescriptor.INSTANCE ); target.addDescriptor( BinaryTypeDescriptor.INSTANCE );

Some files were not shown because too many files have changed in this diff Show More