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(),
keyRestrictionBindings,
Collections.emptyList(),
parameterBinders
parameterBinders,
sqlWhereString
);
}

View File

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

View File

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

View File

@ -10,9 +10,11 @@ import java.util.List;
import java.util.Map;
import org.hibernate.action.internal.BulkOperationCleanupAction;
import org.hibernate.dialect.DmlTargetColumnQualifierSupport;
import org.hibernate.engine.jdbc.spi.JdbcServices;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.internal.util.MutableObject;
import org.hibernate.metamodel.mapping.EntityMappingType;
import org.hibernate.metamodel.mapping.ForeignKeyDescriptor;
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.from.MutatingTableReferenceGroupWrapper;
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.Predicate;
import org.hibernate.sql.ast.tree.select.QuerySpec;
import org.hibernate.sql.exec.spi.JdbcOperationQueryDelete;
import org.hibernate.sql.exec.spi.JdbcParameterBindings;
@ -136,17 +140,29 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
SqmMutationStrategyHelper.cleanUpCollectionTables(
entityDescriptor,
(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 ) {
return null;
return additionalPredicate.get();
}
final ForeignKeyDescriptor fkDescriptor = attributeMapping.getKeyDescriptor();
final Expression fkColumnExpression = MappingModelCreationHelper.buildColumnReferenceExpression(
new MutatingTableReferenceGroupWrapper(
new NavigablePath( attributeMapping.getRootPathName() ),
attributeMapping,
(NamedTableReference) tableReference
),
collectionTableGroup,
fkDescriptor.getKeyPart(),
null,
factory
@ -178,7 +194,10 @@ public class SimpleDeleteQueryPlan implements NonSelectQueryPlan {
session
) );
return new InSubQueryPredicate( fkColumnExpression, matchingIdSubQuery, false );
return Predicate.combinePredicates(
additionalPredicate.get(),
new InSubQueryPredicate( fkColumnExpression, matchingIdSubQuery, false )
);
},
( missingRestriction ? JdbcParameterBindings.NO_BINDINGS : jdbcParameterBindings ),
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 {
getCurrentClauseStack().pop();

View File

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

View File

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

View File

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

View File

@ -32,9 +32,21 @@ public class TableUpdateStandard extends AbstractTableUpdate<JdbcMutationOperati
List<ColumnValueBinding> valueBindings,
List<ColumnValueBinding> keyRestrictionBindings,
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 );
this.whereFragment = null;
this.expectation = null;
this.whereFragment = whereFragment;
this.expectation = expectation;
}
public TableUpdateStandard(