From 756afb878802fb6a2d2f493013e83b1ef530c448 Mon Sep 17 00:00:00 2001 From: Christian Beikov Date: Fri, 22 Oct 2021 16:27:33 +0200 Subject: [PATCH] Fix collection table cleanup issues for all strategies --- .../mapping/EmbeddableMappingType.java | 4 +- .../metamodel/mapping/EntityMappingType.java | 2 +- .../metamodel/mapping/ManagedMappingType.java | 2 +- .../metamodel/mapping/MappingModelHelper.java | 31 ++++++- .../BasicEntityIdentifierMappingImpl.java | 13 +++ .../NonAggregatedIdentifierMappingImpl.java | 32 +++++++ .../internal/ToOneAttributeMapping.java | 28 ++++++ .../entity/AbstractEntityPersister.java | 10 +-- .../sqm/internal/SimpleDeleteQueryPlan.java | 16 ++-- .../internal/MatchingIdSelectionHelper.java | 86 +++++++++++++------ .../internal/SqmMutationStrategyHelper.java | 2 +- .../cte/AbstractCteMutationHandler.java | 58 ++++++++++--- .../internal/cte/CteDeleteHandler.java | 54 +++++++++++- .../idtable/ExecuteWithIdTableHelper.java | 75 +++++++++++----- .../mutation/internal/idtable/IdTable.java | 30 +++++++ .../RestrictedDeleteExecutionDelegate.java | 21 ++++- .../InPredicateRestrictionProducer.java | 3 + .../internal/inline/InlineDeleteHandler.java | 55 ++++++++---- .../inline/MatchingIdRestrictionProducer.java | 3 + .../sql/ast/tree/from/TableGroup.java | 12 ++- .../GoofyPersisterClassProvider.java | 2 +- .../PersisterClassProviderTest.java | 2 +- .../orm/test/legacy/CustomPersister.java | 2 +- 23 files changed, 436 insertions(+), 107 deletions(-) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java index 80f9eb3d37..cc814e7831 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EmbeddableMappingType.java @@ -582,7 +582,7 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectableMapp BiConsumer selectionConsumer) { visitAttributeMappings( attributeMapping -> - ManagedMappingType.super.applySqlSelections( + attributeMapping.applySqlSelections( navigablePath, tableGroup, creationState, @@ -742,7 +742,7 @@ public class EmbeddableMappingType implements ManagedMappingType, SelectableMapp } @Override - public void visitAttributeMappings(Consumer action) { + public void visitAttributeMappings(Consumer action) { attributeMappings.forEach( action ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityMappingType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityMappingType.java index 42e5be3714..13d32b5b9f 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityMappingType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/EntityMappingType.java @@ -209,7 +209,7 @@ public interface EntityMappingType extends ManagedMappingType, EntityValuedModel @Override - default void visitAttributeMappings(Consumer action) { + default void visitAttributeMappings(Consumer action) { getAttributeMappings().forEach( action ); } diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ManagedMappingType.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ManagedMappingType.java index 26ad302df4..1d2589b6b1 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ManagedMappingType.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/ManagedMappingType.java @@ -47,7 +47,7 @@ public interface ManagedMappingType extends MappingType, FetchableContainer { /** * Visit attributes defined on this class and any supers */ - void visitAttributeMappings(Consumer action); + void visitAttributeMappings(Consumer action); /** * Visit attributes defined on this class and any supers diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java index 262f178d87..06ba6d3f91 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/MappingModelHelper.java @@ -14,6 +14,7 @@ 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.SqlTuple; +import org.hibernate.sql.ast.tree.from.TableGroup; import static org.hibernate.sql.ast.spi.SqlExpressionResolver.createColumnReferenceKey; @@ -25,6 +26,14 @@ public class MappingModelHelper { ModelPart modelPart, SqlExpressionResolver sqlExpressionResolver, SessionFactoryImplementor sessionFactory) { + return buildColumnReferenceExpression( null, modelPart, sqlExpressionResolver, sessionFactory ); + } + + public static Expression buildColumnReferenceExpression( + TableGroup tableGroup, + ModelPart modelPart, + SqlExpressionResolver sqlExpressionResolver, + SessionFactoryImplementor sessionFactory) { final int jdbcTypeCount = modelPart.getJdbcTypeCount(); if ( modelPart instanceof EmbeddableValuedModelPart ) { @@ -32,9 +41,16 @@ public class MappingModelHelper { modelPart.forEachSelectable( (columnIndex, selection) -> { final ColumnReference colRef; + final String qualifier; + if ( tableGroup == null ) { + qualifier = selection.getContainingTableExpression(); + } + else { + qualifier = tableGroup.getTableReference( selection.getContainingTableExpression() ).getIdentificationVariable(); + } if ( sqlExpressionResolver == null ) { colRef = new ColumnReference( - selection.getContainingTableExpression(), + qualifier, selection, sessionFactory ); @@ -43,7 +59,7 @@ public class MappingModelHelper { colRef = (ColumnReference) sqlExpressionResolver.resolveSqlExpression( createColumnReferenceKey( selection.getContainingTableExpression(), selection.getSelectionExpression() ), sqlAstProcessingState -> new ColumnReference( - selection.getContainingTableExpression(), + qualifier, selection, sessionFactory ) @@ -57,9 +73,16 @@ public class MappingModelHelper { else { assert modelPart instanceof BasicValuedModelPart; final BasicValuedModelPart basicPart = (BasicValuedModelPart) modelPart; + final String qualifier; + if ( tableGroup == null ) { + qualifier = basicPart.getContainingTableExpression(); + } + else { + qualifier = tableGroup.getTableReference( basicPart.getContainingTableExpression() ).getIdentificationVariable(); + } if ( sqlExpressionResolver == null ) { return new ColumnReference( - basicPart.getContainingTableExpression(), + qualifier, basicPart, sessionFactory ); @@ -68,7 +91,7 @@ public class MappingModelHelper { return sqlExpressionResolver.resolveSqlExpression( createColumnReferenceKey( basicPart.getContainingTableExpression(), basicPart.getSelectionExpression() ), sqlAstProcessingState -> new ColumnReference( - basicPart.getContainingTableExpression(), + qualifier, basicPart, sessionFactory ) diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicEntityIdentifierMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicEntityIdentifierMappingImpl.java index 4e9c92b796..dd847f5ea5 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicEntityIdentifierMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/BasicEntityIdentifierMappingImpl.java @@ -7,6 +7,7 @@ package org.hibernate.metamodel.mapping.internal; import java.util.Locale; +import java.util.function.BiConsumer; import java.util.function.Supplier; import org.hibernate.engine.FetchStyle; @@ -212,6 +213,18 @@ public class BasicEntityIdentifierMappingImpl implements BasicEntityIdentifierMa resolveSqlSelection( navigablePath, tableGroup, true, creationState ); } + @Override + public void applySqlSelections( + NavigablePath navigablePath, + TableGroup tableGroup, + DomainResultCreationState creationState, + BiConsumer selectionConsumer) { + selectionConsumer.accept( + resolveSqlSelection( navigablePath, tableGroup, true, creationState ), + getJdbcMapping() + ); + } + private SqlSelection resolveSqlSelection( NavigablePath navigablePath, TableGroup tableGroup, diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java index 50c4e54839..d9cbe784eb 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/NonAggregatedIdentifierMappingImpl.java @@ -8,6 +8,7 @@ package org.hibernate.metamodel.mapping.internal; import java.io.Serializable; import java.util.List; +import java.util.function.BiConsumer; import org.hibernate.engine.spi.EntityKey; import org.hibernate.engine.spi.PersistenceContext; @@ -19,9 +20,14 @@ import org.hibernate.mapping.Property; import org.hibernate.metamodel.internal.AbstractCompositeIdentifierMapping; import org.hibernate.metamodel.mapping.EmbeddableMappingType; import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.metamodel.mapping.JdbcMapping; import org.hibernate.metamodel.mapping.SingularAttributeMapping; import org.hibernate.metamodel.mapping.StateArrayContributorMetadataAccess; import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.query.NavigablePath; +import org.hibernate.sql.ast.spi.SqlSelection; +import org.hibernate.sql.ast.tree.from.TableGroup; +import org.hibernate.sql.results.graph.DomainResultCreationState; import org.hibernate.type.ComponentType; /** @@ -133,6 +139,32 @@ public class NonAggregatedIdentifierMappingImpl extends AbstractCompositeIdentif } } + @Override + public void applySqlSelections( + NavigablePath navigablePath, + TableGroup tableGroup, + DomainResultCreationState creationState) { + for ( int i = 0; i < idAttributeMappings.size(); i++ ) { + idAttributeMappings.get( i ).applySqlSelections( navigablePath, tableGroup, creationState ); + } + } + + @Override + public void applySqlSelections( + NavigablePath navigablePath, + TableGroup tableGroup, + DomainResultCreationState creationState, + BiConsumer selectionConsumer) { + for ( int i = 0; i < idAttributeMappings.size(); i++ ) { + idAttributeMappings.get( i ).applySqlSelections( + navigablePath, + tableGroup, + creationState, + selectionConsumer + ); + } + } + // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // EmbeddableValuedFetchable diff --git a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java index 703720ea44..e5f6b3a3fa 100644 --- a/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java +++ b/hibernate-core/src/main/java/org/hibernate/metamodel/mapping/internal/ToOneAttributeMapping.java @@ -10,6 +10,7 @@ import java.util.Collections; import java.util.HashSet; import java.util.Iterator; import java.util.Set; +import java.util.function.BiConsumer; import java.util.function.Consumer; import org.hibernate.LockMode; @@ -50,6 +51,7 @@ 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.spi.SqlSelection; import org.hibernate.sql.ast.tree.from.LazyTableGroup; import org.hibernate.sql.ast.tree.from.StandardTableGroup; import org.hibernate.sql.ast.tree.from.TableGroup; @@ -1157,6 +1159,32 @@ public class ToOneAttributeMapping } } + @Override + public void applySqlSelections( + NavigablePath navigablePath, + TableGroup tableGroup, + DomainResultCreationState creationState) { + if ( sideNature == ForeignKeyDescriptor.Nature.KEY ) { + foreignKeyDescriptor.getKeyPart().applySqlSelections( navigablePath, tableGroup, creationState ); + } + } + + @Override + public void applySqlSelections( + NavigablePath navigablePath, + TableGroup tableGroup, + DomainResultCreationState creationState, + BiConsumer selectionConsumer) { + if ( sideNature == ForeignKeyDescriptor.Nature.KEY ) { + foreignKeyDescriptor.getKeyPart().applySqlSelections( + navigablePath, + tableGroup, + creationState, + selectionConsumer + ); + } + } + @Override public int getJdbcTypeCount() { return foreignKeyDescriptor.getJdbcTypeCount(); diff --git a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java index 0be228e5f1..bb311e42df 100644 --- a/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java +++ b/hibernate-core/src/main/java/org/hibernate/persister/entity/AbstractEntityPersister.java @@ -5452,7 +5452,7 @@ public abstract class AbstractEntityPersister protected ReflectionOptimizer.AccessOptimizer accessOptimizer; @Override - public void visitAttributeMappings(Consumer action) { + public void visitAttributeMappings(Consumer action) { attributeMappings.forEach( action ); } @@ -5540,7 +5540,6 @@ public abstract class AbstractEntityPersister "Entity(" + getEntityName() + ") `staticFetchableList` generator", () -> { staticFetchableList = new ArrayList<>( attributeMappings.size() ); - visitAttributeMappings( attributeMapping -> staticFetchableList.add( attributeMapping ) ); visitSubTypeAttributeMappings( attributeMapping -> staticFetchableList.add( attributeMapping ) ); return true; } @@ -6352,11 +6351,12 @@ public abstract class AbstractEntityPersister return; } - attributeMappings.forEach( fetchableConsumer ); - if ( treatTargetType.isTypeOrSuperType( this ) ) { visitSubTypeAttributeMappings( fetchableConsumer ); } + else { + attributeMappings.forEach( fetchableConsumer ); + } } protected List getStaticFetchableList() { @@ -6389,11 +6389,11 @@ public abstract class AbstractEntityPersister @Override public void visitSubTypeAttributeMappings(Consumer action) { + visitAttributeMappings( action ); if ( subclassMappingTypes != null ) { subclassMappingTypes.forEach( (s, subType) -> { subType.visitDeclaredAttributeMappings( action ); - subType.visitSubTypeAttributeMappings( action ); } ); } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleDeleteQueryPlan.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleDeleteQueryPlan.java index 72075da5b4..9b47ca75aa 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleDeleteQueryPlan.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/internal/SimpleDeleteQueryPlan.java @@ -137,26 +137,28 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan { final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor(); final Expression fkColumnExpression = MappingModelHelper.buildColumnReferenceExpression( - fkDescriptor, + fkDescriptor.getKeyPart(), null, factory ); final QuerySpec matchingIdSubQuery = new QuerySpec( false ); + final MutatingTableReferenceGroupWrapper tableGroup = new MutatingTableReferenceGroupWrapper( + new NavigablePath( attributeMapping.getRootPathName() ), + attributeMapping, + sqmInterpretation.getSqlAst().getTargetTable() + ); final Expression fkTargetColumnExpression = MappingModelHelper.buildColumnReferenceExpression( - fkDescriptor, + tableGroup, + fkDescriptor.getTargetPart(), sqmInterpretation.getSqlExpressionResolver(), factory ); matchingIdSubQuery.getSelectClause().addSqlSelection( new SqlSelectionImpl( 1, 0, fkTargetColumnExpression ) ); matchingIdSubQuery.getFromClause().addRoot( - new MutatingTableReferenceGroupWrapper( - new NavigablePath( attributeMapping.getRootPathName() ), - attributeMapping, - sqmInterpretation.getSqlAst().getTargetTable() - ) + tableGroup ); matchingIdSubQuery.applyPredicate( sqmInterpretation.getSqlAst().getRestriction() ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/MatchingIdSelectionHelper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/MatchingIdSelectionHelper.java index 325845f933..6483d7d5cf 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/MatchingIdSelectionHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/MatchingIdSelectionHelper.java @@ -18,13 +18,16 @@ import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment; import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.internal.FilterHelper; +import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.model.domain.EntityDomainType; import org.hibernate.persister.entity.Joinable; import org.hibernate.query.spi.DomainQueryExecutionContext; import org.hibernate.query.sqm.internal.DomainParameterXref; import org.hibernate.query.sqm.internal.SqmJdbcExecutionContextAdapter; import org.hibernate.query.sqm.internal.SqmUtil; +import org.hibernate.query.sqm.sql.internal.SqlAstQueryPartProcessingStateImpl; import org.hibernate.query.sqm.tree.SqmDeleteOrUpdateStatement; import org.hibernate.query.sqm.tree.expression.SqmParameter; import org.hibernate.sql.ast.SqlAstJoinType; @@ -89,34 +92,29 @@ public class MatchingIdSelectionHelper { idSelectionQuery.getFromClause().addRoot( mutatingTableGroup ); final List> domainResults = new ArrayList<>(); - - targetEntityDescriptor.getIdentifierMapping().forEachSelectable( - (position, selection) -> { - final TableReference tableReference = mutatingTableGroup.resolveTableReference( - mutatingTableGroup.getNavigablePath(), - selection.getContainingTableExpression() - ); - final Expression expression = sqmConverter.getSqlExpressionResolver().resolveSqlExpression( - SqlExpressionResolver.createColumnReferenceKey( tableReference, selection.getSelectionExpression() ), - sqlAstProcessingState -> new ColumnReference( - tableReference, - selection, - sessionFactory + sqmConverter.getProcessingStateStack().push( + new SqlAstQueryPartProcessingStateImpl( + idSelectionQuery, + sqmConverter.getCurrentProcessingState(), + sqmConverter.getSqlAstCreationState(), + sqmConverter.getCurrentClauseStack()::getCurrent + ) + ); + targetEntityDescriptor.getIdentifierMapping().applySqlSelections( + mutatingTableGroup.getNavigablePath(), + mutatingTableGroup, + sqmConverter, + (selection, jdbcMapping) -> { + domainResults.add( + new BasicResult<>( + selection.getValuesArrayPosition(), + null, + jdbcMapping.getJavaTypeDescriptor() ) ); - idSelectionQuery.getSelectClause().addSqlSelection( - new SqlSelectionImpl( - position, - position + 1, - expression - ) - ); - - //noinspection unchecked - domainResults.add( new BasicResult( position, null, selection.getJdbcMapping().getJavaTypeDescriptor() ) ); - } ); + sqmConverter.getProcessingStateStack().pop(); final FilterPredicate filterPredicate = FilterHelper.createFilterPredicate( executionContext.getSession().getLoadQueryInfluencers(), @@ -237,6 +235,46 @@ public class MatchingIdSelectionHelper { factory ); + sqmConverter.getProcessingStateStack().push( + new SqlAstQueryPartProcessingStateImpl( + matchingIdSelection.getQuerySpec(), + sqmConverter.getCurrentProcessingState(), + sqmConverter.getSqlAstCreationState(), + sqmConverter.getCurrentClauseStack()::getCurrent + ) + ); + entityDescriptor.visitSubTypeAttributeMappings( + attribute -> { + if ( attribute instanceof PluralAttributeMapping ) { + final PluralAttributeMapping pluralAttribute = (PluralAttributeMapping) attribute; + + if ( pluralAttribute.getSeparateCollectionTable() != null ) { + // Ensure that the FK target columns are available + final boolean useFkTarget = !( pluralAttribute.getKeyDescriptor() + .getTargetPart() instanceof EntityIdentifierMapping ); + if ( useFkTarget ) { + final TableGroup mutatingTableGroup = sqmConverter.getMutatingTableGroup(); + pluralAttribute.getKeyDescriptor().getTargetPart().applySqlSelections( + mutatingTableGroup.getNavigablePath(), + mutatingTableGroup, + sqmConverter, + (selection, jdbcMapping) -> { + matchingIdSelection.getDomainResultDescriptors().add( + new BasicResult<>( + selection.getValuesArrayPosition(), + null, + jdbcMapping.getJavaTypeDescriptor() + ) + ); + } + ); + } + } + } + } + ); + sqmConverter.getProcessingStateStack().pop(); + final JdbcServices jdbcServices = factory.getJdbcServices(); final JdbcEnvironment jdbcEnvironment = jdbcServices.getJdbcEnvironment(); final SqlAstTranslator sqlAstSelectTranslator = jdbcEnvironment diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMutationStrategyHelper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMutationStrategyHelper.java index 02b3c4c081..ef1ed2d474 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMutationStrategyHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/SqmMutationStrategyHelper.java @@ -71,7 +71,7 @@ public class SqmMutationStrategyHelper { return; } - entityDescriptor.visitAttributeMappings( + entityDescriptor.visitSubTypeAttributeMappings( attributeMapping -> { if ( attributeMapping instanceof PluralAttributeMapping ) { cleanUpCollectionTable( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/AbstractCteMutationHandler.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/AbstractCteMutationHandler.java index 928a1e8483..e58e66e364 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/AbstractCteMutationHandler.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/AbstractCteMutationHandler.java @@ -20,6 +20,7 @@ import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.MappingModelExpressable; +import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.SqlExpressable; import org.hibernate.query.spi.DomainQueryExecutionContext; import org.hibernate.query.sqm.internal.DomainParameterXref; @@ -203,6 +204,7 @@ public abstract class AbstractCteMutationHandler extends AbstractMutationHandler lockOptions.setAliasSpecificLockMode( explicitDmlTargetAlias, LockMode.WRITE ); final JdbcSelect select = translator.translate( jdbcParameterBindings, executionContext.getQueryOptions() ); lockOptions.setAliasSpecificLockMode( explicitDmlTargetAlias, lockMode ); + executionContext.getSession().autoFlushIfRequired( select.getAffectedTableNames() ); List list = jdbcServices.getJdbcSelectExecutor().list( select, jdbcParameterBindings, @@ -230,6 +232,14 @@ public abstract class AbstractCteMutationHandler extends AbstractMutationHandler List lhsExpressions, CteStatement idSelectCte, SessionFactoryImplementor factory) { + return createIdSubQueryPredicate( lhsExpressions, idSelectCte, null, factory ); + } + + protected Predicate createIdSubQueryPredicate( + List lhsExpressions, + CteStatement idSelectCte, + ModelPart fkModelPart, + SessionFactoryImplementor factory) { final TableReference idSelectTableReference = new TableReference( idSelectCte.getCteTable().getTableExpression(), CTE_TABLE_IDENTIFIER, @@ -238,23 +248,43 @@ public abstract class AbstractCteMutationHandler extends AbstractMutationHandler ); final Junction predicate = new Junction( Junction.Nature.CONJUNCTION ); final List cteColumns = idSelectCte.getCteTable().getCteColumns(); - final int size = cteColumns.size(); + final int size = lhsExpressions.size(); final QuerySpec subQuery = new QuerySpec( false, 1 ); subQuery.getFromClause().addRoot( new CteTableGroup( idSelectTableReference ) ); final SelectClause subQuerySelectClause = subQuery.getSelectClause(); - for ( int i = 0; i < size; i++ ) { - final CteColumn cteColumn = cteColumns.get( i ); - subQuerySelectClause.addSqlSelection( - new SqlSelectionImpl( - i + 1, - i, - new ColumnReference( - idSelectTableReference, - cteColumn.getColumnExpression(), - cteColumn.getJdbcMapping(), - factory - ) - ) + if ( fkModelPart == null ) { + for ( int i = 0; i < size; i++ ) { + final CteColumn cteColumn = cteColumns.get( i ); + subQuerySelectClause.addSqlSelection( + new SqlSelectionImpl( + i + 1, + i, + new ColumnReference( + idSelectTableReference, + cteColumn.getColumnExpression(), + cteColumn.getJdbcMapping(), + factory + ) + ) + ); + } + } + else { + fkModelPart.forEachSelectable( + (selectionIndex, selectableMapping) -> { + subQuerySelectClause.addSqlSelection( + new SqlSelectionImpl( + selectionIndex + 1, + selectionIndex, + new ColumnReference( + idSelectTableReference, + selectableMapping.getSelectionExpression(), + selectableMapping.getJdbcMapping(), + factory + ) + ) + ); + } ); } final Expression lhs; diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteDeleteHandler.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteDeleteHandler.java index 0761ba2c05..4ce5a00d81 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteDeleteHandler.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/cte/CteDeleteHandler.java @@ -11,10 +11,12 @@ import java.util.List; import java.util.Map; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.query.sqm.internal.DomainParameterXref; import org.hibernate.query.sqm.mutation.internal.DeleteHandler; import org.hibernate.query.sqm.mutation.internal.MultiTableSqmMutationConverter; +import org.hibernate.query.sqm.sql.internal.SqlAstQueryPartProcessingStateImpl; import org.hibernate.query.sqm.tree.cte.SqmCteTable; import org.hibernate.query.sqm.tree.delete.SqmDeleteStatement; import org.hibernate.query.sqm.tree.expression.SqmParameter; @@ -27,6 +29,8 @@ import org.hibernate.sql.ast.tree.expression.ColumnReference; import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.from.TableGroup; import org.hibernate.sql.ast.tree.from.TableReference; +import org.hibernate.sql.ast.tree.select.SelectStatement; +import org.hibernate.sql.results.graph.basic.BasicResult; /** * Bulk-id delete handler that uses CTE and VALUES lists. @@ -53,12 +57,42 @@ public class CteDeleteHandler extends AbstractCteMutationHandler implements Dele Map> parameterResolutions, SessionFactoryImplementor factory) { final TableGroup updatingTableGroup = sqmConverter.getMutatingTableGroup(); - getEntityDescriptor().visitAttributeMappings( + final SelectStatement idSelectStatement = (SelectStatement) idSelectCte.getCteDefinition(); + sqmConverter.getProcessingStateStack().push( + new SqlAstQueryPartProcessingStateImpl( + idSelectStatement.getQuerySpec(), + sqmConverter.getCurrentProcessingState(), + sqmConverter.getSqlAstCreationState(), + sqmConverter.getCurrentClauseStack()::getCurrent + ) + ); + getEntityDescriptor().visitSubTypeAttributeMappings( attribute -> { if ( attribute instanceof PluralAttributeMapping ) { final PluralAttributeMapping pluralAttribute = (PluralAttributeMapping) attribute; if ( pluralAttribute.getSeparateCollectionTable() != null ) { + // Ensure that the FK target columns are available + final boolean useFkTarget = !( pluralAttribute.getKeyDescriptor() + .getTargetPart() instanceof EntityIdentifierMapping ); + if ( useFkTarget ) { + final TableGroup mutatingTableGroup = sqmConverter.getMutatingTableGroup(); + pluralAttribute.getKeyDescriptor().getTargetPart().applySqlSelections( + mutatingTableGroup.getNavigablePath(), + mutatingTableGroup, + sqmConverter, + (selection, jdbcMapping) -> { + idSelectStatement.getDomainResultDescriptors().add( + new BasicResult<>( + selection.getValuesArrayPosition(), + null, + jdbcMapping.getJavaTypeDescriptor() + ) + ); + } + ); + } + // this collection has a separate collection table, meaning it is one of: // 1) element-collection // 2) many-to-many @@ -68,7 +102,7 @@ public class CteDeleteHandler extends AbstractCteMutationHandler implements Dele // collection table final String tableExpression = pluralAttribute.getSeparateCollectionTable(); final CteTable dmlResultCte = new CteTable( - getCteTableName( tableExpression ), + getCteTableName( pluralAttribute ), idSelectCte.getCteTable().getCteColumns(), factory ); @@ -85,7 +119,12 @@ public class CteDeleteHandler extends AbstractCteMutationHandler implements Dele ); final MutationStatement dmlStatement = new DeleteStatement( dmlTableReference, - createIdSubQueryPredicate( columnReferences, idSelectCte, factory ), + createIdSubQueryPredicate( + columnReferences, + idSelectCte, + useFkTarget ? pluralAttribute.getKeyDescriptor().getTargetPart() : null, + factory + ), columnReferences ); statement.addCteStatement( new CteStatement( dmlResultCte, dmlStatement ) ); @@ -93,6 +132,7 @@ public class CteDeleteHandler extends AbstractCteMutationHandler implements Dele } } ); + sqmConverter.getProcessingStateStack().pop(); getEntityDescriptor().visitConstraintOrderedTables( (tableExpression, tableColumnsVisitationSupplier) -> { @@ -124,4 +164,12 @@ public class CteDeleteHandler extends AbstractCteMutationHandler implements Dele } ); } + + protected String getCteTableName(PluralAttributeMapping pluralAttribute) { + final String hibernateEntityName = pluralAttribute.findContainingEntityMapping().getEntityName(); + final String jpaEntityName = getSessionFactory().getJpaMetamodel().entity( hibernateEntityName ).getName(); + return DML_RESULT_TABLE_NAME_PREFIX + jpaEntityName + "_" + pluralAttribute.getRootPathName().substring( + hibernateEntityName.length() + 1 + ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithIdTableHelper.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithIdTableHelper.java index 5f1202baeb..ba87abfa63 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithIdTableHelper.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/ExecuteWithIdTableHelper.java @@ -19,6 +19,7 @@ import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.transaction.spi.IsolationDelegate; import org.hibernate.metamodel.mapping.BasicValuedMapping; import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.query.ComparisonOperator; import org.hibernate.query.NavigablePath; import org.hibernate.query.sqm.mutation.internal.MultiTableSqmMutationConverter; @@ -162,6 +163,15 @@ public final class ExecuteWithIdTableHelper { Function sessionUidAccess, EntityMappingType entityDescriptor, ExecutionContext executionContext) { + return createIdTableSelectQuerySpec( idTable, null, sessionUidAccess, entityDescriptor, executionContext ); + } + + public static QuerySpec createIdTableSelectQuerySpec( + IdTable idTable, + ModelPart fkModelPart, + Function sessionUidAccess, + EntityMappingType entityDescriptor, + ExecutionContext executionContext) { final QuerySpec querySpec = new QuerySpec( false ); final TableReference idTableReference = new TableReference( @@ -182,7 +192,7 @@ public final class ExecuteWithIdTableHelper { querySpec.getFromClause().addRoot( idTableGroup ); - applyIdTableSelections( querySpec, idTableReference, idTable, executionContext ); + applyIdTableSelections( querySpec, idTableReference, idTable, fkModelPart, executionContext ); applyIdTableRestrictions( querySpec, idTableReference, idTable, sessionUidAccess, executionContext ); return querySpec; @@ -192,34 +202,59 @@ public final class ExecuteWithIdTableHelper { QuerySpec querySpec, TableReference tableReference, IdTable idTable, + ModelPart fkModelPart, ExecutionContext executionContext) { - for ( int i = 0; i < idTable.getIdTableColumns().size(); i++ ) { - final IdTableColumn idTableColumn = idTable.getIdTableColumns().get( i ); - if ( idTableColumn != idTable.getSessionUidColumn() ) { - querySpec.getSelectClause().addSqlSelection( - new SqlSelectionImpl( - i + 1, - i, - new ColumnReference( - tableReference, - idTableColumn.getColumnName(), - false, - null, - null, - idTableColumn.getJdbcMapping(), - executionContext.getSession().getFactory() - ) - ) - ); + if ( fkModelPart == null ) { + final int size = idTable.getEntityDescriptor().getIdentifierMapping().getJdbcTypeCount(); + for ( int i = 0; i < size; i++ ) { + final IdTableColumn idTableColumn = idTable.getIdTableColumns().get( i ); + if ( idTableColumn != idTable.getSessionUidColumn() ) { + querySpec.getSelectClause().addSqlSelection( + new SqlSelectionImpl( + i + 1, + i, + new ColumnReference( + tableReference, + idTableColumn.getColumnName(), + false, + null, + null, + idTableColumn.getJdbcMapping(), + executionContext.getSession().getFactory() + ) + ) + ); + } } } + else { + fkModelPart.forEachSelectable( + (i, selectableMapping) -> { + querySpec.getSelectClause().addSqlSelection( + new SqlSelectionImpl( + i + 1, + i, + new ColumnReference( + tableReference, + selectableMapping.getSelectionExpression(), + false, + null, + null, + selectableMapping.getJdbcMapping(), + executionContext.getSession().getFactory() + ) + ) + ); + } + ); + } } private static void applyIdTableRestrictions( QuerySpec querySpec, TableReference idTableReference, IdTable idTable, - Function sessionUidAccess, + Function sessionUidAccess, ExecutionContext executionContext) { if ( idTable.getSessionUidColumn() != null ) { querySpec.applyPredicate( diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/IdTable.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/IdTable.java index d1d33c0ff1..389b2f4d43 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/IdTable.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/IdTable.java @@ -13,8 +13,12 @@ import java.util.function.Function; import org.hibernate.boot.model.relational.Exportable; import org.hibernate.dialect.Dialect; import org.hibernate.mapping.Contributable; +import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; +import org.hibernate.metamodel.mapping.ModelPart; +import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.persister.entity.Joinable; +import org.hibernate.sql.ast.tree.from.TableGroup; /** * @author Steve Ebersole @@ -51,6 +55,32 @@ public class IdTable implements Exportable, Contributable { ) ) ); + entityDescriptor.visitSubTypeAttributeMappings( + attribute -> { + if ( attribute instanceof PluralAttributeMapping ) { + final PluralAttributeMapping pluralAttribute = (PluralAttributeMapping) attribute; + + if ( pluralAttribute.getSeparateCollectionTable() != null ) { + // Ensure that the FK target columns are available + final ModelPart fkTarget = pluralAttribute.getKeyDescriptor().getTargetPart(); + if ( !( fkTarget instanceof EntityIdentifierMapping ) ) { + fkTarget.forEachSelectable( + (columnIndex, selection) -> columns.add( + new IdTableColumn( + this, + selection.getSelectionExpression(), + selection.getJdbcMapping(), + dialect.getTypeName( + selection.getJdbcMapping().getJdbcTypeDescriptor() + ) + ) + ) + ); + } + } + } + } + ); this.dialect = dialect; } diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/RestrictedDeleteExecutionDelegate.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/RestrictedDeleteExecutionDelegate.java index f915e76991..07784ef218 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/RestrictedDeleteExecutionDelegate.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/idtable/RestrictedDeleteExecutionDelegate.java @@ -24,6 +24,7 @@ import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.internal.FilterHelper; import org.hibernate.internal.util.MutableInteger; +import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.MappingModelExpressable; @@ -448,7 +449,7 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle executionContext ); - final QuerySpec idTableSubQuery = ExecuteWithIdTableHelper.createIdTableSelectQuerySpec( + final QuerySpec idTableIdentifierSubQuery = ExecuteWithIdTableHelper.createIdTableSelectQuerySpec( idTable, sessionUidAccess, entityDescriptor, @@ -459,14 +460,26 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle entityDescriptor, (tableReference, attributeMapping) -> { final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor(); - + final QuerySpec idTableFkSubQuery; + if ( fkDescriptor.getTargetPart() instanceof EntityIdentifierMapping ) { + idTableFkSubQuery = idTableIdentifierSubQuery; + } + else { + idTableFkSubQuery = ExecuteWithIdTableHelper.createIdTableSelectQuerySpec( + idTable, + fkDescriptor.getTargetPart(), + sessionUidAccess, + entityDescriptor, + executionContext + ); + } return new InSubQueryPredicate( MappingModelHelper.buildColumnReferenceExpression( fkDescriptor, null, sessionFactory ), - idTableSubQuery, + idTableFkSubQuery, false ); @@ -479,7 +492,7 @@ public class RestrictedDeleteExecutionDelegate implements TableBasedDeleteHandle (tableExpression, tableKeyColumnVisitationSupplier) -> deleteFromTableUsingIdTable( tableExpression, tableKeyColumnVisitationSupplier, - idTableSubQuery, + idTableIdentifierSubQuery, executionContext ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InPredicateRestrictionProducer.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InPredicateRestrictionProducer.java index e64ec699c8..6da2c40662 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InPredicateRestrictionProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InPredicateRestrictionProducer.java @@ -13,6 +13,7 @@ import java.util.function.Supplier; import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.metamodel.mapping.BasicValuedModelPart; +import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.SelectableConsumer; import org.hibernate.metamodel.mapping.EntityIdentifierMapping; import org.hibernate.metamodel.mapping.EntityMappingType; @@ -48,6 +49,8 @@ public class InPredicateRestrictionProducer implements MatchingIdRestrictionProd public InListPredicate produceRestriction( List matchingIdValues, EntityMappingType entityDescriptor, + int valueIndex, + ModelPart valueModelPart, TableReference mutatingTableReference, Supplier> columnsToMatchVisitationSupplier, ExecutionContext executionContext) { diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InlineDeleteHandler.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InlineDeleteHandler.java index 5bb2c2ab26..5c28f74fcf 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InlineDeleteHandler.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/InlineDeleteHandler.java @@ -12,6 +12,10 @@ import java.util.function.Consumer; import java.util.function.Supplier; import org.hibernate.engine.spi.SessionFactoryImplementor; +import org.hibernate.internal.util.MutableInteger; +import org.hibernate.metamodel.mapping.EntityIdentifierMapping; +import org.hibernate.metamodel.mapping.ModelPart; +import org.hibernate.metamodel.mapping.SelectableConsumer; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.PluralAttributeMapping; import org.hibernate.metamodel.mapping.SelectableConsumer; @@ -69,13 +73,13 @@ public class InlineDeleteHandler implements DeleteHandler { @Override public int execute(DomainQueryExecutionContext executionContext) { - final List ids = MatchingIdSelectionHelper.selectMatchingIds( + final List idsAndFks = MatchingIdSelectionHelper.selectMatchingIds( sqmDeleteStatement, domainParameterXref, executionContext ); - if ( ids == null || ids.isEmpty() ) { + if ( idsAndFks == null || idsAndFks.isEmpty() ) { return 0; } @@ -87,8 +91,8 @@ public class InlineDeleteHandler implements DeleteHandler { final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl( domainParameterXref.getQueryParameterCount() ); // delete from the tables - - entityDescriptor.visitAttributeMappings( + final MutableInteger valueIndexCounter = new MutableInteger(); + entityDescriptor.visitSubTypeAttributeMappings( attribute -> { if ( attribute instanceof PluralAttributeMapping ) { final PluralAttributeMapping pluralAttribute = (PluralAttributeMapping) attribute; @@ -101,18 +105,29 @@ public class InlineDeleteHandler implements DeleteHandler { // // in all of these cases, we should clean up the matching rows in the // collection table + final ModelPart fkTargetPart = pluralAttribute.getKeyDescriptor().getTargetPart(); + final int valueIndex; + if ( fkTargetPart instanceof EntityIdentifierMapping ) { + valueIndex = 0; + } + else { + if ( valueIndexCounter.get() == 0 ) { + valueIndexCounter.set( entityDescriptor.getIdentifierMapping().getJdbcTypeCount() ); + } + valueIndex = valueIndexCounter.get(); + valueIndexCounter.plus( fkTargetPart.getJdbcTypeCount() ); + } -// todo (6.0) : implement this -// executeDelete( -// pluralAttribute.getSeparateCollectionTable(), -// matchingIdsPredicateProducer.produceRestriction( -// ids, -// () -> columnConsumer -> , -// executionContext -// ), -// jdbcParameterBindings, -// executionContext -// ); + executeDelete( + pluralAttribute.getSeparateCollectionTable(), + entityDescriptor, + () -> fkTargetPart::forEachSelectable, + idsAndFks, + valueIndex, + fkTargetPart, + jdbcParameterBindings, + executionContext + ); } } } @@ -124,14 +139,16 @@ public class InlineDeleteHandler implements DeleteHandler { tableExpression, entityDescriptor, tableKeyColumnsVisitationSupplier, - ids, + idsAndFks, + 0, + null, jdbcParameterBindings, executionContext ); } ); - return ids.size(); + return idsAndFks.size(); } private void executeDelete( @@ -139,6 +156,8 @@ public class InlineDeleteHandler implements DeleteHandler { EntityMappingType entityDescriptor, Supplier> tableKeyColumnsVisitationSupplier, List ids, + int valueIndex, + ModelPart valueModelPart, JdbcParameterBindings jdbcParameterBindings, DomainQueryExecutionContext executionContext) { final TableReference targetTableReference = new TableReference( @@ -153,6 +172,8 @@ public class InlineDeleteHandler implements DeleteHandler { final Predicate matchingIdsPredicate = matchingIdsPredicateProducer.produceRestriction( ids, entityDescriptor, + valueIndex, + valueModelPart, targetTableReference, tableKeyColumnsVisitationSupplier, executionContextAdapter diff --git a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/MatchingIdRestrictionProducer.java b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/MatchingIdRestrictionProducer.java index 506f1c20b6..b44771501c 100644 --- a/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/MatchingIdRestrictionProducer.java +++ b/hibernate-core/src/main/java/org/hibernate/query/sqm/mutation/internal/inline/MatchingIdRestrictionProducer.java @@ -10,6 +10,7 @@ import java.util.List; import java.util.function.Consumer; import java.util.function.Supplier; +import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.SelectableConsumer; import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.sql.ast.tree.from.TableReference; @@ -33,6 +34,8 @@ public interface MatchingIdRestrictionProducer { Predicate produceRestriction( List matchingIdValues, EntityMappingType entityDescriptor, + int valueIndex, + ModelPart valueModelPart, TableReference mutatingTableReference, Supplier> columnsToMatchVisitationSupplier, ExecutionContext executionContext); diff --git a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/TableGroup.java b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/TableGroup.java index 9a7693646f..b77b2adde2 100644 --- a/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/TableGroup.java +++ b/hibernate-core/src/main/java/org/hibernate/sql/ast/tree/from/TableGroup.java @@ -9,6 +9,8 @@ package org.hibernate.sql.ast.tree.from; import java.util.List; import java.util.function.Consumer; +import org.hibernate.metamodel.mapping.EntityValuedModelPart; +import org.hibernate.metamodel.mapping.ModelPart; import org.hibernate.metamodel.mapping.ModelPartContainer; import org.hibernate.query.NavigablePath; import org.hibernate.query.sqm.sql.internal.DomainResultProducer; @@ -68,7 +70,15 @@ public interface TableGroup extends SqlAstNode, ColumnReferenceQualifier, SqmPat @Override default void applySqlSelections(DomainResultCreationState creationState) { - getModelPart().applySqlSelections( + final ModelPartContainer modelPart = getModelPart(); + final ModelPart modelPartToApply; + if ( modelPart instanceof EntityValuedModelPart ) { + modelPartToApply = ( (EntityValuedModelPart) modelPart ).getEntityMappingType(); + } + else { + modelPartToApply = modelPart; + } + modelPartToApply.applySqlSelections( getNavigablePath(), creationState.getSqlAstCreationState().getFromClauseAccess().findTableGroup( getNavigablePath() ), creationState diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/cfg/persister/GoofyPersisterClassProvider.java b/hibernate-core/src/test/java/org/hibernate/orm/test/cfg/persister/GoofyPersisterClassProvider.java index dca50cd166..57be1653cf 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/cfg/persister/GoofyPersisterClassProvider.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/cfg/persister/GoofyPersisterClassProvider.java @@ -700,7 +700,7 @@ public class GoofyPersisterClassProvider implements PersisterClassResolver { } @Override - public void visitAttributeMappings(Consumer action) { + public void visitAttributeMappings(Consumer action) { } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/PersisterClassProviderTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/PersisterClassProviderTest.java index 75336643ff..bb447af765 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/PersisterClassProviderTest.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/jpa/ejb3configuration/PersisterClassProviderTest.java @@ -714,7 +714,7 @@ public class PersisterClassProviderTest { } @Override - public void visitAttributeMappings(Consumer action) { + public void visitAttributeMappings(Consumer action) { } diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/legacy/CustomPersister.java b/hibernate-core/src/test/java/org/hibernate/orm/test/legacy/CustomPersister.java index b8add1e636..45cee8678c 100644 --- a/hibernate-core/src/test/java/org/hibernate/orm/test/legacy/CustomPersister.java +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/legacy/CustomPersister.java @@ -815,7 +815,7 @@ public class CustomPersister implements EntityPersister { } @Override - public void visitAttributeMappings(Consumer action) { + public void visitAttributeMappings(Consumer action) { }