HHH-17105 Include custom sql restriction in join table mutations

This commit is contained in:
Marco Belladelli 2023-08-25 10:53:55 +02:00
parent 5d33adadbc
commit 5635a33ab7
9 changed files with 126 additions and 23 deletions

View File

@ -1782,7 +1782,8 @@ public abstract class AbstractCollectionPersister
"one-shot delete for " + getRolePath(), "one-shot delete for " + getRolePath(),
keyRestrictionBindings, keyRestrictionBindings,
Collections.emptyList(), Collections.emptyList(),
parameterBinders parameterBinders,
sqlWhereString
); );
} }

View File

@ -458,7 +458,12 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
final PluralAttributeMapping attribute = getAttributeMapping(); final PluralAttributeMapping attribute = getAttributeMapping();
assert attribute != null; assert attribute != null;
final TableUpdateBuilderStandard<?> updateBuilder = new TableUpdateBuilderStandard<>( this, tableReference, getFactory() ); final TableUpdateBuilderStandard<?> updateBuilder = new TableUpdateBuilderStandard<>(
this,
tableReference,
getFactory(),
sqlWhereString
);
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// SET // SET
@ -667,7 +672,12 @@ public class BasicCollectionPersister extends AbstractCollectionPersister {
final ForeignKeyDescriptor fkDescriptor = pluralAttribute.getKeyDescriptor(); final ForeignKeyDescriptor fkDescriptor = pluralAttribute.getKeyDescriptor();
assert fkDescriptor != null; assert fkDescriptor != null;
final TableDeleteBuilderStandard deleteBuilder = new TableDeleteBuilderStandard( this, tableReference, getFactory() ); final TableDeleteBuilderStandard deleteBuilder = new TableDeleteBuilderStandard(
this,
tableReference,
getFactory(),
sqlWhereString
);
if ( pluralAttribute.getIdentifierDescriptor() != null ) { if ( pluralAttribute.getIdentifierDescriptor() != null ) {
deleteBuilder.addKeyRestrictionsLeniently( pluralAttribute.getIdentifierDescriptor() ); deleteBuilder.addKeyRestrictionsLeniently( pluralAttribute.getIdentifierDescriptor() );

View File

@ -564,7 +564,12 @@ public class OneToManyPersister extends AbstractCollectionPersister {
} }
public RestrictedTableMutation<JdbcMutationOperation> generateDeleteRowAst(MutatingTableReference tableReference) { public RestrictedTableMutation<JdbcMutationOperation> generateDeleteRowAst(MutatingTableReference tableReference) {
final TableUpdateBuilderStandard<MutationOperation> updateBuilder = new TableUpdateBuilderStandard<>( this, tableReference, getFactory() ); final TableUpdateBuilderStandard<MutationOperation> updateBuilder = new TableUpdateBuilderStandard<>(
this,
tableReference,
getFactory(),
sqlWhereString
);
// for each key column - // for each key column -
// 1) set the value to null // 1) set the value to null
@ -654,9 +659,14 @@ public class OneToManyPersister extends AbstractCollectionPersister {
} }
private TableUpdate<JdbcMutationOperation> buildTableUpdate(MutatingTableReference tableReference) { private TableUpdate<JdbcMutationOperation> buildTableUpdate(MutatingTableReference tableReference) {
final TableUpdateBuilderStandard<JdbcMutationOperation> updateBuilder = new TableUpdateBuilderStandard<>( this, tableReference, getFactory() ); final TableUpdateBuilderStandard<JdbcMutationOperation> updateBuilder = new TableUpdateBuilderStandard<>(
final PluralAttributeMapping attributeMapping = getAttributeMapping(); this,
tableReference,
getFactory(),
sqlWhereString
);
final PluralAttributeMapping attributeMapping = getAttributeMapping();
attributeMapping.getKeyDescriptor().getKeyPart().forEachSelectable( updateBuilder ); attributeMapping.getKeyDescriptor().getKeyPart().forEachSelectable( updateBuilder );
final CollectionPart indexDescriptor = attributeMapping.getIndexDescriptor(); final CollectionPart indexDescriptor = attributeMapping.getIndexDescriptor();
@ -757,7 +767,12 @@ public class OneToManyPersister extends AbstractCollectionPersister {
} }
private JdbcMutationOperation buildGeneratedWriteIndexOperation(MutatingTableReference tableReference) { private JdbcMutationOperation buildGeneratedWriteIndexOperation(MutatingTableReference tableReference) {
final TableUpdateBuilderStandard<JdbcMutationOperation> updateBuilder = new TableUpdateBuilderStandard<>( this, tableReference, getFactory() ); final TableUpdateBuilderStandard<JdbcMutationOperation> updateBuilder = new TableUpdateBuilderStandard<>(
this,
tableReference,
getFactory(),
sqlWhereString
);
final OneToManyCollectionPart elementDescriptor = (OneToManyCollectionPart) getAttributeMapping().getElementDescriptor(); final OneToManyCollectionPart elementDescriptor = (OneToManyCollectionPart) getAttributeMapping().getElementDescriptor();
updateBuilder.addKeyRestrictionsLeniently( elementDescriptor.getAssociatedEntityMappingType().getIdentifierMapping() ); updateBuilder.addKeyRestrictionsLeniently( elementDescriptor.getAssociatedEntityMappingType().getIdentifierMapping() );

View File

@ -10,9 +10,11 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import org.hibernate.action.internal.BulkOperationCleanupAction; import org.hibernate.action.internal.BulkOperationCleanupAction;
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
import org.hibernate.engine.jdbc.spi.JdbcServices; import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.MutableObject;
import org.hibernate.metamodel.mapping.EntityMappingType; import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor; import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
import org.hibernate.metamodel.mapping.MappingModelExpressible; import org.hibernate.metamodel.mapping.MappingModelExpressible;
@ -35,7 +37,9 @@ import org.hibernate.sql.ast.tree.expression.Expression;
import org.hibernate.sql.ast.tree.expression.JdbcParameter; import org.hibernate.sql.ast.tree.expression.JdbcParameter;
import org.hibernate.sql.ast.tree.from.MutatingTableReferenceGroupWrapper; import org.hibernate.sql.ast.tree.from.MutatingTableReferenceGroupWrapper;
import org.hibernate.sql.ast.tree.from.NamedTableReference; import org.hibernate.sql.ast.tree.from.NamedTableReference;
import org.hibernate.sql.ast.tree.from.TableGroup;
import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate; import org.hibernate.sql.ast.tree.predicate.InSubQueryPredicate;
import org.hibernate.sql.ast.tree.predicate.Predicate;
import org.hibernate.sql.ast.tree.select.QuerySpec; import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.exec.spi.JdbcOperationQueryDelete; import org.hibernate.sql.exec.spi.JdbcOperationQueryDelete;
import org.hibernate.sql.exec.spi.JdbcParameterBindings; import org.hibernate.sql.exec.spi.JdbcParameterBindings;
@ -136,17 +140,29 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
SqmMutationStrategyHelper.cleanUpCollectionTables( SqmMutationStrategyHelper.cleanUpCollectionTables(
entityDescriptor, entityDescriptor,
(tableReference, attributeMapping) -> { (tableReference, attributeMapping) -> {
final TableGroup collectionTableGroup = new MutatingTableReferenceGroupWrapper(
new NavigablePath( attributeMapping.getRootPathName() ),
attributeMapping,
(NamedTableReference) tableReference
);
final MutableObject<Predicate> additionalPredicate = new MutableObject<>();
attributeMapping.applyBaseRestrictions(
p -> additionalPredicate.set( Predicate.combinePredicates( additionalPredicate.get(), p ) ),
collectionTableGroup,
factory.getJdbcServices().getDialect().getDmlTargetColumnQualifierSupport() == DmlTargetColumnQualifierSupport.TABLE_ALIAS,
executionContext.getSession().getLoadQueryInfluencers().getEnabledFilters(),
null,
null
);
if ( missingRestriction ) { if ( missingRestriction ) {
return null; return additionalPredicate.get();
} }
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor(); final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();
final Expression fkColumnExpression = MappingModelCreationHelper.buildColumnReferenceExpression( final Expression fkColumnExpression = MappingModelCreationHelper.buildColumnReferenceExpression(
new MutatingTableReferenceGroupWrapper( collectionTableGroup,
new NavigablePath( attributeMapping.getRootPathName() ),
attributeMapping,
(NamedTableReference) tableReference
),
fkDescriptor.getKeyPart(), fkDescriptor.getKeyPart(),
null, null,
factory factory
@ -178,7 +194,10 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
session session
) ); ) );
return new InSubQueryPredicate( fkColumnExpression, matchingIdSubQuery, false ); return Predicate.combinePredicates(
additionalPredicate.get(),
new InSubQueryPredicate( fkColumnExpression, matchingIdSubQuery, false )
);
}, },
( missingRestriction ? JdbcParameterBindings.NO_BINDINGS : jdbcParameterBindings ), ( missingRestriction ? JdbcParameterBindings.NO_BINDINGS : jdbcParameterBindings ),
executionContextAdapter executionContextAdapter

View File

@ -8126,6 +8126,10 @@ public abstract class AbstractSqlAstTranslator<T extends JdbcOperation> implemen
} }
} ); } );
} }
if ( tableDelete.getWhereFragment() != null ) {
sqlBuffer.append( " and (" ).append( tableDelete.getWhereFragment() ).append( ")" );
}
} }
finally { finally {
getCurrentClauseStack().pop(); getCurrentClauseStack().pop();

View File

@ -6,15 +6,12 @@
*/ */
package org.hibernate.sql.model.ast.builder; package org.hibernate.sql.model.ast.builder;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.sql.model.MutationTarget; import org.hibernate.sql.model.MutationTarget;
import org.hibernate.sql.model.MutationType; import org.hibernate.sql.model.MutationType;
import org.hibernate.sql.model.TableMapping; import org.hibernate.sql.model.TableMapping;
import org.hibernate.sql.model.ast.ColumnValueParameter;
import org.hibernate.sql.model.ast.MutatingTableReference; import org.hibernate.sql.model.ast.MutatingTableReference;
import org.hibernate.sql.model.ast.TableDelete; import org.hibernate.sql.model.ast.TableDelete;
import org.hibernate.sql.model.internal.TableDeleteCustomSql; import org.hibernate.sql.model.internal.TableDeleteCustomSql;
@ -34,21 +31,32 @@ public class TableDeleteBuilderStandard
private String sqlComment; private String sqlComment;
private final String whereFragment;
public TableDeleteBuilderStandard( public TableDeleteBuilderStandard(
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
TableMapping table, TableMapping table,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
this( mutationTarget, new MutatingTableReference( table ), sessionFactory ); this( mutationTarget, new MutatingTableReference( table ), sessionFactory, null );
} }
public TableDeleteBuilderStandard( public TableDeleteBuilderStandard(
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
MutatingTableReference tableReference, MutatingTableReference tableReference,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
this( mutationTarget, tableReference, sessionFactory, null );
}
public TableDeleteBuilderStandard(
MutationTarget<?> mutationTarget,
MutatingTableReference tableReference,
SessionFactoryImplementor sessionFactory,
String whereFragment) {
super( MutationType.DELETE, mutationTarget, tableReference, sessionFactory ); super( MutationType.DELETE, mutationTarget, tableReference, sessionFactory );
this.isCustomSql = tableReference.getTableMapping().getDeleteDetails().getCustomSql() != null; this.isCustomSql = tableReference.getTableMapping().getDeleteDetails().getCustomSql() != null;
this.sqlComment = "delete for " + mutationTarget.getRolePath(); this.sqlComment = "delete for " + mutationTarget.getRolePath();
this.whereFragment = whereFragment;
} }
public String getSqlComment() { public String getSqlComment() {
@ -98,7 +106,8 @@ public class TableDeleteBuilderStandard
sqlComment, sqlComment,
getKeyRestrictionBindings(), getKeyRestrictionBindings(),
getOptimisticLockBindings(), getOptimisticLockBindings(),
getParameters() getParameters(),
whereFragment
); );
} }
} }

View File

@ -8,7 +8,9 @@ package org.hibernate.sql.model.ast.builder;
import java.util.List; import java.util.List;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.sql.model.MutationOperation; import org.hibernate.sql.model.MutationOperation;
import org.hibernate.sql.model.MutationTarget; import org.hibernate.sql.model.MutationTarget;
import org.hibernate.sql.model.TableMapping; import org.hibernate.sql.model.TableMapping;
@ -26,19 +28,30 @@ import org.hibernate.sql.model.internal.TableUpdateStandard;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class TableUpdateBuilderStandard<O extends MutationOperation> extends AbstractTableUpdateBuilder<O> { public class TableUpdateBuilderStandard<O extends MutationOperation> extends AbstractTableUpdateBuilder<O> {
private final String whereFragment;
public TableUpdateBuilderStandard( public TableUpdateBuilderStandard(
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
TableMapping tableMapping, TableMapping tableMapping,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
super( mutationTarget, tableMapping, sessionFactory ); super( mutationTarget, tableMapping, sessionFactory );
this.whereFragment = null;
} }
public TableUpdateBuilderStandard( public TableUpdateBuilderStandard(
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
MutatingTableReference tableReference, MutatingTableReference tableReference,
SessionFactoryImplementor sessionFactory) { SessionFactoryImplementor sessionFactory) {
this( mutationTarget, tableReference, sessionFactory, null );
}
public TableUpdateBuilderStandard(
MutationTarget<?> mutationTarget,
MutatingTableReference tableReference,
SessionFactoryImplementor sessionFactory,
String whereFragment) {
super( mutationTarget, tableReference, sessionFactory ); super( mutationTarget, tableReference, sessionFactory );
this.whereFragment = whereFragment;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -76,7 +89,9 @@ public class TableUpdateBuilderStandard<O extends MutationOperation> extends Abs
getSqlComment(), getSqlComment(),
valueBindings, valueBindings,
getKeyRestrictionBindings(), getKeyRestrictionBindings(),
getOptimisticLockBindings() getOptimisticLockBindings(),
whereFragment,
null
); );
} }
} }

View File

@ -19,6 +19,8 @@ import org.hibernate.sql.model.ast.MutatingTableReference;
* @author Steve Ebersole * @author Steve Ebersole
*/ */
public class TableDeleteStandard extends AbstractTableDelete { public class TableDeleteStandard extends AbstractTableDelete {
private final String whereFragment;
public TableDeleteStandard( public TableDeleteStandard(
MutatingTableReference mutatingTable, MutatingTableReference mutatingTable,
MutationTarget<?> mutationTarget, MutationTarget<?> mutationTarget,
@ -26,7 +28,23 @@ public class TableDeleteStandard extends AbstractTableDelete {
List<ColumnValueBinding> keyRestrictionBindings, List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings, List<ColumnValueBinding> optLockRestrictionBindings,
List<ColumnValueParameter> parameters) { List<ColumnValueParameter> parameters) {
this( mutatingTable, mutationTarget, sqlComment, keyRestrictionBindings, optLockRestrictionBindings, parameters, null );
}
public TableDeleteStandard(
MutatingTableReference mutatingTable,
MutationTarget<?> mutationTarget,
String sqlComment,
List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings,
List<ColumnValueParameter> parameters,
String whereFragment) {
super( mutatingTable, mutationTarget, sqlComment, keyRestrictionBindings, optLockRestrictionBindings, parameters ); super( mutatingTable, mutationTarget, sqlComment, keyRestrictionBindings, optLockRestrictionBindings, parameters );
this.whereFragment = whereFragment;
}
public String getWhereFragment() {
return whereFragment;
} }
@Override @Override

View File

@ -32,9 +32,21 @@ public class TableUpdateStandard extends AbstractTableUpdate<JdbcMutationOperati
List<ColumnValueBinding> valueBindings, List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings, List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings) { List<ColumnValueBinding> optLockRestrictionBindings) {
this( mutatingTable, mutationTarget, sqlComment, valueBindings, keyRestrictionBindings, optLockRestrictionBindings, null, null );
}
public TableUpdateStandard(
MutatingTableReference mutatingTable,
MutationTarget<?> mutationTarget,
String sqlComment,
List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings,
List<ColumnValueBinding> optLockRestrictionBindings,
String whereFragment,
Expectation expectation) {
super( mutatingTable, mutationTarget, sqlComment, valueBindings, keyRestrictionBindings, optLockRestrictionBindings ); super( mutatingTable, mutationTarget, sqlComment, valueBindings, keyRestrictionBindings, optLockRestrictionBindings );
this.whereFragment = null; this.whereFragment = whereFragment;
this.expectation = null; this.expectation = expectation;
} }
public TableUpdateStandard( public TableUpdateStandard(