Implement support for avoiding joins when accessing FK keys
This commit is contained in:
parent
c74e5ef595
commit
df9d285f2c
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.userguide.mapping.identifier.composite;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.time.OffsetDateTime;
|
||||
|
||||
import org.hibernate.dialect.H2Dialect;
|
||||
import org.hibernate.jpa.test.BaseEntityManagerFunctionalTestCase;
|
||||
|
@ -33,15 +34,16 @@ public class EmbeddedIdDatabaseGeneratedValueTest extends BaseEntityManagerFunct
|
|||
@TestForIssue(jiraKey = "HHH-13096")
|
||||
public void test() {
|
||||
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[]
|
||||
Timestamp currentTimestamp = (Timestamp) entityManager
|
||||
OffsetDateTime currentTimestamp = (OffsetDateTime) entityManager
|
||||
.createNativeQuery(
|
||||
"SELECT CURRENT_TIMESTAMP" )
|
||||
.getSingleResult();
|
||||
|
||||
EventId id = new EventId();
|
||||
id.setCategory( 1 );
|
||||
id.setCreatedOn( currentTimestamp );
|
||||
id.setCreatedOn( Timestamp.from( currentTimestamp.toInstant() ) );
|
||||
|
||||
Event event = new Event();
|
||||
event.setId( id );
|
||||
|
|
|
@ -101,7 +101,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
|
|||
final List<Fetch> fetches = new ArrayList<>( naturalIdMapping.getNaturalIdAttributes().size() );
|
||||
fetchParent.getReferencedMappingContainer().visitFetchables(
|
||||
fetchable -> {
|
||||
final NavigablePath navigablePath = fetchParent.getNavigablePath().append( fetchable.getFetchableName() );
|
||||
final NavigablePath navigablePath = fetchParent.resolveNavigablePath( fetchable );
|
||||
final Fetch fetch = fetchParent.generateFetchableFetch(
|
||||
fetchable,
|
||||
navigablePath,
|
||||
|
@ -280,7 +280,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
|
|||
SelectableMapping selectableMapping,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SessionFactoryImplementor sessionFactory) {
|
||||
final TableReference tableReference = rootTableGroup.getTableReference( selectableMapping.getContainingTableExpression() );
|
||||
final TableReference tableReference = rootTableGroup.getTableReference( rootTableGroup.getNavigablePath(), selectableMapping.getContainingTableExpression() );
|
||||
if ( tableReference == null ) {
|
||||
throw new IllegalStateException(
|
||||
String.format(
|
||||
|
@ -321,7 +321,7 @@ public abstract class AbstractNaturalIdLoader<T> implements NaturalIdLoader<T> {
|
|||
|
||||
fetchParent.getReferencedMappingContainer().visitFetchables(
|
||||
(fetchable) -> {
|
||||
final NavigablePath navigablePath = fetchParent.getNavigablePath().append( fetchable.getFetchableName() );
|
||||
final NavigablePath navigablePath = fetchParent.resolveNavigablePath( fetchable );
|
||||
final Fetch fetch = fetchParent.generateFetchableFetch(
|
||||
fetchable,
|
||||
navigablePath,
|
||||
|
|
|
@ -109,10 +109,13 @@ class DatabaseSnapshotExecutor {
|
|||
domainResults.add(
|
||||
new QueryLiteral<>( null, IntegerType.INSTANCE ).createDomainResult( null, state )
|
||||
);
|
||||
|
||||
final NavigablePath idNavigablePath = rootPath.append( entityDescriptor.getIdentifierMapping().getNavigableRole().getNavigableName() );
|
||||
entityDescriptor.getIdentifierMapping().forEachSelectable(
|
||||
(columnIndex, selection) -> {
|
||||
final TableReference tableReference = rootTableGroup.resolveTableReference( selection.getContainingTableExpression() );
|
||||
final TableReference tableReference = rootTableGroup.resolveTableReference(
|
||||
idNavigablePath,
|
||||
selection.getContainingTableExpression()
|
||||
);
|
||||
|
||||
final JdbcParameter jdbcParameter = new JdbcParameterImpl( selection.getJdbcMapping() );
|
||||
jdbcParameters.add( jdbcParameter );
|
||||
|
|
|
@ -467,12 +467,13 @@ public class LoaderSelectBuilder {
|
|||
Consumer<JdbcParameter> jdbcParameterConsumer,
|
||||
LoaderSqlAstCreationState sqlAstCreationState) {
|
||||
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
|
||||
final NavigablePath navigablePath = rootNavigablePath.append( modelPart.getNavigableRole().getNavigableName() );
|
||||
|
||||
if ( numberColumns == 1 ) {
|
||||
modelPart.forEachSelectable(
|
||||
(columnIndex, selection) -> {
|
||||
final TableReference tableReference = rootTableGroup.resolveTableReference(
|
||||
selection.getContainingTableExpression() );
|
||||
navigablePath, selection.getContainingTableExpression() );
|
||||
final ColumnReference columnRef =
|
||||
(ColumnReference) sqlExpressionResolver.resolveSqlExpression(
|
||||
createColumnReferenceKey( tableReference, selection.getSelectionExpression() ),
|
||||
|
@ -511,7 +512,7 @@ public class LoaderSelectBuilder {
|
|||
|
||||
modelPart.forEachSelectable(
|
||||
(columnIndex, selection) -> {
|
||||
final TableReference tableReference = rootTableGroup.resolveTableReference( selection.getContainingTableExpression() );
|
||||
final TableReference tableReference = rootTableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() );
|
||||
columnReferences.add(
|
||||
(ColumnReference) sqlExpressionResolver.resolveSqlExpression(
|
||||
createColumnReferenceKey( tableReference, selection.getSelectionExpression() ),
|
||||
|
@ -629,7 +630,6 @@ public class LoaderSelectBuilder {
|
|||
List<Fetch> fetches,
|
||||
List<String> bagRoles) {
|
||||
return (fetchable, isKeyFetchable) -> {
|
||||
final NavigablePath parentNavigablePath = fetchParent.getNavigablePath();
|
||||
final NavigablePath fetchablePath;
|
||||
|
||||
if ( isKeyFetchable ) {
|
||||
|
@ -659,16 +659,16 @@ public class LoaderSelectBuilder {
|
|||
|
||||
if ( identifierMapping != null ) {
|
||||
fetchablePath = new EntityIdentifierNavigablePath(
|
||||
parentNavigablePath,
|
||||
fetchParent.getNavigablePath(),
|
||||
attributeName( identifierMapping )
|
||||
);
|
||||
}
|
||||
else {
|
||||
fetchablePath = parentNavigablePath.append( fetchable.getFetchableName() );
|
||||
fetchablePath = fetchParent.resolveNavigablePath( fetchable );
|
||||
}
|
||||
}
|
||||
else {
|
||||
fetchablePath = parentNavigablePath.append( fetchable.getFetchableName() );
|
||||
fetchablePath = fetchParent.resolveNavigablePath( fetchable );
|
||||
}
|
||||
|
||||
final Fetch biDirectionalFetch = fetchable.resolveCircularFetch(
|
||||
|
@ -879,6 +879,7 @@ public class LoaderSelectBuilder {
|
|||
|
||||
final PluralAttributeMapping attributeMapping = (PluralAttributeMapping) loadable;
|
||||
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();
|
||||
final NavigablePath navigablePath = rootNavigablePath.append( attributeMapping.getAttributeName() );
|
||||
|
||||
final Expression fkExpression;
|
||||
|
||||
|
@ -892,7 +893,7 @@ public class LoaderSelectBuilder {
|
|||
simpleFkDescriptor.getSelectionExpression()
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
rootTableGroup.resolveTableReference( simpleFkDescriptor.getContainingTableExpression() ),
|
||||
rootTableGroup.resolveTableReference( navigablePath, simpleFkDescriptor.getContainingTableExpression() ),
|
||||
simpleFkDescriptor.getSelectionExpression(),
|
||||
false,
|
||||
null,
|
||||
|
@ -914,7 +915,7 @@ public class LoaderSelectBuilder {
|
|||
selection.getSelectionExpression()
|
||||
),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
rootTableGroup.resolveTableReference( selection.getContainingTableExpression() ),
|
||||
rootTableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() ),
|
||||
selection,
|
||||
this.creationContext.getSessionFactory()
|
||||
)
|
||||
|
@ -961,11 +962,12 @@ public class LoaderSelectBuilder {
|
|||
loadingSqlAst.getFromClause().visitRoots( subQuery.getFromClause()::addRoot );
|
||||
|
||||
final SqlExpressionResolver sqlExpressionResolver = creationState.getSqlExpressionResolver();
|
||||
final NavigablePath navigablePath = ownerTableGroup.getNavigablePath().append( attributeMapping.getAttributeName() );
|
||||
|
||||
fkDescriptor.visitTargetSelectables(
|
||||
(valuesPosition, selection) -> {
|
||||
// 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(
|
||||
createColumnReferenceKey( tableReference, selection.getSelectionExpression() ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
|
|
|
@ -162,6 +162,7 @@ public abstract class AbstractCompositeIdentifierMapping
|
|||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
|
@ -228,12 +229,13 @@ public abstract class AbstractCompositeIdentifierMapping
|
|||
SqlAstCreationState sqlAstCreationState) {
|
||||
final SelectableMappings selectableMappings = getEmbeddableTypeDescriptor();
|
||||
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(
|
||||
(columnIndex, selection) -> {
|
||||
final TableReference tableReference = selection.getContainingTableExpression().equals( defaultTableReference.getTableExpression() )
|
||||
? defaultTableReference
|
||||
: tableGroup.resolveTableReference( selection.getContainingTableExpression() );
|
||||
: tableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() );
|
||||
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver()
|
||||
.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey(
|
||||
|
|
|
@ -454,6 +454,7 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectableMapp
|
|||
attributeIndex,
|
||||
bootPropertyDescriptor,
|
||||
entityPersister,
|
||||
entityPersister,
|
||||
(EntityType) subtype,
|
||||
getRepresentationStrategy().resolvePropertyAccess( bootPropertyDescriptor ),
|
||||
compositeType.getCascadeStyle( attributeIndex ),
|
||||
|
|
|
@ -32,6 +32,8 @@ public interface ForeignKeyDescriptor extends VirtualModelPart {
|
|||
|
||||
ModelPart getKeyPart();
|
||||
|
||||
ModelPart getTargetPart();
|
||||
|
||||
/**
|
||||
* Create a DomainResult for the referring-side of the fk
|
||||
*/
|
||||
|
|
|
@ -57,7 +57,7 @@ public abstract class AbstractDomainPath implements DomainPath {
|
|||
SqlAstCreationState creationState) {
|
||||
if ( referenceModelPart instanceof BasicValuedModelPart ) {
|
||||
final BasicValuedModelPart selection = (BasicValuedModelPart) referenceModelPart;
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( selection.getContainingTableExpression() );
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( getNavigablePath(), selection.getContainingTableExpression() );
|
||||
return creationState.getSqlExpressionResolver().resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey(
|
||||
selection.getContainingTableExpression(),
|
||||
|
@ -221,7 +221,7 @@ public abstract class AbstractDomainPath implements DomainPath {
|
|||
String collation,
|
||||
SortOrder sortOrder,
|
||||
SqlAstCreationState creationState) {
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( selection.getContainingTableExpression() );
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( getNavigablePath(), selection.getContainingTableExpression() );
|
||||
final Expression expression = creationState.getSqlExpressionResolver().resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey(
|
||||
selection.getContainingTableExpression(),
|
||||
|
|
|
@ -190,7 +190,7 @@ public class AnyDiscriminatorPart implements BasicValuedModelPart, FetchOptions,
|
|||
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
|
||||
|
||||
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(
|
||||
createColumnReferenceKey( tableReference, column ),
|
||||
processingState -> new ColumnReference(
|
||||
|
|
|
@ -153,7 +153,7 @@ public class AnyKeyPart implements BasicValuedModelPart, FetchOptions {
|
|||
.getSessionFactory();
|
||||
|
||||
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(
|
||||
SqlExpressionResolver.createColumnReferenceKey( tableReference, column ),
|
||||
|
|
|
@ -202,7 +202,7 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa
|
|||
.getSqlExpressionResolver();
|
||||
final TableReference rootTableReference;
|
||||
try {
|
||||
rootTableReference = tableGroup.resolveTableReference( rootTable );
|
||||
rootTableReference = tableGroup.resolveTableReference( navigablePath, rootTable );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new IllegalStateException(
|
||||
|
|
|
@ -217,7 +217,11 @@ public class BasicValuedSingularAttributeMapping
|
|||
|
||||
private SqlSelection resolveSqlSelection(TableGroup tableGroup, DomainResultCreationState creationState) {
|
||||
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();
|
||||
return expressionResolver.resolveSqlSelection(
|
||||
expressionResolver.resolveSqlExpression(
|
||||
|
|
|
@ -228,12 +228,13 @@ public class EmbeddedAttributeMapping
|
|||
SqmToSqlAstConverter walker,
|
||||
SqlAstCreationState sqlAstCreationState) {
|
||||
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(
|
||||
(columnIndex, selection) -> {
|
||||
final TableReference tableReference = selection.getContainingTableExpression().equals( defaultTableReference.getTableExpression() )
|
||||
? defaultTableReference
|
||||
: tableGroup.resolveTableReference( selection.getContainingTableExpression() );
|
||||
: tableGroup.resolveTableReference( navigablePath, selection.getContainingTableExpression() );
|
||||
final Expression columnReference = sqlAstCreationState.getSqlExpressionResolver().resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey(
|
||||
tableReference,
|
||||
|
@ -273,6 +274,7 @@ public class EmbeddedAttributeMapping
|
|||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
|
|
|
@ -176,7 +176,11 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
|||
sqlExpressionResolver.resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey( selection.getContainingTableExpression(), selection.getSelectionExpression() ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
tableGroup.resolveTableReference( selection.getContainingTableExpression() ),
|
||||
tableGroup.resolveTableReference(
|
||||
tableGroup.getNavigablePath()
|
||||
.append( getNavigableRole().getNavigableName() ),
|
||||
selection.getContainingTableExpression()
|
||||
),
|
||||
selection,
|
||||
sqlAstCreationState.getCreationContext().getSessionFactory()
|
||||
)
|
||||
|
@ -193,6 +197,7 @@ public class EmbeddedCollectionPart implements CollectionPart, EmbeddableValuedF
|
|||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
|
|
|
@ -245,6 +245,7 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
|
|||
tableGroup,
|
||||
null,
|
||||
SqlAstJoinType.INNER,
|
||||
true,
|
||||
LockMode.NONE,
|
||||
creationState.getSqlAstCreationState()
|
||||
);
|
||||
|
@ -370,7 +371,11 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
|
|||
return tableGroup.getPrimaryTableReference();
|
||||
}
|
||||
|
||||
final TableReference tableReference = lhs.resolveTableReference( table );
|
||||
final TableReference tableReference = lhs.resolveTableReference(
|
||||
lhs.getNavigablePath()
|
||||
.append( getNavigableRole().getNavigableName() ),
|
||||
table
|
||||
);
|
||||
if ( tableReference != null ) {
|
||||
return tableReference;
|
||||
}
|
||||
|
@ -407,6 +412,11 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
|
|||
return keyMappingType.getEmbeddableTypeDescriptor().getEmbeddedValueMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ModelPart getTargetPart() {
|
||||
return targetMappingType.getEmbeddableTypeDescriptor().getEmbeddedValueMapping();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingType getPartMappingType() {
|
||||
return targetMappingType.getPartMappingType();
|
||||
|
@ -437,6 +447,7 @@ public class EmbeddedForeignKeyDescriptor implements ForeignKeyDescriptor {
|
|||
tableGroup,
|
||||
null,
|
||||
null,
|
||||
true,
|
||||
LockMode.NONE,
|
||||
creationState.getSqlAstCreationState()
|
||||
);
|
||||
|
|
|
@ -151,7 +151,7 @@ public class EntityCollectionPart
|
|||
final FromClauseAccess fromClauseAccess = creationState.getSqlAstCreationState().getFromClauseAccess();
|
||||
creationState.registerVisitedAssociationKey( getForeignKeyDescriptor().getAssociationKey() );
|
||||
|
||||
fromClauseAccess.resolveTableGroup(
|
||||
TableGroup tableGroup = fromClauseAccess.resolveTableGroup(
|
||||
fetchablePath,
|
||||
np -> {
|
||||
// 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
|
||||
|
@ -347,6 +347,7 @@ public class EntityCollectionPart
|
|||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
|
@ -356,6 +357,7 @@ public class EntityCollectionPart
|
|||
lhs,
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
lockMode,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
|
|
|
@ -42,7 +42,11 @@ public class EntityDiscriminatorMappingImpl extends AbstractEntityDiscriminatorM
|
|||
final SqlExpressionResolver expressionResolver = creationState.getSqlAstCreationState()
|
||||
.getSqlExpressionResolver();
|
||||
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( getContainingTableExpression() );
|
||||
final TableReference tableReference = tableGroup.resolveTableReference(
|
||||
tableGroup.getNavigablePath()
|
||||
.append( getNavigableRole().getNavigableName() ),
|
||||
getContainingTableExpression()
|
||||
);
|
||||
|
||||
return expressionResolver.resolveSqlSelection(
|
||||
expressionResolver.resolveSqlExpression(
|
||||
|
|
|
@ -83,7 +83,7 @@ public class EntityRowIdMappingImpl implements EntityRowIdMapping, SelectableMap
|
|||
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||
|
||||
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
|
||||
final TableReference columnTableReference = tableGroup.resolveTableReference( tableExpression );
|
||||
final TableReference columnTableReference = tableGroup.resolveTableReference( navigablePath, tableExpression );
|
||||
|
||||
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
|
||||
sqlExpressionResolver.resolveSqlExpression(
|
||||
|
|
|
@ -149,7 +149,7 @@ public class EntityVersionMappingImpl implements EntityVersionMapping, FetchOpti
|
|||
final TableGroup tableGroup = sqlAstCreationState.getFromClauseAccess().findTableGroup( fetchParent.getNavigablePath() );
|
||||
|
||||
final SqlExpressionResolver sqlExpressionResolver = sqlAstCreationState.getSqlExpressionResolver();
|
||||
final TableReference columnTableReference = tableGroup.resolveTableReference( columnTableExpression );
|
||||
final TableReference columnTableReference = tableGroup.resolveTableReference( fetchablePath, columnTableExpression );
|
||||
|
||||
final SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
|
||||
sqlExpressionResolver.resolveSqlExpression(
|
||||
|
@ -220,7 +220,11 @@ public class EntityVersionMappingImpl implements EntityVersionMapping, FetchOpti
|
|||
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||
|
||||
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(
|
||||
sqlExpressionResolver.resolveSqlExpression(
|
||||
|
|
|
@ -233,6 +233,7 @@ public class MappingModelCreationHelper {
|
|||
idAttributeMappings.size(),
|
||||
bootIdSubProperty,
|
||||
attributeMappingType,
|
||||
entityPersister,
|
||||
keyManyToOnePropertyType,
|
||||
entityPersister.getRepresentationStrategy().resolvePropertyAccess( bootIdSubProperty ),
|
||||
CascadeStyles.ALL,
|
||||
|
@ -1408,6 +1409,7 @@ public class MappingModelCreationHelper {
|
|||
int stateArrayPosition,
|
||||
Property bootProperty,
|
||||
ManagedMappingType declaringType,
|
||||
EntityPersister declaringEntityPersister,
|
||||
EntityType attrType,
|
||||
PropertyAccess propertyAccess,
|
||||
CascadeStyle cascadeStyle,
|
||||
|
@ -1454,6 +1456,7 @@ public class MappingModelCreationHelper {
|
|||
fetchStrategy,
|
||||
entityPersister,
|
||||
declaringType,
|
||||
declaringEntityPersister,
|
||||
propertyAccess
|
||||
);
|
||||
|
||||
|
|
|
@ -417,6 +417,11 @@ public class PluralAttributeMappingImpl
|
|||
return separateCollectionTable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsTableReference(String tableExpression) {
|
||||
return tableExpression.equals( separateCollectionTable );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getStateArrayPosition() {
|
||||
return stateArrayPosition;
|
||||
|
@ -494,6 +499,7 @@ public class PluralAttributeMappingImpl
|
|||
lhsTableGroup,
|
||||
null,
|
||||
SqlAstJoinType.LEFT,
|
||||
true,
|
||||
lockMode,
|
||||
creationState.getSqlAstCreationState()
|
||||
);
|
||||
|
@ -559,6 +565,7 @@ public class PluralAttributeMappingImpl
|
|||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
|
@ -570,6 +577,7 @@ public class PluralAttributeMappingImpl
|
|||
lhs,
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
lockMode,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
|
@ -582,6 +590,7 @@ public class PluralAttributeMappingImpl
|
|||
lhs,
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
lockMode,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
|
@ -600,12 +609,14 @@ public class PluralAttributeMappingImpl
|
|||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final TableGroup tableGroup = createOneToManyTableGroup(
|
||||
navigablePath,
|
||||
fetched,
|
||||
lockMode,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
|
@ -632,6 +643,7 @@ public class PluralAttributeMappingImpl
|
|||
|
||||
private TableGroup createOneToManyTableGroup(
|
||||
NavigablePath navigablePath,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
|
@ -658,6 +670,7 @@ public class PluralAttributeMappingImpl
|
|||
return new StandardTableGroup(
|
||||
navigablePath,
|
||||
this,
|
||||
fetched,
|
||||
lockMode,
|
||||
primaryTableReference,
|
||||
true,
|
||||
|
@ -680,12 +693,14 @@ public class PluralAttributeMappingImpl
|
|||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final TableGroup tableGroup = createCollectionTableGroup(
|
||||
navigablePath,
|
||||
fetched,
|
||||
lockMode,
|
||||
aliasBaseGenerator,
|
||||
sqlExpressionResolver,
|
||||
|
@ -712,6 +727,7 @@ public class PluralAttributeMappingImpl
|
|||
|
||||
private TableGroup createCollectionTableGroup(
|
||||
NavigablePath navigablePath,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
|
@ -840,6 +856,7 @@ public class PluralAttributeMappingImpl
|
|||
final StandardTableGroup tableGroup = new StandardTableGroup(
|
||||
navigablePath,
|
||||
this,
|
||||
fetched,
|
||||
lockMode,
|
||||
collectionTableReference,
|
||||
true,
|
||||
|
@ -931,6 +948,7 @@ public class PluralAttributeMappingImpl
|
|||
if ( getCollectionDescriptor().isOneToMany() ) {
|
||||
return createOneToManyTableGroup(
|
||||
navigablePath,
|
||||
false,
|
||||
lockMode,
|
||||
creationState.getSqlAliasBaseGenerator(),
|
||||
creationState.getSqlExpressionResolver(),
|
||||
|
@ -940,6 +958,7 @@ public class PluralAttributeMappingImpl
|
|||
else {
|
||||
return createCollectionTableGroup(
|
||||
navigablePath,
|
||||
false,
|
||||
lockMode,
|
||||
creationState.getSqlAliasBaseGenerator(),
|
||||
creationState.getSqlExpressionResolver(),
|
||||
|
|
|
@ -9,12 +9,10 @@ package org.hibernate.metamodel.mapping.internal;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.IntFunction;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.engine.FetchStyle;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
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.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.MappingModelExpressable;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.SelectableConsumer;
|
||||
import org.hibernate.metamodel.mapping.SelectableMapping;
|
||||
import org.hibernate.metamodel.mapping.SelectableMappings;
|
||||
import org.hibernate.metamodel.model.domain.NavigableRole;
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.query.ComparisonOperator;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.sql.internal.DomainResultProducer;
|
||||
import org.hibernate.sql.ast.Clause;
|
||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||
import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
||||
|
@ -94,14 +88,6 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
return targetSide.getContainingTableExpression();
|
||||
}
|
||||
|
||||
public BasicValuedModelPart getKeySide() {
|
||||
return keySide;
|
||||
}
|
||||
|
||||
public BasicValuedModelPart getTargetSide() {
|
||||
return targetSide;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ForeignKeyDescriptor withKeySelectionMapping(
|
||||
IntFunction<SelectableMapping> selectableMappingAccess,
|
||||
|
@ -146,12 +132,8 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
NavigablePath collectionPath,
|
||||
TableGroup tableGroup,
|
||||
DomainResultCreationState creationState) {
|
||||
if ( targetSide.getContainingTableExpression()
|
||||
.equals( keySide.getContainingTableExpression() ) ) {
|
||||
return createDomainResult( collectionPath, tableGroup, targetSide, creationState );
|
||||
}
|
||||
return createDomainResult( collectionPath, tableGroup, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
public DomainResult<?> createDomainResult(
|
||||
|
@ -204,7 +186,10 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
final SqlAstCreationState sqlAstCreationState = creationState.getSqlAstCreationState();
|
||||
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 SqlSelection sqlSelection = sqlExpressionResolver.resolveSqlSelection(
|
||||
|
@ -333,7 +318,11 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
return tableGroup.getPrimaryTableReference();
|
||||
}
|
||||
|
||||
final TableReference tableReference = lhs.resolveTableReference( table );
|
||||
final TableReference tableReference = lhs.resolveTableReference(
|
||||
lhs.getNavigablePath()
|
||||
.append( getNavigableRole().getNavigableName() ),
|
||||
table
|
||||
);
|
||||
if ( tableReference != null ) {
|
||||
return tableReference;
|
||||
}
|
||||
|
@ -342,10 +331,15 @@ public class SimpleForeignKeyDescriptor implements ForeignKeyDescriptor, BasicVa
|
|||
}
|
||||
|
||||
@Override
|
||||
public ModelPart getKeyPart() {
|
||||
public BasicValuedModelPart getKeyPart() {
|
||||
return keySide;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BasicValuedModelPart getTargetPart() {
|
||||
return targetSide;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MappingType getPartMappingType() {
|
||||
return targetSide.getMappedType();
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
*/
|
||||
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.engine.FetchStrategy;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
|
@ -16,14 +20,13 @@ import org.hibernate.mapping.ManyToOne;
|
|||
import org.hibernate.mapping.OneToOne;
|
||||
import org.hibernate.mapping.ToOne;
|
||||
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.EntityIdentifierMapping;
|
||||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
|
||||
import org.hibernate.metamodel.mapping.JdbcMapping;
|
||||
import org.hibernate.metamodel.mapping.ManagedMappingType;
|
||||
import org.hibernate.metamodel.mapping.MappingType;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
import org.hibernate.metamodel.mapping.PluralAttributeMapping;
|
||||
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.SqlAstCreationState;
|
||||
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.TableGroup;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupJoinProducer;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroupProducer;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.results.graph.DomainResult;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
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.embeddable.EmbeddableValuedFetchable;
|
||||
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.internal.domain.CircularBiDirectionalFetchImpl;
|
||||
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
|
||||
|
@ -85,9 +92,12 @@ public class ToOneAttributeMapping
|
|||
private final EntityMappingType entityMappingType;
|
||||
|
||||
private final String referencedPropertyName;
|
||||
private final String targetKeyPropertyName;
|
||||
private final Set<String> targetKeyPropertyNames;
|
||||
|
||||
private final Cardinality cardinality;
|
||||
private final String bidirectionalAttributeName;
|
||||
private final TableGroupProducer declaringTableGroupProducer;
|
||||
|
||||
private ForeignKeyDescriptor foreignKeyDescriptor;
|
||||
private String identifyingColumnsTableExpression;
|
||||
|
@ -102,6 +112,7 @@ public class ToOneAttributeMapping
|
|||
FetchStrategy mappedFetchStrategy,
|
||||
EntityMappingType entityMappingType,
|
||||
ManagedMappingType declaringType,
|
||||
EntityPersister declaringEntityPersister,
|
||||
PropertyAccess propertyAccess) {
|
||||
super(
|
||||
name,
|
||||
|
@ -192,6 +203,35 @@ public class ToOneAttributeMapping
|
|||
}
|
||||
|
||||
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) {
|
||||
|
@ -209,8 +249,33 @@ public class ToOneAttributeMapping
|
|||
this.unwrapProxy = original.unwrapProxy;
|
||||
this.entityMappingType = original.entityMappingType;
|
||||
this.referencedPropertyName = original.referencedPropertyName;
|
||||
this.targetKeyPropertyName = original.targetKeyPropertyName;
|
||||
this.targetKeyPropertyNames = original.targetKeyPropertyNames;
|
||||
this.cardinality = original.cardinality;
|
||||
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() {
|
||||
|
@ -233,10 +298,18 @@ public class ToOneAttributeMapping
|
|||
return this.foreignKeyDescriptor;
|
||||
}
|
||||
|
||||
public boolean canJoinForeignKey(EntityIdentifierMapping identifierMapping) {
|
||||
return isKeyReferringSide && identifierMapping == getForeignKeyDescriptor().getTargetPart();
|
||||
}
|
||||
|
||||
public String getReferencedPropertyName() {
|
||||
return referencedPropertyName;
|
||||
}
|
||||
|
||||
public String getTargetKeyPropertyName() {
|
||||
return targetKeyPropertyName;
|
||||
}
|
||||
|
||||
public Cardinality getCardinality() {
|
||||
return cardinality;
|
||||
}
|
||||
|
@ -256,6 +329,21 @@ public class ToOneAttributeMapping
|
|||
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
|
||||
public Fetch resolveCircularFetch(
|
||||
NavigablePath fetchablePath,
|
||||
|
@ -476,21 +564,23 @@ public class ToOneAttributeMapping
|
|||
assert parentNavigablePath.equals( fetchParent.getNavigablePath() );
|
||||
|
||||
if ( fetchTiming == FetchTiming.IMMEDIATE && selected ) {
|
||||
final TableGroup tableGroup;
|
||||
if ( fetchParent instanceof EntityResultJoinedSubclassImpl &&
|
||||
( (EntityPersister) fetchParent.getReferencedModePart() ).findDeclaredAttributeMapping( getPartName() ) == null ) {
|
||||
final TableGroup tableGroupJoin = createTableGroupJoin(
|
||||
tableGroup = createTableGroupJoin(
|
||||
fetchablePath,
|
||||
true,
|
||||
lockMode,
|
||||
creationState,
|
||||
parentTableGroup
|
||||
);
|
||||
fromClauseAccess.registerTableGroup( fetchablePath, tableGroupJoin );
|
||||
fromClauseAccess.registerTableGroup( fetchablePath, tableGroup );
|
||||
}
|
||||
else {
|
||||
fromClauseAccess.resolveTableGroup(
|
||||
tableGroup = fromClauseAccess.resolveTableGroup(
|
||||
fetchablePath,
|
||||
np ->
|
||||
createTableGroupJoin( fetchablePath, lockMode, creationState, parentTableGroup )
|
||||
createTableGroupJoin( fetchablePath, true, lockMode, creationState, parentTableGroup )
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -498,6 +588,7 @@ public class ToOneAttributeMapping
|
|||
return new EntityFetchJoinedImpl(
|
||||
fetchParent,
|
||||
this,
|
||||
tableGroup,
|
||||
lockMode,
|
||||
true,
|
||||
fetchablePath,
|
||||
|
@ -578,6 +669,7 @@ public class ToOneAttributeMapping
|
|||
tableGroup,
|
||||
null,
|
||||
tableGroup.isInnerJoinPossible() ? SqlAstJoinType.INNER : SqlAstJoinType.LEFT,
|
||||
true,
|
||||
null,
|
||||
creationState.getSqlAstCreationState()
|
||||
);
|
||||
|
@ -600,7 +692,7 @@ public class ToOneAttributeMapping
|
|||
return new EntityResultImpl(
|
||||
navigablePath,
|
||||
this,
|
||||
null,
|
||||
tableGroup, null,
|
||||
creationState
|
||||
);
|
||||
}
|
||||
|
@ -608,6 +700,7 @@ public class ToOneAttributeMapping
|
|||
|
||||
private TableGroup createTableGroupJoin(
|
||||
NavigablePath fetchablePath,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
DomainResultCreationState creationState,
|
||||
TableGroup parentTableGroup) {
|
||||
|
@ -628,6 +721,7 @@ public class ToOneAttributeMapping
|
|||
parentTableGroup,
|
||||
null,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
lockMode,
|
||||
creationState.getSqlAstCreationState()
|
||||
);
|
||||
|
@ -646,22 +740,101 @@ public class ToOneAttributeMapping
|
|||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
SqlAstCreationContext creationContext) {
|
||||
final String aliasRoot = explicitSourceAlias == null ? sqlAliasStem : explicitSourceAlias;
|
||||
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(
|
||||
sqlAliasBase,
|
||||
sqlExpressionResolver,
|
||||
creationContext
|
||||
);
|
||||
|
||||
final TableGroup tableGroup = new StandardTableGroup(
|
||||
return new StandardTableGroup(
|
||||
navigablePath,
|
||||
this,
|
||||
fetched,
|
||||
lockMode,
|
||||
primaryTableReference,
|
||||
false,
|
||||
|
@ -676,25 +849,6 @@ public class ToOneAttributeMapping
|
|||
),
|
||||
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
|
||||
|
|
|
@ -117,7 +117,7 @@ public class ColumnReference implements OrderingExpression, SequencePart {
|
|||
final int tableNumber = abstractEntityPersister.determineTableNumberForColumn( columnExpression );
|
||||
final String tableName = abstractEntityPersister.getTableName( tableNumber );
|
||||
|
||||
return tableGroup.getTableReference( tableName );
|
||||
return tableGroup.getTableReference( tableGroup.getNavigablePath(), tableName );
|
||||
}
|
||||
else {
|
||||
return tableGroup.getPrimaryTableReference();
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
|||
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
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.tree.domain.SqmPath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPluralValuedSimplePath;
|
||||
|
@ -128,14 +127,14 @@ public abstract class AbstractPluralAttribute<D,C,E>
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<E> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) {
|
||||
public SqmPath<E> createSqmPath(SqmPath<?> lhs) {
|
||||
final NavigablePath navigablePath = lhs.getNavigablePath().append( getPathName() );
|
||||
//noinspection unchecked
|
||||
return new SqmPluralValuedSimplePath(
|
||||
navigablePath,
|
||||
this,
|
||||
lhs,
|
||||
creationState.getCreationContext().getNodeBuilder()
|
||||
lhs.nodeBuilder()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,10 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.model.domain.internal;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.metamodel.model.domain.AnyMappingDomainType;
|
||||
import org.hibernate.metamodel.model.domain.BasicDomainType;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
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.SqmPath;
|
||||
|
||||
|
@ -20,7 +19,7 @@ import static javax.persistence.metamodel.Bindable.BindableType.SINGULAR_ATTRIBU
|
|||
* @author Steve Ebersole
|
||||
*/
|
||||
public class AnyMappingSqmPathSource<J> extends AbstractSqmPathSource<J> {
|
||||
private SqmPathSource<?> keyPathSource;
|
||||
private final SqmPathSource<?> keyPathSource;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public AnyMappingSqmPathSource(
|
||||
|
@ -47,13 +46,9 @@ public class AnyMappingSqmPathSource<J> extends AbstractSqmPathSource<J> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) {
|
||||
return new SqmAnyValuedSimplePath<>(
|
||||
lhs.getNavigablePath().append( getPathName() ),
|
||||
this,
|
||||
lhs,
|
||||
creationState.getCreationContext().getQueryEngine().getCriteriaBuilder()
|
||||
);
|
||||
public SqmPath<J> createSqmPath(SqmPath<?> lhs) {
|
||||
final NavigablePath navigablePath = lhs.getNavigablePath().append( getPathName() );
|
||||
return new SqmAnyValuedSimplePath( navigablePath, this, lhs, lhs.nodeBuilder() );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,7 +12,6 @@ import org.hibernate.metamodel.model.domain.BasicDomainType;
|
|||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.sqm.IllegalPathUsageException;
|
||||
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.SqmPath;
|
||||
|
||||
|
@ -42,13 +41,13 @@ public class BasicSqmPathSource<J>
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) {
|
||||
public SqmPath<J> createSqmPath(SqmPath<?> lhs) {
|
||||
final NavigablePath navigablePath = lhs.getNavigablePath().append( getPathName() );
|
||||
return new SqmBasicValuedSimplePath<>(
|
||||
navigablePath,
|
||||
this,
|
||||
lhs,
|
||||
creationState.getCreationContext().getNodeBuilder()
|
||||
lhs.nodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.metamodel.model.domain.internal;
|
|||
import org.hibernate.metamodel.model.domain.AllowableParameterType;
|
||||
import org.hibernate.metamodel.model.domain.EmbeddableDomainType;
|
||||
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.SqmPath;
|
||||
|
||||
|
@ -49,12 +48,12 @@ public class EmbeddedSqmPathSource<J>
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) {
|
||||
public SqmPath<J> createSqmPath(SqmPath<?> lhs) {
|
||||
return new SqmEmbeddedValuedSimplePath<>(
|
||||
lhs.getNavigablePath().append( getPathName() ),
|
||||
this,
|
||||
lhs,
|
||||
creationState.getCreationContext().getNodeBuilder()
|
||||
lhs.nodeBuilder()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.metamodel.model.domain.internal;
|
||||
|
||||
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.tree.domain.SqmEntityValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
|
@ -36,12 +35,12 @@ public class EntitySqmPathSource<J> extends AbstractSqmPathSource<J> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) {
|
||||
public SqmPath<J> createSqmPath(SqmPath<?> lhs) {
|
||||
return new SqmEntityValuedSimplePath<>(
|
||||
lhs.getNavigablePath().append( getPathName() ),
|
||||
this,
|
||||
lhs,
|
||||
creationState.getCreationContext().getNodeBuilder()
|
||||
lhs.nodeBuilder()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,6 @@ import org.hibernate.metamodel.model.domain.IdentifiableDomainType;
|
|||
import org.hibernate.metamodel.model.domain.JpaMetamodel;
|
||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||
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.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmBasicValuedSimplePath;
|
||||
|
@ -86,12 +85,12 @@ public class EntityTypeImpl<J>
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<?> createSqmPath(SqmPath lhs, SqmCreationState creationState) {
|
||||
public SqmPath<?> createSqmPath(SqmPath lhs) {
|
||||
return new SqmBasicValuedSimplePath(
|
||||
lhs.getNavigablePath().append( EntityDiscriminatorMapping.ROLE_NAME ),
|
||||
this,
|
||||
lhs,
|
||||
creationState.getCreationContext().getNodeBuilder()
|
||||
lhs.nodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -223,8 +222,7 @@ public class EntityTypeImpl<J>
|
|||
|
||||
@Override
|
||||
public SqmPath<J> createSqmPath(
|
||||
SqmPath<?> lhs,
|
||||
SqmCreationState creationState) {
|
||||
SqmPath<?> lhs) {
|
||||
throw new UnsupportedOperationException(
|
||||
"EntityType cannot be used to create an SqmPath - that would be an SqmFrom which are created directly"
|
||||
);
|
||||
|
|
|
@ -6,13 +6,10 @@
|
|||
*/
|
||||
package org.hibernate.metamodel.model.domain.internal;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
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.SqmPathSource;
|
||||
import org.hibernate.query.sqm.tree.domain.NonAggregatedCompositeSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmEmbeddedValuedSimplePath;
|
||||
import org.hibernate.query.sqm.tree.domain.SqmPath;
|
||||
|
||||
/**
|
||||
|
@ -39,12 +36,12 @@ public class NonAggregatedCompositeSqmPathSource extends AbstractSqmPathSource i
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) {
|
||||
public SqmPath createSqmPath(SqmPath lhs) {
|
||||
return new NonAggregatedCompositeSimplePath(
|
||||
lhs.getNavigablePath().append( getPathName() ),
|
||||
this,
|
||||
lhs,
|
||||
creationState.getCreationContext().getNodeBuilder()
|
||||
lhs.nodeBuilder()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -221,10 +221,8 @@ public class SingularAttributeImpl<D,J>
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<J> createSqmPath(
|
||||
SqmPath lhs,
|
||||
SqmCreationState creationState) {
|
||||
return sqmPathSource.createSqmPath( lhs, creationState );
|
||||
public SqmPath<J> createSqmPath(SqmPath lhs) {
|
||||
return sqmPathSource.createSqmPath( lhs );
|
||||
}
|
||||
|
||||
private class DelayedKeyTypeAccess implements Supplier<SimpleDomainType<J>>, Serializable {
|
||||
|
|
|
@ -1950,7 +1950,7 @@ public abstract class AbstractCollectionPersister
|
|||
tableReference = tableGroup.getPrimaryTableReference();
|
||||
}
|
||||
else if ( elementPersister instanceof Joinable ) {
|
||||
tableReference = tableGroup.getTableReference( ( (Joinable) elementPersister ).getTableName() );
|
||||
tableReference = tableGroup.getTableReference( tableGroup.getNavigablePath(), ( (Joinable) elementPersister ).getTableName() );
|
||||
}
|
||||
|
||||
if ( tableReference != null ) {
|
||||
|
|
|
@ -1267,7 +1267,7 @@ public abstract class AbstractEntityPersister
|
|||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
//noinspection unchecked
|
||||
return new EntityResultImpl( navigablePath, this, resultVariable, creationState );
|
||||
return new EntityResultImpl( navigablePath, this, tableGroup, resultVariable, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -6613,6 +6613,7 @@ public abstract class AbstractEntityPersister
|
|||
stateArrayPosition,
|
||||
bootProperty,
|
||||
this,
|
||||
this,
|
||||
(EntityType) attrType,
|
||||
propertyAccess,
|
||||
tupleAttrDefinition.getCascadeStyle(),
|
||||
|
|
|
@ -1294,7 +1294,7 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
DomainResultCreationState creationState) {
|
||||
if ( hasSubclasses() ) {
|
||||
//noinspection unchecked
|
||||
return new EntityResultJoinedSubclassImpl( navigablePath, this, resultVariable, creationState );
|
||||
return new EntityResultJoinedSubclassImpl( navigablePath, this, tableGroup, resultVariable, creationState );
|
||||
}
|
||||
else {
|
||||
return super.createDomainResult( navigablePath, tableGroup, resultVariable, creationState );
|
||||
|
@ -1358,11 +1358,11 @@ public class JoinedSubclassEntityPersister extends AbstractEntityPersister {
|
|||
boolean addPrimaryTableCaseAsLastCaseExpression = false;
|
||||
for ( String tableName : discriminatorValuesByTableName.keySet() ) {
|
||||
if ( !primaryTableReference.getTableExpression().equals( tableName ) ) {
|
||||
TableReference tableReference = entityTableGroup.getTableReference( tableName );
|
||||
TableReference tableReference = entityTableGroup.getTableReference( entityTableGroup.getNavigablePath(), tableName );
|
||||
if ( tableReference == null ) {
|
||||
// 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
|
||||
tableReference = entityTableGroup.resolveTableReference( tableName );
|
||||
tableReference = entityTableGroup.resolveTableReference( entityTableGroup.getNavigablePath(), tableName );
|
||||
}
|
||||
|
||||
final ColumnReference identifierColumnReference = getIdentifierColumnReference( tableReference );
|
||||
|
|
|
@ -51,9 +51,11 @@ import org.hibernate.sql.ast.spi.SqlAstCreationContext;
|
|||
import org.hibernate.sql.ast.spi.SqlAstCreationState;
|
||||
import org.hibernate.sql.ast.spi.SqlExpressionResolver;
|
||||
import org.hibernate.sql.ast.tree.expression.ColumnReference;
|
||||
import org.hibernate.sql.ast.tree.expression.Expression;
|
||||
import org.hibernate.sql.ast.tree.expression.QueryLiteral;
|
||||
import org.hibernate.sql.ast.tree.from.TableGroup;
|
||||
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.type.AssociationType;
|
||||
import org.hibernate.type.BasicType;
|
||||
|
@ -636,7 +638,7 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
frag.addValues( decodeTreatAsRequests( treatAsDeclarations ) );
|
||||
}
|
||||
else {
|
||||
frag.addValues( fullDiscriminatorValues() );
|
||||
frag.addValues( fullDiscriminatorSQLValues() );
|
||||
}
|
||||
|
||||
return frag.toFragmentString();
|
||||
|
@ -672,10 +674,11 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
return ArrayHelper.toStringArray( values );
|
||||
}
|
||||
|
||||
private String[] fullDiscriminatorValues;
|
||||
private String[] fullDiscriminatorSQLValues;
|
||||
|
||||
private String[] fullDiscriminatorValues() {
|
||||
if ( fullDiscriminatorValues == null ) {
|
||||
private String[] fullDiscriminatorSQLValues() {
|
||||
String[] fullDiscriminatorSQLValues = this.fullDiscriminatorSQLValues;
|
||||
if ( fullDiscriminatorSQLValues == null ) {
|
||||
// first access; build it
|
||||
final List<String> values = new ArrayList<>();
|
||||
for ( String subclass : getSubclassClosure() ) {
|
||||
|
@ -684,7 +687,26 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
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;
|
||||
|
@ -946,8 +968,9 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
getDiscriminatorColumnName()
|
||||
);
|
||||
}
|
||||
return new ComparisonPredicate(
|
||||
sqlExpressionResolver.resolveSqlExpression(
|
||||
|
||||
final BasicType<?> discriminatorType = (BasicType<?>) getDiscriminatorType();
|
||||
final Expression sqlExpression = sqlExpressionResolver.resolveSqlExpression(
|
||||
columnReferenceKey,
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
tableGroup.getPrimaryTableReference().getIdentificationVariable(),
|
||||
|
@ -955,14 +978,24 @@ public class SingleTableEntityPersister extends AbstractEntityPersister {
|
|||
isDiscriminatorFormula(),
|
||||
null,
|
||||
null,
|
||||
( (BasicType<?>) getDiscriminatorType() ).getJdbcMapping(),
|
||||
(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(
|
||||
sqlExpression,
|
||||
ComparisonOperator.EQUAL,
|
||||
new QueryLiteral<>(
|
||||
getDiscriminatorValue(),
|
||||
( (BasicType<?>) getDiscriminatorType() )
|
||||
discriminatorType
|
||||
)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -139,20 +139,12 @@ public class BasicDotIdentifierConsumer implements DotIdentifierConsumer {
|
|||
}
|
||||
}
|
||||
|
||||
final SqmFrom pathRootByExposedNavigable = sqmPathRegistry.findFromExposing( identifier );
|
||||
final SqmFrom<?, ?> pathRootByExposedNavigable = sqmPathRegistry.findFromExposing( identifier );
|
||||
if ( pathRootByExposedNavigable != null ) {
|
||||
// identifier is an "unqualified attribute reference"
|
||||
validateAsRoot( pathRootByExposedNavigable );
|
||||
|
||||
SqmPath sqmPath = pathRootByExposedNavigable.getImplicitJoinPath( identifier );
|
||||
if ( sqmPath == null ) {
|
||||
final SqmPathSource subPathSource = pathRootByExposedNavigable.getReferencedPathSource()
|
||||
.findSubPathSource( identifier );
|
||||
sqmPath = subPathSource.createSqmPath( pathRootByExposedNavigable, creationState );
|
||||
if ( !isTerminal ) {
|
||||
pathRootByExposedNavigable.registerImplicitJoinPath( sqmPath );
|
||||
}
|
||||
}
|
||||
SqmPath<?> sqmPath = (SqmPath<?>) pathRootByExposedNavigable.get( identifier );
|
||||
if ( isTerminal ) {
|
||||
return sqmPath;
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
package org.hibernate.query.hql.internal;
|
||||
|
||||
import org.hibernate.NotYetImplementedFor6Exception;
|
||||
import org.hibernate.query.SemanticException;
|
||||
import org.hibernate.query.hql.HqlLogging;
|
||||
import org.hibernate.query.hql.spi.SemanticPathPart;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
|
@ -43,18 +42,6 @@ public class DomainPathPart implements SemanticPathPart {
|
|||
currentPath,
|
||||
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
|
||||
//
|
||||
// final SqmPathRegistry pathRegistry = creationState.getCurrentProcessingState().getPathRegistry();
|
||||
|
@ -70,13 +57,11 @@ public class DomainPathPart implements SemanticPathPart {
|
|||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
currentPath = subPathSource.createSqmPath( lhs, creationState );
|
||||
currentPath = (SqmPath<?>) currentPath.get( name );
|
||||
if ( isTerminal ) {
|
||||
return currentPath;
|
||||
}
|
||||
else {
|
||||
lhs.registerImplicitJoinPath( currentPath );
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1925,8 +1925,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
if ( sqmPathType instanceof IdentifiableDomainType ) {
|
||||
//noinspection unchecked
|
||||
final SqmPath idPath = ( (IdentifiableDomainType) sqmPathType ).getIdentifierDescriptor().createSqmPath(
|
||||
sqmPath,
|
||||
this
|
||||
sqmPath
|
||||
);
|
||||
|
||||
if ( ctx.pathContinuation() == null ) {
|
||||
|
@ -1960,7 +1959,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
}
|
||||
|
||||
//noinspection unchecked
|
||||
return versionAttribute.createSqmPath( sqmPath, this );
|
||||
return versionAttribute.createSqmPath( sqmPath );
|
||||
}
|
||||
|
||||
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
|
||||
return ( (PluralPersistentAttribute<?, ?, ?>) pluralAttribute ).getIndexPathSource().createSqmPath(
|
||||
sqmFrom,
|
||||
this
|
||||
sqmFrom
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -4143,8 +4141,7 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
//noinspection unchecked
|
||||
SqmPath result = attribute.getElementPathSource().createSqmPath(
|
||||
pluralAttributePath,
|
||||
this
|
||||
pluralAttributePath
|
||||
);
|
||||
|
||||
if ( ctx.pathContinuation() != null ) {
|
||||
|
@ -4162,15 +4159,15 @@ public class SemanticQueryBuilder<R> extends HqlParserBaseVisitor<Object> implem
|
|||
|
||||
if ( sqmPath instanceof SqmMapJoin ) {
|
||||
final SqmMapJoin sqmMapJoin = (SqmMapJoin) sqmPath;
|
||||
return sqmMapJoin.getReferencedPathSource().getIndexPathSource().createSqmPath( sqmMapJoin, this );
|
||||
return sqmMapJoin.getReferencedPathSource().getIndexPathSource().createSqmPath( sqmMapJoin );
|
||||
}
|
||||
else {
|
||||
assert sqmPath instanceof SqmPluralValuedSimplePath;
|
||||
final SqmPluralValuedSimplePath mapPath = (SqmPluralValuedSimplePath) sqmPath;
|
||||
final SqmPath keyPath = mapPath.getReferencedPathSource()
|
||||
.getIndexPathSource()
|
||||
.createSqmPath( mapPath, this );
|
||||
mapPath.registerImplicitJoinPath( keyPath );
|
||||
.createSqmPath( mapPath );
|
||||
mapPath.registerReusablePath( keyPath );
|
||||
return keyPath;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,8 +29,6 @@ import org.hibernate.query.spi.QueryParameterBindings;
|
|||
import org.hibernate.query.spi.QueryParameterImplementor;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
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;
|
||||
|
||||
/**
|
||||
|
@ -94,7 +92,7 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"WeakerAccess" })
|
||||
protected QueryParameterBinding<?> makeBinding(QueryParameterImplementor<?> queryParameter) {
|
||||
protected <T> QueryParameterBinding<T> makeBinding(QueryParameterImplementor<T> queryParameter) {
|
||||
if ( parameterBindingMap == null ) {
|
||||
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 );
|
||||
|
||||
return binding;
|
||||
|
@ -122,8 +120,7 @@ public class QueryParameterBindingsImpl implements QueryParameterBindings {
|
|||
@Override
|
||||
public <P> QueryParameterBinding<P> getBinding(QueryParameterImplementor<P> parameter) {
|
||||
if ( parameterBindingMap == null ) {
|
||||
//noinspection unchecked
|
||||
return (QueryParameterBinding<P>) makeBinding( parameter );
|
||||
return makeBinding( parameter );
|
||||
}
|
||||
|
||||
QueryParameterBinding<?> binding = parameterBindingMap.get( parameter );
|
||||
|
|
|
@ -315,7 +315,7 @@ public class DomainResultCreationStateImpl
|
|||
|
||||
final Consumer<Fetchable> fetchableConsumer = fetchable -> {
|
||||
final String fetchableName = fetchable.getFetchableName();
|
||||
final NavigablePath fetchPath = fetchParent.getNavigablePath().append( fetchableName );
|
||||
final NavigablePath fetchPath = fetchParent.resolveNavigablePath( fetchable );
|
||||
final NavigablePath relativePath = relativePathStack.isEmpty()
|
||||
? new NavigablePath( fetchableName )
|
||||
: relativePathStack.getCurrent().append( fetchableName );
|
||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.query.results;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
|
@ -113,18 +112,12 @@ public class TableGroupImpl implements TableGroup {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(
|
||||
String tableExpression, Supplier<TableReference> creator) {
|
||||
public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
return primaryTableReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression) {
|
||||
return primaryTableReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(String tableExpression) {
|
||||
public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
return primaryTableReference;
|
||||
}
|
||||
|
||||
|
|
|
@ -68,7 +68,7 @@ public class CompleteFetchBuilderBasicPart implements CompleteFetchBuilder, Mode
|
|||
final String mappedColumn = referencedModelPart.getSelectionExpression();
|
||||
|
||||
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 int jdbcPosition;
|
||||
|
|
|
@ -62,7 +62,7 @@ public class CompleteResultBuilderBasicModelPart
|
|||
final DomainResultCreationStateImpl creationStateImpl = impl( domainResultCreationState );
|
||||
|
||||
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 int jdbcPosition = jdbcResultsMetadata.resolveColumnPosition( columnAlias );
|
||||
|
|
|
@ -59,7 +59,7 @@ public class ImplicitFetchBuilderBasic implements ImplicitFetchBuilder {
|
|||
final int valuesArrayPosition = jdbcPositionToValuesArrayPosition( jdbcPosition );
|
||||
|
||||
final Expression expression = creationStateImpl.resolveSqlExpression(
|
||||
createColumnReferenceKey( parentTableGroup.getTableReference( table ), column ),
|
||||
createColumnReferenceKey( parentTableGroup.getTableReference( fetchPath, table ), column ),
|
||||
processingState -> new SqlSelectionImpl( valuesArrayPosition, fetchable )
|
||||
);
|
||||
|
||||
|
|
|
@ -17,13 +17,10 @@ import org.hibernate.query.NavigablePath;
|
|||
import org.hibernate.query.results.Builders;
|
||||
import org.hibernate.query.results.DomainResultCreationStateImpl;
|
||||
import org.hibernate.query.results.FetchBuilder;
|
||||
import org.hibernate.query.results.SqlSelectionImpl;
|
||||
import org.hibernate.query.results.dynamic.DynamicFetchBuilderLegacy;
|
||||
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.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
import org.hibernate.sql.results.graph.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.Fetch;
|
||||
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 static org.hibernate.query.results.ResultsHelper.impl;
|
||||
import static org.hibernate.query.results.ResultsHelper.jdbcPositionToValuesArrayPosition;
|
||||
import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey;
|
||||
|
||||
/**
|
||||
|
@ -92,6 +88,7 @@ public class ImplicitFetchBuilderEmbeddable implements ImplicitFetchBuilder {
|
|||
parentTableGroup,
|
||||
null,
|
||||
SqlAstJoinType.INNER,
|
||||
true,
|
||||
LockMode.READ,
|
||||
creationStateImpl
|
||||
);
|
||||
|
|
|
@ -65,6 +65,7 @@ public class ImplicitModelPartResultBuilderEmbeddable
|
|||
parentTableGroup,
|
||||
null,
|
||||
SqlAstJoinType.INNER,
|
||||
true,
|
||||
LockMode.READ,
|
||||
creationStateImpl
|
||||
);
|
||||
|
|
|
@ -720,7 +720,7 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
|||
@SuppressWarnings( {"unchecked", "rawtypes"} )
|
||||
public Set<Parameter<?>> getParameters() {
|
||||
getSession().checkOpen( false );
|
||||
return (Set) ( (ParameterMetadata) getParameterMetadata() ).getRegistrations();
|
||||
return (Set) getParameterMetadata().getRegistrations();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -821,16 +821,16 @@ public abstract class AbstractQuery<R> implements QueryImplementor<R> {
|
|||
return getQueryParameterBindings().getBinding( parameter );
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"WeakerAccess", "unchecked"} )
|
||||
@SuppressWarnings( {"WeakerAccess"} )
|
||||
protected <P> QueryParameterBinding<P> locateBinding(String name) {
|
||||
getSession().checkOpen();
|
||||
return (QueryParameterBinding<P>) getQueryParameterBindings().getBinding( name );
|
||||
return getQueryParameterBindings().getBinding( name );
|
||||
}
|
||||
|
||||
@SuppressWarnings( {"WeakerAccess", "unchecked"} )
|
||||
@SuppressWarnings( {"WeakerAccess"} )
|
||||
protected <P> QueryParameterBinding<P> locateBinding(int position) {
|
||||
getSession().checkOpen();
|
||||
return (QueryParameterBinding<P>) getQueryParameterBindings().getBinding( position );
|
||||
return getQueryParameterBindings().getBinding( position );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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
|
||||
*/
|
||||
SqmPath<J> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState);
|
||||
SqmPath<J> createSqmPath(SqmPath<?> lhs);
|
||||
|
||||
default <X extends DomainType> X sqmAs(Class<X> targetType) {
|
||||
if ( targetType.isInstance( this ) ) {
|
||||
|
|
|
@ -231,7 +231,9 @@ public class QuerySqmImpl<R>
|
|||
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
|
||||
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() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,10 @@ public class MatchingIdSelectionHelper {
|
|||
|
||||
targetEntityDescriptor.getIdentifierMapping().forEachSelectable(
|
||||
(position, selection) -> {
|
||||
final TableReference tableReference = mutatingTableGroup.resolveTableReference( selection.getContainingTableExpression() );
|
||||
final TableReference tableReference = mutatingTableGroup.resolveTableReference(
|
||||
mutatingTableGroup.getNavigablePath(),
|
||||
selection.getContainingTableExpression()
|
||||
);
|
||||
final Expression expression = sqmConverter.getSqlExpressionResolver().resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey( tableReference, selection.getSelectionExpression() ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
|
@ -153,7 +156,10 @@ public class MatchingIdSelectionHelper {
|
|||
|
||||
targetEntityDescriptor.getIdentifierMapping().forEachSelectable(
|
||||
(position, selection) -> {
|
||||
final TableReference tableReference = mutatingTableGroup.resolveTableReference( selection.getContainingTableExpression() );
|
||||
final TableReference tableReference = mutatingTableGroup.resolveTableReference(
|
||||
mutatingTableGroup.getNavigablePath(),
|
||||
selection.getContainingTableExpression()
|
||||
);
|
||||
final Expression expression = sqmConverter.getSqlExpressionResolver().resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey( tableReference, selection.getSelectionExpression() ),
|
||||
sqlAstProcessingState -> new ColumnReference(
|
||||
|
|
|
@ -101,7 +101,10 @@ public class CteDeleteHandler extends AbstractCteMutationHandler implements Dele
|
|||
idSelectCte.getCteTable().getCteColumns(),
|
||||
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() );
|
||||
tableColumnsVisitationSupplier.get().accept(
|
||||
(index, selectable) -> columnReferences.add(
|
||||
|
|
|
@ -69,7 +69,10 @@ public class CteUpdateHandler extends AbstractCteMutationHandler implements Upda
|
|||
final EntityPersister rootEntityDescriptor = factory.getDomainModel().getEntityDescriptor( rootEntityName );
|
||||
|
||||
final String hierarchyRootTableName = ( (Joinable) rootEntityDescriptor ).getTableName();
|
||||
final TableReference hierarchyRootTableReference = updatingTableGroup.resolveTableReference( hierarchyRootTableName );
|
||||
final TableReference hierarchyRootTableReference = updatingTableGroup.resolveTableReference(
|
||||
updatingTableGroup.getNavigablePath(),
|
||||
hierarchyRootTableName
|
||||
);
|
||||
assert hierarchyRootTableReference != null;
|
||||
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -144,7 +147,10 @@ public class CteUpdateHandler extends AbstractCteMutationHandler implements Upda
|
|||
if ( assignmentList == null ) {
|
||||
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() );
|
||||
tableColumnsVisitationSupplier.get().accept(
|
||||
(index, selectable) -> columnReferences.add(
|
||||
|
|
|
@ -87,7 +87,10 @@ public final class ExecuteWithIdTableHelper {
|
|||
|
||||
mutatingEntityDescriptor.getIdentifierMapping().forEachSelectable(
|
||||
(jdbcPosition, selection) -> {
|
||||
final TableReference tableReference = mutatingTableGroup.resolveTableReference( selection.getContainingTableExpression() );
|
||||
final TableReference tableReference = mutatingTableGroup.resolveTableReference(
|
||||
mutatingTableGroup.getNavigablePath(),
|
||||
selection.getContainingTableExpression()
|
||||
);
|
||||
matchingIdSelection.getSelectClause().addSqlSelection(
|
||||
new SqlSelectionImpl(
|
||||
jdbcPosition,
|
||||
|
|
|
@ -124,7 +124,10 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle
|
|||
|
||||
final TableGroup deletingTableGroup = converter.getMutatingTableGroup();
|
||||
|
||||
final TableReference hierarchyRootTableReference = deletingTableGroup.resolveTableReference( hierarchyRootTableName );
|
||||
final TableReference hierarchyRootTableReference = deletingTableGroup.resolveTableReference(
|
||||
deletingTableGroup.getNavigablePath(),
|
||||
hierarchyRootTableName
|
||||
);
|
||||
assert hierarchyRootTableReference != null;
|
||||
|
||||
final Map<SqmParameter, List<List<JdbcParameter>>> parameterResolutions;
|
||||
|
@ -213,7 +216,10 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle
|
|||
final MutableInteger rows = new MutableInteger();
|
||||
|
||||
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(
|
||||
tableGroup.getNavigablePath(),
|
||||
|
@ -251,7 +257,7 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle
|
|||
}
|
||||
else {
|
||||
deleteFromNonRootTableWithoutIdTable(
|
||||
tableGroup.resolveTableReference( tableExpression ),
|
||||
tableGroup.resolveTableReference( tableGroup.getNavigablePath(), tableExpression ),
|
||||
tableKeyColumnVisitationSupplier,
|
||||
sqlExpressionResolver,
|
||||
tableGroup,
|
||||
|
|
|
@ -133,7 +133,10 @@ public class TableBasedUpdateHandler
|
|||
|
||||
final TableGroup updatingTableGroup = converterDelegate.getMutatingTableGroup();
|
||||
|
||||
final TableReference hierarchyRootTableReference = updatingTableGroup.resolveTableReference( hierarchyRootTableName );
|
||||
final TableReference hierarchyRootTableReference = updatingTableGroup.resolveTableReference(
|
||||
updatingTableGroup.getNavigablePath(),
|
||||
hierarchyRootTableName
|
||||
);
|
||||
assert hierarchyRootTableReference != null;
|
||||
|
||||
final Map<SqmParameter, List<List<JdbcParameter>>> parameterResolutions;
|
||||
|
|
|
@ -211,7 +211,10 @@ public class UpdateExecutionDelegate implements TableBasedUpdateHandler.Executio
|
|||
return tableReferenceByQualifier;
|
||||
}
|
||||
|
||||
final TableReference tableReferenceByName = updatingTableGroup.resolveTableReference( columnReference.getQualifier() );
|
||||
final TableReference tableReferenceByName = updatingTableGroup.resolveTableReference(
|
||||
updatingTableGroup.getNavigablePath(),
|
||||
columnReference.getQualifier()
|
||||
);
|
||||
if ( tableReferenceByName != null ) {
|
||||
return tableReferenceByName;
|
||||
}
|
||||
|
@ -224,7 +227,7 @@ public class UpdateExecutionDelegate implements TableBasedUpdateHandler.Executio
|
|||
Supplier<Consumer<SelectableConsumer>> tableKeyColumnVisitationSupplier,
|
||||
QuerySpec idTableSubQuery,
|
||||
ExecutionContext executionContext) {
|
||||
final TableReference updatingTableReference = updatingTableGroup.resolveTableReference( tableExpression );
|
||||
final TableReference updatingTableReference = updatingTableGroup.resolveTableReference( updatingTableGroup.getNavigablePath(), tableExpression );
|
||||
|
||||
final List<Assignment> assignments = assignmentsByTable.get( updatingTableReference );
|
||||
if ( assignments == null || assignments.isEmpty() ) {
|
||||
|
|
|
@ -646,11 +646,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
|
||||
private void applyManipulationImplicitJoins(SqmPath<?> sqmPath, TableGroup correspondingTableGroup) {
|
||||
consumeImplicitJoins(
|
||||
sqmPath,
|
||||
correspondingTableGroup,
|
||||
BaseSqmToSqlAstConverter::verifyManipulationImplicitJoin
|
||||
);
|
||||
consumeReusablePaths( sqmPath, correspondingTableGroup, BaseSqmToSqlAstConverter::verifyManipulationImplicitJoin );
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
consumeExplicitJoins( sqmRoot, tableGroup );
|
||||
consumeImplicitJoins( sqmRoot, tableGroup );
|
||||
consumeReusablePaths( sqmRoot, tableGroup );
|
||||
return;
|
||||
}
|
||||
else {
|
||||
|
@ -1786,6 +1782,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
creationContext
|
||||
);
|
||||
final EntityIdentifierMapping identifierMapping = entityDescriptor.getIdentifierMapping();
|
||||
final NavigablePath navigablePath = sqmRoot.getNavigablePath().append( identifierMapping.getNavigableRole().getNavigableName() );
|
||||
final int jdbcTypeCount = identifierMapping.getJdbcTypeCount();
|
||||
if ( jdbcTypeCount == 1 ) {
|
||||
identifierMapping.forEachSelectable(
|
||||
|
@ -1793,13 +1790,13 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
additionalRestrictions,
|
||||
new ComparisonPredicate(
|
||||
new ColumnReference(
|
||||
parentTableGroup.getTableReference( selectable.getContainingTableExpression() ),
|
||||
parentTableGroup.getTableReference( navigablePath, selectable.getContainingTableExpression() ),
|
||||
selectable,
|
||||
sessionFactory
|
||||
),
|
||||
ComparisonOperator.EQUAL,
|
||||
new ColumnReference(
|
||||
tableGroup.getTableReference( selectable.getContainingTableExpression() ),
|
||||
tableGroup.getTableReference( navigablePath, selectable.getContainingTableExpression() ),
|
||||
selectable,
|
||||
sessionFactory
|
||||
)
|
||||
|
@ -1814,14 +1811,14 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
(index, selectable) -> {
|
||||
lhs.add(
|
||||
new ColumnReference(
|
||||
parentTableGroup.getTableReference( selectable.getContainingTableExpression() ),
|
||||
parentTableGroup.getTableReference( navigablePath, selectable.getContainingTableExpression() ),
|
||||
selectable,
|
||||
sessionFactory
|
||||
)
|
||||
);
|
||||
rhs.add(
|
||||
new ColumnReference(
|
||||
tableGroup.getTableReference( selectable.getContainingTableExpression() ),
|
||||
tableGroup.getTableReference( navigablePath, selectable.getContainingTableExpression() ),
|
||||
selectable,
|
||||
sessionFactory
|
||||
)
|
||||
|
@ -1860,7 +1857,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
currentQuerySpec().getFromClause().addRoot( tableGroup );
|
||||
|
||||
consumeExplicitJoins( sqmRoot, tableGroup );
|
||||
consumeImplicitJoins( sqmRoot, tableGroup );
|
||||
consumeReusablePaths( sqmRoot, tableGroup );
|
||||
}
|
||||
|
||||
private EntityPersister resolveEntityPersister(EntityDomainType<?> entityDomainType) {
|
||||
|
@ -1929,6 +1926,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
lhsTableGroup,
|
||||
sqmJoin.getExplicitAlias(),
|
||||
sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(),
|
||||
sqmJoin.isFetched(),
|
||||
determineLockMode( sqmJoin.getExplicitAlias() ),
|
||||
this
|
||||
);
|
||||
|
@ -1943,6 +1941,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
lhsTableGroup,
|
||||
sqmJoin.getExplicitAlias(),
|
||||
sqmJoin.getSqmJoinType().getCorrespondingSqlJoinType(),
|
||||
sqmJoin.isFetched(),
|
||||
determineLockMode( sqmJoin.getExplicitAlias() ),
|
||||
this
|
||||
);
|
||||
|
@ -1969,7 +1968,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
}
|
||||
|
||||
consumeExplicitJoins( sqmJoin, joinedTableGroup );
|
||||
consumeImplicitJoins( sqmJoin, joinedTableGroup );
|
||||
consumeReusablePaths( sqmJoin, joinedTableGroup );
|
||||
}
|
||||
|
||||
private NavigablePath getJoinNavigablePath(
|
||||
|
@ -2015,7 +2014,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
getFromClauseIndex().register( sqmJoin, tableGroup );
|
||||
|
||||
consumeExplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() );
|
||||
consumeImplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() );
|
||||
consumeReusablePaths( sqmJoin, tableGroupJoin.getJoinedGroup() );
|
||||
}
|
||||
|
||||
private void consumeEntityJoin(SqmEntityJoin sqmJoin, TableGroup lhsTableGroup) {
|
||||
|
@ -2043,7 +2042,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
lhsTableGroup.addTableGroupJoin( tableGroupJoin );
|
||||
|
||||
consumeExplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() );
|
||||
consumeImplicitJoins( sqmJoin, tableGroupJoin.getJoinedGroup() );
|
||||
consumeReusablePaths( sqmJoin, tableGroupJoin.getJoinedGroup() );
|
||||
|
||||
// add any additional join restrictions
|
||||
if ( sqmJoin.getJoinPredicate() != null ) {
|
||||
|
@ -2054,58 +2053,58 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
|
||||
}
|
||||
|
||||
private void consumeImplicitJoins(SqmPath<?> sqmPath, TableGroup tableGroup) {
|
||||
consumeImplicitJoins(
|
||||
sqmPath,
|
||||
tableGroup,
|
||||
(sqmSubPath) -> {}
|
||||
);
|
||||
private void consumeReusablePaths(SqmPath<?> sqmPath, TableGroup tableGroup) {
|
||||
consumeReusablePaths( sqmPath, tableGroup, (sqmSubPath) -> {} );
|
||||
}
|
||||
|
||||
private void consumeImplicitJoins(
|
||||
private void consumeReusablePaths(
|
||||
SqmPath<?> sqmPath,
|
||||
TableGroup tableGroup,
|
||||
TableGroup parentTableGroup,
|
||||
Consumer<SqmPath<?>> implicitJoinChecker) {
|
||||
if ( log.isTraceEnabled() ) {
|
||||
log.tracef( "Visiting implicit joins for `%s`", sqmPath.getNavigablePath() );
|
||||
}
|
||||
|
||||
sqmPath.visitImplicitJoinPaths(
|
||||
sqmPath.visitReusablePaths(
|
||||
joinedPath -> {
|
||||
if ( log.isTraceEnabled() ) {
|
||||
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();
|
||||
assert fromClauseIndex.findTableGroup( joinedPath.getLhs().getNavigablePath() ) == tableGroup;
|
||||
|
||||
final ModelPart subPart = tableGroup.getModelPart().findSubPart(
|
||||
final ModelPart subPart = parentTableGroup.getModelPart().findSubPart(
|
||||
joinedPath.getReferencedPathSource().getPathName(),
|
||||
sqmPath instanceof SqmTreatedPath
|
||||
? resolveEntityPersister( ( (SqmTreatedPath) sqmPath ).getTreatTarget() )
|
||||
lhsPath instanceof SqmTreatedPath
|
||||
? resolveEntityPersister( ( (SqmTreatedPath<?, ?>) lhsPath ).getTreatTarget() )
|
||||
: null
|
||||
);
|
||||
|
||||
final TableGroup tableGroup;
|
||||
if ( subPart instanceof TableGroupJoinProducer ) {
|
||||
implicitJoinChecker.accept( joinedPath );
|
||||
final TableGroupJoinProducer joinProducer = (TableGroupJoinProducer) subPart;
|
||||
final TableGroupJoin tableGroupJoin = joinProducer.createTableGroupJoin(
|
||||
joinedPath.getNavigablePath(),
|
||||
tableGroup,
|
||||
parentTableGroup,
|
||||
null,
|
||||
tableGroup.isInnerJoinPossible() ? SqlAstJoinType.INNER : SqlAstJoinType.LEFT,
|
||||
parentTableGroup.isInnerJoinPossible() ? SqlAstJoinType.INNER : SqlAstJoinType.LEFT,
|
||||
false,
|
||||
null,
|
||||
this
|
||||
);
|
||||
|
||||
fromClauseIndex.register( joinedPath, tableGroupJoin.getJoinedGroup() );
|
||||
|
||||
consumeImplicitJoins( joinedPath, tableGroupJoin.getJoinedGroup(), implicitJoinChecker );
|
||||
tableGroup = tableGroupJoin.getJoinedGroup();
|
||||
}
|
||||
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 ) {
|
||||
// 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
|
||||
// inferable type and fallback to the binding type
|
||||
// inferrable type and fallback to the binding type
|
||||
final Supplier<MappingModelExpressable> currentExpressableSupplier = inferrableTypeAccessStack.getCurrent();
|
||||
if ( currentExpressableSupplier != null ) {
|
||||
final MappingModelExpressable inferredMapping = currentExpressableSupplier.get();
|
||||
|
@ -2697,6 +2696,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
parentTableGroup,
|
||||
null,
|
||||
SqlAstJoinType.INNER,
|
||||
false,
|
||||
LockMode.READ,
|
||||
sqlAliasBaseManager,
|
||||
getSqlExpressionResolver(),
|
||||
|
@ -3907,12 +3907,12 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
? mappingModelExpressable.getIndexDescriptor()
|
||||
: mappingModelExpressable.getElementDescriptor();
|
||||
final List<SqlAstNode> arguments = new ArrayList<>( 1 );
|
||||
|
||||
final NavigablePath navigablePath = pluralPartPath.getNavigablePath();
|
||||
collectionPart.forEachSelectable(
|
||||
(selectionIndex, selectionMapping) -> {
|
||||
arguments.add(
|
||||
new ColumnReference(
|
||||
tableGroup.getTableReference( selectionMapping.getContainingTableExpression() ),
|
||||
tableGroup.getTableReference( navigablePath, selectionMapping.getContainingTableExpression() ),
|
||||
selectionMapping,
|
||||
creationContext.getSessionFactory()
|
||||
)
|
||||
|
@ -4150,6 +4150,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
tableGroup,
|
||||
sqmPluralPath.getExplicitAlias(),
|
||||
SqlAstJoinType.INNER,
|
||||
false,
|
||||
LockMode.NONE,
|
||||
sqlAliasBaseManager,
|
||||
subQueryState,
|
||||
|
@ -4451,7 +4452,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
final List<String> bagRoles = new ArrayList<>();
|
||||
|
||||
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(
|
||||
fetchablePath,
|
||||
|
@ -4594,6 +4595,7 @@ public abstract class BaseSqmToSqlAstConverter<T extends Statement> extends Base
|
|||
lhs,
|
||||
alias,
|
||||
SqlAstJoinType.LEFT,
|
||||
true,
|
||||
LockMode.NONE,
|
||||
this
|
||||
);
|
||||
|
|
|
@ -46,7 +46,10 @@ public class BasicValuedPathInterpretation<T> extends AbstractSqmPathInterpretat
|
|||
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(
|
||||
SqlExpressionResolver.createColumnReferenceKey(
|
||||
|
|
|
@ -43,7 +43,7 @@ public class DiscriminatedAssociationPathInterpretation<T> extends AbstractSqmPa
|
|||
|
||||
mapping.forEachSelectable(
|
||||
(selectionIndex, selectableMapping) -> {
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( selectableMapping.getContainingTableExpression() );
|
||||
final TableReference tableReference = tableGroup.resolveTableReference( sqmPath.getNavigablePath(), selectableMapping.getContainingTableExpression() );
|
||||
final Expression expression = converter.getSqlExpressionResolver().resolveSqlExpression(
|
||||
SqlExpressionResolver.createColumnReferenceKey( tableReference, selectableMapping.getSelectionExpression() ),
|
||||
processingState -> new ColumnReference(
|
||||
|
|
|
@ -61,7 +61,10 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
|
|||
if ( mapping instanceof EntityAssociationMapping ) {
|
||||
final EntityAssociationMapping associationMapping = (EntityAssociationMapping) mapping;
|
||||
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 ) {
|
||||
final SimpleForeignKeyDescriptor simpleKeyDescriptor = (SimpleForeignKeyDescriptor) keyDescriptor;
|
||||
|
@ -98,7 +101,10 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
|
|||
if ( identifierMapping instanceof BasicEntityIdentifierMapping ) {
|
||||
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();
|
||||
|
||||
sqlExpression = sqlExprResolver.resolveSqlExpression(
|
||||
|
@ -189,6 +195,7 @@ public class EntityValuedPathInterpretation<T> extends AbstractSqmPathInterpreta
|
|||
parentTableGroup,
|
||||
null,
|
||||
SqlAstJoinType.INNER,
|
||||
false,
|
||||
LockMode.READ,
|
||||
sqlAstCreationState
|
||||
);
|
||||
|
|
|
@ -121,7 +121,7 @@ public abstract class AbstractSqmFrom<O,T> extends AbstractSqmPath<T> implements
|
|||
throw UnknownPathException.unknownSubPath( this, name );
|
||||
}
|
||||
|
||||
return subSource.createSqmPath( this, creationState );
|
||||
return subSource.createSqmPath( this );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -10,9 +10,7 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import javax.persistence.metamodel.MapAttribute;
|
||||
import javax.persistence.metamodel.PluralAttribute;
|
||||
|
@ -21,11 +19,8 @@ import javax.persistence.metamodel.SingularAttribute;
|
|||
import org.hibernate.metamodel.mapping.EntityDiscriminatorMapping;
|
||||
import org.hibernate.metamodel.model.domain.DomainType;
|
||||
import org.hibernate.metamodel.model.domain.EntityDomainType;
|
||||
import org.hibernate.metamodel.model.domain.MapPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.IllegalPathUsageException;
|
||||
import org.hibernate.query.sqm.NodeBuilder;
|
||||
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> {
|
||||
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 processing the {@link org.hibernate.query.hql.spi.SqmPathRegistry}
|
||||
* serves the same purpose.
|
||||
* For HQL and Criteria processing - used to track reusable paths relative to this path.
|
||||
* E.g., given `p.mate.mate` the SqmRoot identified by `p` would
|
||||
* have a reusable path for the `p.mate` path.
|
||||
*/
|
||||
private Map<String, SqmPath> attributePathRegistry;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
private Map<String, SqmPath<?>> reusablePaths;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected AbstractSqmPath(
|
||||
|
@ -79,7 +65,7 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
|
|||
}
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
protected AbstractSqmPath(SqmPathSource<T> referencedPathSource, SqmPath lhs, NodeBuilder nodeBuilder) {
|
||||
protected AbstractSqmPath(SqmPathSource<T> referencedPathSource, SqmPath<?> lhs, NodeBuilder nodeBuilder) {
|
||||
this(
|
||||
lhs == null
|
||||
? new NavigablePath( referencedPathSource.getPathName() )
|
||||
|
@ -101,43 +87,43 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<SqmPath<?>> getImplicitJoinPaths() {
|
||||
if ( implicitJoinPaths == null ) {
|
||||
public List<SqmPath<?>> getReusablePaths() {
|
||||
if ( reusablePaths == null ) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return new ArrayList<>( implicitJoinPaths.values() );
|
||||
return new ArrayList<>( reusablePaths.values() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitImplicitJoinPaths(Consumer<SqmPath<?>> consumer) {
|
||||
if ( implicitJoinPaths != null ) {
|
||||
implicitJoinPaths.values().forEach( consumer );
|
||||
public void visitReusablePaths(Consumer<SqmPath<?>> consumer) {
|
||||
if ( reusablePaths != null ) {
|
||||
reusablePaths.values().forEach( consumer );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerImplicitJoinPath(SqmPath<?> path) {
|
||||
public void registerReusablePath(SqmPath<?> path) {
|
||||
assert path.getLhs() == this;
|
||||
|
||||
if ( implicitJoinPaths == null ) {
|
||||
implicitJoinPaths = new HashMap<>();
|
||||
if ( reusablePaths == null ) {
|
||||
reusablePaths = new HashMap<>();
|
||||
}
|
||||
|
||||
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 ) {
|
||||
throw new IllegalStateException( "Implicit-join path registration unexpectedly overrode previous registration - " + relativeName );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<?> getImplicitJoinPath(String name) {
|
||||
if ( implicitJoinPaths == null ) {
|
||||
public SqmPath<?> getReusablePath(String name) {
|
||||
if ( reusablePaths == null ) {
|
||||
return null;
|
||||
}
|
||||
return implicitJoinPaths.get( name );
|
||||
return reusablePaths.get( name );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -185,7 +171,7 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmPath createSqmPath(SqmPath lhs, SqmCreationState creationState) {
|
||||
public SqmPath createSqmPath(SqmPath lhs) {
|
||||
return new SqmBasicValuedSimplePath( discriminatorNavigablePath, this, AbstractSqmPath.this, nodeBuilder() );
|
||||
}
|
||||
|
||||
|
@ -195,7 +181,7 @@ public abstract class AbstractSqmPath<T> extends AbstractSqmExpression<T> implem
|
|||
}
|
||||
|
||||
@Override
|
||||
public Class getBindableJavaType() {
|
||||
public Class<?> getBindableJavaType() {
|
||||
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() + "`" );
|
||||
}
|
||||
|
||||
return resolvePath(
|
||||
attributeName,
|
||||
(pathSource, name) -> {
|
||||
final SqmPathSource<?> subNavigable = getReferencedPathSource().findSubPathSource( attributeName );
|
||||
|
||||
if ( subNavigable == null ) {
|
||||
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 );
|
||||
}
|
||||
}
|
||||
);
|
||||
return resolvePath( attributeName, 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()
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
private SqmPath<?> resolvePath(PersistentAttribute<?, ?> attribute) {
|
||||
return resolvePath( attribute.getName(), (SqmPathSource<?>) attribute );
|
||||
}
|
||||
|
||||
private SqmPath createPluralPath(PluralPersistentAttribute pluralAttribute) {
|
||||
return new SqmPluralValuedSimplePath(
|
||||
getNavigablePath().append( pluralAttribute.getPathName() ),
|
||||
pluralAttribute,
|
||||
this,
|
||||
nodeBuilder()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private SqmPath resolvePath(String attributeName, BiFunction<SqmPath, String, SqmPath> creator) {
|
||||
final SqmPath pathSource = getLhs();
|
||||
|
||||
if ( attributePathRegistry == null ) {
|
||||
attributePathRegistry = new HashMap<>();
|
||||
final SqmPath path = creator.apply( pathSource, attributeName );
|
||||
attributePathRegistry.put( attributeName, path );
|
||||
private SqmPath<?> resolvePath(String attributeName, SqmPathSource<?> pathSource) {
|
||||
if ( reusablePaths == null ) {
|
||||
reusablePaths = new HashMap<>();
|
||||
final SqmPath<?> path = pathSource.createSqmPath( this );
|
||||
reusablePaths.put( attributeName, path );
|
||||
return path;
|
||||
}
|
||||
else {
|
||||
return attributePathRegistry.computeIfAbsent(
|
||||
return reusablePaths.computeIfAbsent(
|
||||
attributeName,
|
||||
name -> creator.apply( pathSource, attributeName )
|
||||
name -> pathSource.createSqmPath( this )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SqmPath get(SingularAttribute jpaAttribute) {
|
||||
final SingularPersistentAttribute attribute = (SingularPersistentAttribute) jpaAttribute;
|
||||
return resolvePath(
|
||||
attribute.getName(),
|
||||
(pathSource, name) -> createSingularPath( attribute )
|
||||
);
|
||||
public <Y> SqmPath<Y> get(SingularAttribute<? super T, Y> jpaAttribute) {
|
||||
return (SqmPath<Y>) resolvePath( (PersistentAttribute<?, ?>) jpaAttribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SqmPath get(PluralAttribute attribute) {
|
||||
return resolvePath(
|
||||
attribute.getName(),
|
||||
(pathSource, name) -> createPluralPath( (PluralPersistentAttribute) attribute )
|
||||
);
|
||||
public <E, C extends java.util.Collection<E>> SqmPath<C> get(PluralAttribute<T, C, E> attribute) {
|
||||
return (SqmPath<C>) resolvePath( (PersistentAttribute<?, ?>) attribute );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public SqmPath get(MapAttribute map) {
|
||||
return resolvePath(
|
||||
map.getName(),
|
||||
(pathSource, name) -> createPluralPath( (MapPersistentAttribute) map )
|
||||
);
|
||||
public <K, V, M extends java.util.Map<K, V>> SqmPath<M> get(MapAttribute<T, K, V> map) {
|
||||
return (SqmPath<M>) resolvePath( (PersistentAttribute<?, ?>) map );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -43,7 +43,7 @@ public class NonAggregatedCompositeSimplePath<T> extends SqmEntityValuedSimplePa
|
|||
throw UnknownPathException.unknownSubPath( this, name );
|
||||
}
|
||||
|
||||
return subPathSource.createSqmPath( this, creationState );
|
||||
return subPathSource.createSqmPath( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -25,7 +25,7 @@ public class SqmAnyValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
public SqmAnyValuedSimplePath(
|
||||
NavigablePath navigablePath,
|
||||
SqmPathSource<T> referencedPathSource,
|
||||
SqmPath lhs,
|
||||
SqmPath<?> lhs,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( navigablePath, referencedPathSource, lhs, nodeBuilder );
|
||||
|
||||
|
@ -36,7 +36,7 @@ public class SqmAnyValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
public SqmAnyValuedSimplePath(
|
||||
NavigablePath navigablePath,
|
||||
SqmPathSource<T> referencedPathSource,
|
||||
SqmPath lhs,
|
||||
SqmPath<?> lhs,
|
||||
String explicitAlias,
|
||||
NodeBuilder nodeBuilder) {
|
||||
super( navigablePath, referencedPathSource, lhs, explicitAlias, nodeBuilder );
|
||||
|
@ -64,7 +64,7 @@ public class SqmAnyValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
throw UnknownPathException.unknownSubPath( this, name );
|
||||
}
|
||||
|
||||
return subPathSource.createSqmPath( this, creationState );
|
||||
return subPathSource.createSqmPath( this );
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
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.EntityDomainType;
|
||||
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.SemanticQueryWalker;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class SqmEmbeddedValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
||||
public class SqmEmbeddedValuedSimplePath<T> extends AbstractSqmSimplePath<T> implements AllowableParameterType<T> {
|
||||
public SqmEmbeddedValuedSimplePath(
|
||||
NavigablePath navigablePath,
|
||||
SqmPathSource<T> referencedPathSource,
|
||||
|
@ -53,7 +55,7 @@ public class SqmEmbeddedValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
throw UnknownPathException.unknownSubPath( this, name );
|
||||
}
|
||||
|
||||
return subPathSource.createSqmPath( this, creationState );
|
||||
return subPathSource.createSqmPath( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -72,7 +74,22 @@ public class SqmEmbeddedValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
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(
|
||||
// String resultVariable,
|
||||
// DomainResultCreationState creationState,
|
||||
|
|
|
@ -41,7 +41,7 @@ public class SqmEntityValuedSimplePath<T> extends AbstractSqmSimplePath<T> {
|
|||
.findPath( getLhs().getNavigablePath() ) != null;
|
||||
|
||||
//noinspection unchecked
|
||||
return subPathSource.createSqmPath( this, creationState );
|
||||
return subPathSource.createSqmPath( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -61,7 +61,7 @@ public class SqmIndexedCollectionAccessPath<T> extends AbstractSqmPath<T> implem
|
|||
SqmCreationState creationState) {
|
||||
final SqmPathSource subPathSource = getReferencedPathSource().getElementPathSource().findSubPathSource( name );
|
||||
//noinspection unchecked
|
||||
return subPathSource.createSqmPath( this, creationState );
|
||||
return subPathSource.createSqmPath( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -36,7 +36,7 @@ public class SqmMaxElementPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
|
|||
SqmCreationState creationState) {
|
||||
if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) {
|
||||
//noinspection unchecked
|
||||
return getPluralAttribute().getElementPathSource().createSqmPath( this, creationState );
|
||||
return getPluralAttribute().getElementPathSource().createSqmPath( this );
|
||||
}
|
||||
|
||||
throw new SemanticException( "Collection element cannot be de-referenced : " + getPluralDomainPath().getNavigablePath() );
|
||||
|
|
|
@ -48,7 +48,7 @@ public class SqmMaxIndexPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
|
|||
String name,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
return indexPathSource.createSqmPath( this, creationState );
|
||||
return indexPathSource.createSqmPath( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -36,7 +36,7 @@ public class SqmMinElementPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
|
|||
SqmCreationState creationState) {
|
||||
if ( getPluralAttribute().getElementPathSource().getSqmPathType() instanceof ManagedDomainType ) {
|
||||
//noinspection unchecked
|
||||
return getPluralAttribute().getElementPathSource().createSqmPath( this, creationState );
|
||||
return getPluralAttribute().getElementPathSource().createSqmPath( this );
|
||||
}
|
||||
|
||||
throw new SemanticException( "Collection element cannot be de-referenced : " + getPluralDomainPath().getNavigablePath() );
|
||||
|
|
|
@ -48,7 +48,7 @@ public class SqmMinIndexPath<T> extends AbstractSqmSpecificPluralPartPath<T> {
|
|||
String name,
|
||||
boolean isTerminal,
|
||||
SqmCreationState creationState) {
|
||||
return indexPathSource.createSqmPath( this, creationState );
|
||||
return indexPathSource.createSqmPath( this );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -63,21 +63,21 @@ public interface SqmPath<T> extends SqmExpression<T>, SemanticPathPart, JpaPath<
|
|||
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"
|
||||
|
|
|
@ -86,26 +86,24 @@ public class SqmPluralValuedSimplePath<E> extends AbstractSqmSimplePath<E> {
|
|||
|
||||
if ( CollectionPropertyNames.COLLECTION_ELEMENTS.equals( name ) ) {
|
||||
return referencedPathSource.getElementPathSource().createSqmPath(
|
||||
this,
|
||||
creationState
|
||||
this
|
||||
);
|
||||
}
|
||||
|
||||
if ( CollectionPropertyNames.COLLECTION_INDEX.equals( name )
|
||||
|| CollectionPropertyNames.COLLECTION_INDICES.equals( name ) ) {
|
||||
if ( referencedPathSource instanceof MapPersistentAttribute ) {
|
||||
return ( (MapPersistentAttribute) referencedPathSource ).getKeyPathSource().createSqmPath( this, creationState );
|
||||
return ( (MapPersistentAttribute) referencedPathSource ).getKeyPathSource().createSqmPath( this );
|
||||
}
|
||||
else if ( referencedPathSource instanceof ListPersistentAttribute ) {
|
||||
return referencedPathSource.getIndexPathSource().createSqmPath( this, creationState );
|
||||
return referencedPathSource.getIndexPathSource().createSqmPath( this );
|
||||
}
|
||||
|
||||
throw new UnsupportedOperationException( );
|
||||
}
|
||||
|
||||
return referencedPathSource.getElementPathSource().createSqmPath(
|
||||
this,
|
||||
creationState
|
||||
this
|
||||
);
|
||||
}
|
||||
);
|
||||
|
|
|
@ -33,7 +33,6 @@ import org.hibernate.metamodel.model.domain.PersistentAttribute;
|
|||
import org.hibernate.metamodel.model.domain.PluralPersistentAttribute;
|
||||
import org.hibernate.metamodel.model.domain.SimpleDomainType;
|
||||
import org.hibernate.metamodel.model.domain.SingularPersistentAttribute;
|
||||
import org.hibernate.query.hql.spi.SqmCreationState;
|
||||
import org.hibernate.query.sqm.SqmPathSource;
|
||||
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
|
||||
|
||||
|
@ -374,7 +373,7 @@ public class SqmPolymorphicRootDescriptor<T> implements EntityDomainType<T> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public SqmPath<T> createSqmPath(SqmPath<?> lhs, SqmCreationState creationState) {
|
||||
public SqmPath<T> createSqmPath(SqmPath<?> lhs) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ import org.hibernate.sql.ast.tree.SqlAstTreeLogger;
|
|||
import org.hibernate.sql.ast.tree.Statement;
|
||||
import org.hibernate.sql.ast.tree.delete.DeleteStatement;
|
||||
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.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.from.TableReferenceJoin;
|
||||
|
@ -106,6 +107,13 @@ public class SqlTreePrinter {
|
|||
}
|
||||
|
||||
private void logTableGroupDetails(TableGroup tableGroup) {
|
||||
if (tableGroup instanceof LazyTableGroup ) {
|
||||
TableGroup underlyingTableGroup = ( (LazyTableGroup) tableGroup ).getUnderlyingTableGroup();
|
||||
if ( underlyingTableGroup != null ) {
|
||||
logTableGroupDetails( underlyingTableGroup );
|
||||
}
|
||||
return;
|
||||
}
|
||||
logWithIndentation(
|
||||
"primaryTableReference : %s as %s",
|
||||
tableGroup.getPrimaryTableReference().getTableExpression(),
|
||||
|
|
|
@ -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.UnaryOperation;
|
||||
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.TableGroupJoin;
|
||||
import org.hibernate.sql.ast.tree.from.TableReference;
|
||||
|
@ -2683,7 +2684,7 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
|
|||
if ( joinedGroup instanceof VirtualTableGroup ) {
|
||||
processTableGroupJoins( tableGroupJoin.getJoinedGroup() );
|
||||
}
|
||||
else {
|
||||
else if ( !( joinedGroup instanceof LazyTableGroup ) || ( (LazyTableGroup) joinedGroup ).getUnderlyingTableGroup() != null ) {
|
||||
appendSql( EMPTY_STRING );
|
||||
SqlAstJoinType joinType = tableGroupJoin.getJoinType();
|
||||
if ( !joinedGroup.isRealTableGroup() && joinType == SqlAstJoinType.INNER && !joinedGroup.getTableReferenceJoins().isEmpty() ) {
|
||||
|
|
|
@ -9,7 +9,6 @@ package org.hibernate.sql.ast.tree.cte;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
|
@ -62,7 +61,7 @@ public class CteTableGroup implements TableGroup {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(String tableExpression) {
|
||||
public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
if ( cteTableReference.getTableExpression().equals( tableExpression ) ) {
|
||||
return cteTableReference;
|
||||
}
|
||||
|
@ -70,14 +69,7 @@ public class CteTableGroup implements TableGroup {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression) {
|
||||
return cteTableReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(
|
||||
String tableExpression,
|
||||
Supplier<TableReference> creator) {
|
||||
public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
return cteTableReference;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
package org.hibernate.sql.ast.tree.from;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -25,20 +25,10 @@ public abstract class AbstractColumnReferenceQualifier implements ColumnReferenc
|
|||
// TableReference handling
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) {
|
||||
final TableReference existing = getTableReferenceInternal( tableExpression );
|
||||
if ( existing != null ) {
|
||||
return existing;
|
||||
}
|
||||
|
||||
return creator.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression) {
|
||||
public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
assert tableExpression != null;
|
||||
|
||||
final TableReference tableReference = getTableReferenceInternal( tableExpression );
|
||||
final TableReference tableReference = getTableReferenceInternal( navigablePath, tableExpression );
|
||||
if ( tableReference == null ) {
|
||||
throw new IllegalStateException( "Could not resolve binding for table `" + tableExpression + "`" );
|
||||
}
|
||||
|
@ -47,18 +37,24 @@ public abstract class AbstractColumnReferenceQualifier implements ColumnReferenc
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(String tableExpression) {
|
||||
return getTableReferenceInternal( tableExpression );
|
||||
public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
return getTableReferenceInternal( navigablePath, tableExpression );
|
||||
}
|
||||
|
||||
protected TableReference getTableReferenceInternal(String tableExpression) {
|
||||
if ( getPrimaryTableReference().getTableReference( tableExpression ) != null) {
|
||||
return getPrimaryTableReference();
|
||||
protected TableReference getTableReferenceInternal(
|
||||
NavigablePath navigablePath,
|
||||
String tableExpression) {
|
||||
final TableReference primaryTableReference = getPrimaryTableReference().getTableReference( navigablePath , tableExpression );
|
||||
if ( primaryTableReference != null) {
|
||||
return primaryTableReference;
|
||||
}
|
||||
|
||||
for ( TableReferenceJoin tableJoin : getTableReferenceJoins() ) {
|
||||
if ( tableJoin.getJoinedTableReference().getTableReference( tableExpression ) != null) {
|
||||
return tableJoin.getJoinedTableReference();
|
||||
final TableReference tableReference = tableJoin.getJoinedTableReference().getTableReference(
|
||||
navigablePath,
|
||||
tableExpression );
|
||||
if ( tableReference != null) {
|
||||
return tableReference;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6,13 +6,15 @@
|
|||
*/
|
||||
package org.hibernate.sql.ast.tree.from;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface ColumnReferenceQualifier {
|
||||
TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator);
|
||||
TableReference resolveTableReference(String tableExpression);
|
||||
TableReference getTableReference(String tableExpression);
|
||||
TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression);
|
||||
TableReference getTableReference(NavigablePath navigablePath, String tableExpression);
|
||||
default TableReference getTableReference(String tableExpression) {
|
||||
return getTableReference( null, tableExpression );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
|
||||
|
@ -110,26 +109,19 @@ public class CompositeTableGroup implements VirtualTableGroup {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(String tableExpression) {
|
||||
public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
return underlyingTableGroup.getTableReference( tableExpression );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(
|
||||
String tableExpression,
|
||||
Supplier<TableReference> creator) {
|
||||
return underlyingTableGroup.resolveTableReference( tableExpression, creator );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression) {
|
||||
TableReference tableReference = underlyingTableGroup.getTableReference( tableExpression );
|
||||
public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
TableReference tableReference = underlyingTableGroup.getTableReference( navigablePath, tableExpression );
|
||||
if ( tableReference != null ) {
|
||||
return tableReference;
|
||||
}
|
||||
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
|
||||
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference();
|
||||
if ( primaryTableReference.getTableExpression().equals( tableExpression ) ) {
|
||||
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference().getTableReference( navigablePath, tableExpression );
|
||||
if ( primaryTableReference != null ) {
|
||||
return primaryTableReference;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.function.Consumer;
|
|||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.SqlAstJoinType;
|
||||
import org.hibernate.sql.ast.spi.SqlAliasBase;
|
||||
import org.hibernate.sql.ast.tree.predicate.Predicate;
|
||||
|
@ -59,20 +60,23 @@ public class CorrelatedTableGroup extends AbstractTableGroup {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected TableReference getTableReferenceInternal(String tableExpression) {
|
||||
final TableReference primaryTableReference = correlatedTableGroup.getPrimaryTableReference();
|
||||
if ( tableExpression.equals( primaryTableReference.getTableExpression() ) ) {
|
||||
protected TableReference getTableReferenceInternal(
|
||||
NavigablePath navigablePath,
|
||||
String tableExpression) {
|
||||
final TableReference primaryTableReference = correlatedTableGroup.getPrimaryTableReference().getTableReference( navigablePath, tableExpression );
|
||||
if ( primaryTableReference != null ) {
|
||||
return primaryTableReference;
|
||||
}
|
||||
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
|
||||
final TableReference groupTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference();
|
||||
if ( groupTableReference.getTableReference( tableExpression ) != null ) {
|
||||
final TableReference groupTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference().getTableReference( navigablePath, tableExpression );
|
||||
if ( groupTableReference != null ) {
|
||||
return groupTableReference;
|
||||
}
|
||||
}
|
||||
for ( TableReferenceJoin tableReferenceJoin : correlatedTableGroup.getTableReferenceJoins() ) {
|
||||
if ( tableExpression.equals( tableReferenceJoin.getJoinedTableReference().getTableExpression() ) ) {
|
||||
return tableReferenceJoin.getJoinedTableReference();
|
||||
final TableReference tableReference = tableReferenceJoin.getJoinedTableReference().getTableReference( navigablePath, tableExpression );
|
||||
if ( tableReference != null ) {
|
||||
return tableReference;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
}
|
|
@ -9,7 +9,6 @@ package org.hibernate.sql.ast.tree.from;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
|
@ -62,20 +61,15 @@ public class MutatingTableReferenceGroupWrapper implements VirtualTableGroup {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(String tableExpression) {
|
||||
public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
return mutatingTableReference.getTableExpression().equals( tableExpression )
|
||||
? mutatingTableReference
|
||||
: null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) {
|
||||
return resolveTableReference( tableExpression );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression) {
|
||||
return getTableReference( tableExpression );
|
||||
public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
return getTableReference( navigablePath, tableExpression );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,6 +26,7 @@ public class StandardTableGroup extends AbstractTableGroup {
|
|||
private final Predicate<String> tableReferenceJoinNameChecker;
|
||||
private final BiFunction<String,TableGroup,TableReferenceJoin> tableReferenceJoinCreator;
|
||||
private final boolean realTableGroup;
|
||||
private final boolean fetched;
|
||||
|
||||
private List<TableReferenceJoin> tableJoins;
|
||||
|
||||
|
@ -39,6 +40,7 @@ public class StandardTableGroup extends AbstractTableGroup {
|
|||
super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory );
|
||||
this.primaryTableReference = primaryTableReference;
|
||||
this.realTableGroup = false;
|
||||
this.fetched = false;
|
||||
this.tableJoins = Collections.emptyList();
|
||||
this.tableReferenceJoinCreator = null;
|
||||
this.tableReferenceJoinNameChecker = s -> {
|
||||
|
@ -64,6 +66,27 @@ public class StandardTableGroup extends AbstractTableGroup {
|
|||
super( navigablePath, tableGroupProducer, lockMode, sqlAliasBase, sessionFactory );
|
||||
this.primaryTableReference = primaryTableReference;
|
||||
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.tableReferenceJoinNameChecker = tableReferenceJoinNameChecker;
|
||||
this.tableReferenceJoinCreator = tableReferenceJoinCreator;
|
||||
|
@ -78,11 +101,6 @@ public class StandardTableGroup extends AbstractTableGroup {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(String tableExpression) {
|
||||
return getTableReferenceInternal( tableExpression );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference getPrimaryTableReference() {
|
||||
return primaryTableReference;
|
||||
|
@ -98,6 +116,11 @@ public class StandardTableGroup extends AbstractTableGroup {
|
|||
return realTableGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFetched() {
|
||||
return fetched;
|
||||
}
|
||||
|
||||
public void addTableReferenceJoin(TableReferenceJoin join) {
|
||||
if ( tableJoins == null ) {
|
||||
tableJoins = new ArrayList<>();
|
||||
|
@ -106,8 +129,10 @@ public class StandardTableGroup extends AbstractTableGroup {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReferenceInternal(String tableExpression) {
|
||||
TableReference tableReference = primaryTableReference.getTableReference( tableExpression );
|
||||
public TableReference getTableReferenceInternal(
|
||||
NavigablePath navigablePath,
|
||||
String tableExpression) {
|
||||
TableReference tableReference = primaryTableReference.getTableReference( navigablePath, tableExpression );
|
||||
if ( tableReference != null ) {
|
||||
return tableReference;
|
||||
}
|
||||
|
@ -118,7 +143,7 @@ public class StandardTableGroup extends AbstractTableGroup {
|
|||
final TableReferenceJoin join = tableJoins.get( i );
|
||||
assert join != null;
|
||||
final TableReference resolveTableReference = join.getJoinedTableReference()
|
||||
.getTableReference( tableExpression );
|
||||
.getTableReference( navigablePath, tableExpression );
|
||||
if ( resolveTableReference != null ) {
|
||||
return resolveTableReference;
|
||||
}
|
||||
|
@ -130,7 +155,7 @@ public class StandardTableGroup extends AbstractTableGroup {
|
|||
|
||||
for ( TableGroupJoin tableGroupJoin : getTableGroupJoins() ) {
|
||||
final TableReference primaryTableReference = tableGroupJoin.getJoinedGroup().getPrimaryTableReference();
|
||||
if ( primaryTableReference.getTableReference( tableExpression ) != null ) {
|
||||
if ( primaryTableReference.getTableReference( navigablePath, tableExpression ) != null ) {
|
||||
return primaryTableReference;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,4 +91,8 @@ public interface TableGroup extends SqlAstNode, ColumnReferenceQualifier, SqmPat
|
|||
default boolean isRealTableGroup() {
|
||||
return false;
|
||||
}
|
||||
|
||||
default boolean isFetched() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ public interface TableGroupJoinProducer extends TableGroupProducer {
|
|||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAstCreationState creationState) {
|
||||
return createTableGroupJoin(
|
||||
|
@ -33,6 +34,7 @@ public interface TableGroupJoinProducer extends TableGroupProducer {
|
|||
lhs,
|
||||
explicitSourceAlias,
|
||||
sqlAstJoinType,
|
||||
fetched,
|
||||
lockMode,
|
||||
creationState.getSqlAliasBaseGenerator(),
|
||||
creationState.getSqlExpressionResolver(),
|
||||
|
@ -48,6 +50,7 @@ public interface TableGroupJoinProducer extends TableGroupProducer {
|
|||
TableGroup lhs,
|
||||
String explicitSourceAlias,
|
||||
SqlAstJoinType sqlAstJoinType,
|
||||
boolean fetched,
|
||||
LockMode lockMode,
|
||||
SqlAliasBaseGenerator aliasBaseGenerator,
|
||||
SqlExpressionResolver sqlExpressionResolver,
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
package org.hibernate.sql.ast.tree.from;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
import org.hibernate.sql.ast.SqlAstWalker;
|
||||
import org.hibernate.sql.ast.tree.SqlAstNode;
|
||||
|
||||
|
@ -52,12 +52,7 @@ public class TableReference implements SqlAstNode, ColumnReferenceQualifier {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) {
|
||||
throw new UnsupportedOperationException( "Cannot create a TableReference relative to a TableReference" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression) {
|
||||
public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
if ( tableExpression.equals( getTableExpression() ) ) {
|
||||
return this;
|
||||
}
|
||||
|
@ -65,7 +60,7 @@ public class TableReference implements SqlAstNode, ColumnReferenceQualifier {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(String tableExpression) {
|
||||
public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
if ( this.tableExpression.equals( tableExpression ) ) {
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ import java.util.ArrayList;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
|
@ -109,19 +108,13 @@ public class UnionTableGroup implements VirtualTableGroup {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(String tableExpression) {
|
||||
public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
// assert tableReference.getTableExpression().equals( tableExpression );
|
||||
return tableReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) {
|
||||
assert tableReference.getTableExpression().equals( tableExpression );
|
||||
return tableReference;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression) {
|
||||
public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
// assert tableReference.getTableExpression().equals( tableExpression );
|
||||
return tableReference;
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package org.hibernate.sql.ast.tree.from;
|
||||
|
||||
import org.hibernate.engine.spi.SessionFactoryImplementor;
|
||||
import org.hibernate.query.NavigablePath;
|
||||
|
||||
/**
|
||||
* @author Andrea Boriero
|
||||
|
@ -25,7 +26,7 @@ public class UnionTableReference extends TableReference {
|
|||
this.subclassTableSpaceExpressions = subclassTableSpaceExpressions;
|
||||
}
|
||||
|
||||
public TableReference resolveTableReference(String tableExpression) {
|
||||
public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
if ( hasTableExpression( tableExpression ) ) {
|
||||
return this;
|
||||
}
|
||||
|
@ -33,7 +34,7 @@ public class UnionTableReference extends TableReference {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(String tableExpression) {
|
||||
public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
if ( hasTableExpression( tableExpression ) ) {
|
||||
return this;
|
||||
}
|
||||
|
|
|
@ -42,6 +42,10 @@ public interface FetchParent extends DomainResultGraphNode {
|
|||
return null;
|
||||
}
|
||||
|
||||
default NavigablePath resolveNavigablePath(Fetchable fetchable) {
|
||||
return getNavigablePath().append( fetchable.getFetchableName() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Whereas {@link #getReferencedMappingContainer} and {@link #getReferencedMappingType} return the
|
||||
* referenced container type, this method returns the referenced part.
|
||||
|
|
|
@ -8,7 +8,6 @@ package org.hibernate.sql.results.graph.collection.internal;
|
|||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import org.hibernate.LockMode;
|
||||
import org.hibernate.metamodel.mapping.ModelPart;
|
||||
|
@ -103,18 +102,13 @@ public class EntityCollectionPartTableGroup implements TableGroup {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TableReference getTableReference(String tableExpression) {
|
||||
public TableReference getTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
return collectionTableGroup.getTableReference( tableExpression );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression, Supplier<TableReference> creator) {
|
||||
return collectionTableGroup.resolveTableReference( tableExpression, creator );
|
||||
}
|
||||
|
||||
@Override
|
||||
public TableReference resolveTableReference(String tableExpression) {
|
||||
return collectionTableGroup.resolveTableReference( tableExpression );
|
||||
public TableReference resolveTableReference(NavigablePath navigablePath, String tableExpression) {
|
||||
return collectionTableGroup.resolveTableReference( navigablePath, tableExpression );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -66,6 +66,7 @@ public class EmbeddableFetchImpl extends AbstractFetchParent implements Embeddab
|
|||
lhsTableGroup,
|
||||
null,
|
||||
nullable ? SqlAstJoinType.LEFT : SqlAstJoinType.INNER,
|
||||
true,
|
||||
LockMode.NONE,
|
||||
creationState.getSqlAstCreationState()
|
||||
);
|
||||
|
|
|
@ -61,12 +61,22 @@ public class EmbeddableForeignKeyResultImpl<T>
|
|||
LockMode lockMode,
|
||||
String resultVariable,
|
||||
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(
|
||||
this,
|
||||
fetchablePath,
|
||||
fetchTiming,
|
||||
// We need to make sure to-ones are always delayed to avoid cycles while resolving entity keys
|
||||
selected && !( fetchable instanceof ToOneAttributeMapping ),
|
||||
shouldSelect,
|
||||
lockMode,
|
||||
resultVariable,
|
||||
creationState
|
||||
|
|
|
@ -52,6 +52,7 @@ public class EmbeddableResultImpl<T> extends AbstractFetchParent implements Embe
|
|||
fromClauseAccess.findTableGroup( navigablePath.getParent() ),
|
||||
resultVariable,
|
||||
SqlAstJoinType.INNER,
|
||||
true,
|
||||
LockMode.NONE,
|
||||
creationState.getSqlAstCreationState()
|
||||
);
|
||||
|
|
|
@ -73,6 +73,16 @@ public abstract class AbstractEntityResultGraphNode extends AbstractFetchParent
|
|||
identifierResult = null;
|
||||
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 {
|
||||
identifierResult = identifierMapping.createDomainResult(
|
||||
identifierNavigablePath,
|
||||
|
|
|
@ -9,6 +9,7 @@ package org.hibernate.sql.results.graph.entity.internal;
|
|||
import org.hibernate.LockMode;
|
||||
import org.hibernate.engine.FetchTiming;
|
||||
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.DomainResultCreationState;
|
||||
import org.hibernate.sql.results.graph.FetchParent;
|
||||
|
@ -29,6 +30,7 @@ public class EntityFetchJoinedImpl extends AbstractNonLazyEntityFetch {
|
|||
public EntityFetchJoinedImpl(
|
||||
FetchParent fetchParent,
|
||||
EntityValuedFetchable fetchedAttribute,
|
||||
TableGroup tableGroup,
|
||||
LockMode lockMode,
|
||||
boolean nullable,
|
||||
NavigablePath navigablePath,
|
||||
|
@ -38,6 +40,7 @@ public class EntityFetchJoinedImpl extends AbstractNonLazyEntityFetch {
|
|||
entityResult = new EntityResultImpl(
|
||||
navigablePath,
|
||||
fetchedAttribute,
|
||||
tableGroup,
|
||||
null,
|
||||
creationState
|
||||
);
|
||||
|
|
|
@ -9,9 +9,13 @@ package org.hibernate.sql.results.graph.entity.internal;
|
|||
import org.hibernate.metamodel.mapping.EntityMappingType;
|
||||
import org.hibernate.metamodel.mapping.EntityValuedModelPart;
|
||||
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.DomainResultAssembler;
|
||||
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.entity.AbstractEntityResultGraphNode;
|
||||
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 {
|
||||
|
||||
private final TableGroup tableGroup;
|
||||
private final String resultVariable;
|
||||
|
||||
public EntityResultImpl(
|
||||
NavigablePath navigablePath,
|
||||
EntityValuedModelPart entityValuedModelPart,
|
||||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
this( navigablePath, entityValuedModelPart, resultVariable, null, creationState );
|
||||
this( navigablePath, entityValuedModelPart, tableGroup, resultVariable, null, creationState );
|
||||
}
|
||||
|
||||
public EntityResultImpl(
|
||||
NavigablePath navigablePath,
|
||||
EntityValuedModelPart entityValuedModelPart,
|
||||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
EntityMappingType targetType,
|
||||
DomainResultCreationState creationState) {
|
||||
|
@ -46,12 +53,27 @@ public class EntityResultImpl extends AbstractEntityResultGraphNode implements E
|
|||
navigablePath,
|
||||
creationState
|
||||
);
|
||||
|
||||
this.tableGroup = tableGroup;
|
||||
this.resultVariable = resultVariable;
|
||||
|
||||
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
|
||||
public FetchableContainer getReferencedMappingType() {
|
||||
return getReferencedMappingContainer();
|
||||
|
|
|
@ -24,9 +24,10 @@ public class EntityResultJoinedSubclassImpl extends EntityResultImpl {
|
|||
public EntityResultJoinedSubclassImpl(
|
||||
NavigablePath navigablePath,
|
||||
EntityValuedModelPart entityValuedModelPart,
|
||||
TableGroup tableGroup,
|
||||
String resultVariable,
|
||||
DomainResultCreationState creationState) {
|
||||
super( navigablePath, entityValuedModelPart, resultVariable, creationState );
|
||||
super( navigablePath, entityValuedModelPart, tableGroup, resultVariable, creationState );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.hibernate.type.descriptor.jdbc.RealTypeDescriptor;
|
|||
import org.hibernate.type.descriptor.jdbc.SmallIntTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.TimeTypeDescriptor;
|
||||
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.VarbinaryTypeDescriptor;
|
||||
import org.hibernate.type.descriptor.jdbc.VarcharTypeDescriptor;
|
||||
|
@ -57,6 +58,7 @@ public class JdbcTypeDescriptorBaseline {
|
|||
|
||||
target.addDescriptor( DateTypeDescriptor.INSTANCE );
|
||||
target.addDescriptor( TimestampTypeDescriptor.INSTANCE );
|
||||
target.addDescriptor( TimestampWithTimeZoneDescriptor.INSTANCE );
|
||||
target.addDescriptor( TimeTypeDescriptor.INSTANCE );
|
||||
|
||||
target.addDescriptor( BinaryTypeDescriptor.INSTANCE );
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue