Skip to content

Commit 8c8ede3

Browse files
committed
HHH-18563 Add foreign key target tables to affected tables
1 parent 809c01f commit 8c8ede3

File tree

10 files changed

+215
-35
lines changed

10 files changed

+215
-35
lines changed

hibernate-community-dialects/src/main/java/org/hibernate/community/dialect/OracleLegacySqlAstTranslator.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import org.hibernate.query.sqm.FetchClauseType;
2020
import org.hibernate.query.sqm.FrameExclusion;
2121
import org.hibernate.query.sqm.FrameKind;
22+
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
2223
import org.hibernate.sql.ast.Clause;
2324
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
2425
import org.hibernate.sql.ast.spi.SqlSelection;
@@ -50,6 +51,7 @@
5051
import org.hibernate.sql.ast.tree.select.QuerySpec;
5152
import org.hibernate.sql.ast.tree.select.SelectClause;
5253
import org.hibernate.sql.ast.tree.select.SortSpecification;
54+
import org.hibernate.sql.ast.tree.update.Assignable;
5355
import org.hibernate.sql.ast.tree.update.Assignment;
5456
import org.hibernate.sql.ast.tree.update.UpdateStatement;
5557
import org.hibernate.sql.exec.spi.JdbcOperation;
@@ -678,6 +680,13 @@ private boolean supportsOffsetFetchClause() {
678680

679681
@Override
680682
protected void visitSetAssignment(Assignment assignment) {
683+
final Assignable assignable = assignment.getAssignable();
684+
if ( assignable instanceof SqmPathInterpretation<?> ) {
685+
final String affectedTableName = ( (SqmPathInterpretation<?>) assignable ).getAffectedTableName();
686+
if ( affectedTableName != null ) {
687+
addAffectedTableName( affectedTableName );
688+
}
689+
}
681690
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
682691
if ( columnReferences.size() == 1 ) {
683692
columnReferences.get( 0 ).appendColumnForWrite( this );

hibernate-core/src/main/java/org/hibernate/dialect/OracleSqlAstTranslator.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import org.hibernate.query.sqm.FetchClauseType;
1818
import org.hibernate.query.sqm.FrameExclusion;
1919
import org.hibernate.query.sqm.FrameKind;
20+
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
2021
import org.hibernate.sql.ast.Clause;
2122
import org.hibernate.sql.ast.spi.SqlSelection;
2223
import org.hibernate.sql.ast.tree.Statement;
@@ -47,6 +48,7 @@
4748
import org.hibernate.sql.ast.tree.select.QuerySpec;
4849
import org.hibernate.sql.ast.tree.select.SelectClause;
4950
import org.hibernate.sql.ast.tree.select.SortSpecification;
51+
import org.hibernate.sql.ast.tree.update.Assignable;
5052
import org.hibernate.sql.ast.tree.update.Assignment;
5153
import org.hibernate.sql.ast.tree.update.UpdateStatement;
5254
import org.hibernate.sql.exec.spi.JdbcOperation;
@@ -621,6 +623,13 @@ private boolean supportsOffsetFetchClause() {
621623

622624
@Override
623625
protected void visitSetAssignment(Assignment assignment) {
626+
final Assignable assignable = assignment.getAssignable();
627+
if ( assignable instanceof SqmPathInterpretation<?> ) {
628+
final String affectedTableName = ( (SqmPathInterpretation<?>) assignable ).getAffectedTableName();
629+
if ( affectedTableName != null ) {
630+
addAffectedTableName( affectedTableName );
631+
}
632+
}
624633
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
625634
if ( columnReferences.size() == 1 ) {
626635
columnReferences.get( 0 ).appendColumnForWrite( this );

hibernate-core/src/main/java/org/hibernate/query/sqm/sql/BaseSqmToSqlAstConverter.java

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -977,23 +977,39 @@ public List<Assignment> visitSetClause(SqmSetClause setClause) {
977977
targetColumnReferences = pathSqlExpression.getColumnReference().getColumnReferences();
978978
}
979979
if ( assignmentValueParameter != null ) {
980+
final ArrayList<Expression> expressions = new ArrayList<>( targetColumnReferences.size() );
980981
consumeSqmParameter(
981982
assignmentValueParameter,
982983
assignedPathInterpretation.getExpressionType(),
983-
(index, jdbcParameter) -> addAssignment(
984-
assignments,
985-
aggregateColumnAssignmentHandler,
986-
targetColumnReferences.get( index ),
987-
jdbcParameter
988-
)
984+
(index, jdbcParameter) -> expressions.add( jdbcParameter )
989985
);
986+
if ( pathSqlExpression instanceof SqlTuple ) {
987+
addAssignment(
988+
assignments,
989+
aggregateColumnAssignmentHandler,
990+
(Assignable) assignedPathInterpretation,
991+
targetColumnReferences,
992+
new SqlTuple( expressions, assignedPathInterpretation.getExpressionType() )
993+
);
994+
}
995+
else {
996+
assert expressions.size() == 1;
997+
addAssignment(
998+
assignments,
999+
aggregateColumnAssignmentHandler,
1000+
(Assignable) assignedPathInterpretation,
1001+
targetColumnReferences,
1002+
expressions.get( 0 )
1003+
);
1004+
}
9901005
}
9911006
else if ( assignmentValue instanceof SqmLiteralNull<?> ) {
9921007
for ( ColumnReference columnReference : targetColumnReferences ) {
9931008
addAssignment(
9941009
assignments,
9951010
aggregateColumnAssignmentHandler,
9961011
columnReference,
1012+
targetColumnReferences,
9971013
new QueryLiteral<>( null, (BasicValuedMapping) columnReference.getExpressionType() )
9981014
);
9991015
}
@@ -1014,27 +1030,13 @@ else if ( assignmentValue instanceof SqmLiteralNull<?> ) {
10141030

10151031
assert assignedPathJdbcCount == valueExprJdbcCount;
10161032

1017-
if ( valueExpression instanceof SqlTuple ) {
1018-
final List<? extends Expression> expressions = ( (SqlTuple) valueExpression ).getExpressions();
1019-
assert targetColumnReferences.size() == expressions.size();
1020-
for ( int i = 0; i < targetColumnReferences.size(); i++ ) {
1021-
final ColumnReference columnReference = targetColumnReferences.get( i );
1022-
addAssignment( assignments, aggregateColumnAssignmentHandler, columnReference, expressions.get( i ) );
1023-
}
1024-
}
1025-
else if ( valueExpression instanceof EmbeddableValuedPathInterpretation<?> ) {
1026-
final List<? extends Expression> expressions = ( (EmbeddableValuedPathInterpretation<?>) valueExpression ).getSqlTuple().getExpressions();
1027-
assert targetColumnReferences.size() == expressions.size();
1028-
for ( int i = 0; i < targetColumnReferences.size(); i++ ) {
1029-
final ColumnReference columnReference = targetColumnReferences.get( i );
1030-
addAssignment( assignments, aggregateColumnAssignmentHandler, columnReference, expressions.get( i ) );
1031-
}
1032-
}
1033-
else {
1034-
for ( ColumnReference columnReference : targetColumnReferences ) {
1035-
addAssignment( assignments, aggregateColumnAssignmentHandler, columnReference, valueExpression );
1036-
}
1037-
}
1033+
addAssignment(
1034+
assignments,
1035+
aggregateColumnAssignmentHandler,
1036+
(Assignable) assignedPathInterpretation,
1037+
targetColumnReferences,
1038+
valueExpression
1039+
);
10381040
}
10391041
}
10401042
finally {
@@ -1053,12 +1055,15 @@ else if ( valueExpression instanceof EmbeddableValuedPathInterpretation<?> ) {
10531055
private void addAssignment(
10541056
List<Assignment> assignments,
10551057
AggregateColumnAssignmentHandler aggregateColumnAssignmentHandler,
1056-
ColumnReference columnReference,
1058+
Assignable assignable,
1059+
List<ColumnReference> targetColumnReferences,
10571060
Expression valueExpression) {
10581061
if ( aggregateColumnAssignmentHandler != null ) {
1059-
aggregateColumnAssignmentHandler.addAssignment( assignments.size(), columnReference );
1062+
for ( ColumnReference targetColumnReference : targetColumnReferences ) {
1063+
aggregateColumnAssignmentHandler.addAssignment( assignments.size(), targetColumnReference );
1064+
}
10601065
}
1061-
assignments.add( new Assignment( columnReference, valueExpression ) );
1066+
assignments.add( new Assignment( assignable, valueExpression ) );
10621067
}
10631068

10641069
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/BasicValuedPathInterpretation.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import org.hibernate.metamodel.MappingMetamodel;
1212
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
13+
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
1314
import org.hibernate.metamodel.mapping.EntityMappingType;
1415
import org.hibernate.metamodel.mapping.MappingType;
1516
import org.hibernate.metamodel.mapping.ModelPart;
@@ -23,6 +24,7 @@
2324
import org.hibernate.query.sqm.tree.domain.SqmPath;
2425
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
2526
import org.hibernate.spi.NavigablePath;
27+
import org.hibernate.sql.ast.SqlAstTranslator;
2628
import org.hibernate.sql.ast.SqlAstWalker;
2729
import org.hibernate.sql.ast.tree.expression.ColumnReference;
2830
import org.hibernate.sql.ast.tree.expression.Expression;
@@ -31,6 +33,8 @@
3133
import org.hibernate.sql.ast.tree.from.TableReference;
3234
import org.hibernate.sql.ast.tree.update.Assignable;
3335

36+
import org.checkerframework.checker.nullness.qual.Nullable;
37+
3438
import static jakarta.persistence.metamodel.Type.PersistenceType.ENTITY;
3539
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
3640
import static org.hibernate.query.sqm.internal.SqmUtil.getTargetMappingIfNeeded;
@@ -131,15 +135,37 @@ else if ( expression instanceof SqlSelectionExpression ) {
131135
}
132136

133137
private final ColumnReference columnReference;
138+
private final @Nullable String affectedTableName;
134139

135140
public BasicValuedPathInterpretation(
136141
ColumnReference columnReference,
137142
NavigablePath navigablePath,
138143
BasicValuedModelPart mapping,
139144
TableGroup tableGroup) {
145+
this( columnReference, navigablePath, mapping, tableGroup, determineAffectedTableName( tableGroup, mapping ) );
146+
}
147+
148+
private static @Nullable String determineAffectedTableName(TableGroup tableGroup, BasicValuedModelPart mapping) {
149+
final ModelPartContainer modelPart = tableGroup.getModelPart();
150+
if ( modelPart instanceof EntityAssociationMapping ) {
151+
final EntityAssociationMapping associationMapping = (EntityAssociationMapping) modelPart;
152+
if ( !associationMapping.containsTableReference( mapping.getContainingTableExpression() ) ) {
153+
return associationMapping.getAssociatedEntityMappingType().getMappedTableDetails().getTableName();
154+
}
155+
}
156+
return null;
157+
}
158+
159+
public BasicValuedPathInterpretation(
160+
ColumnReference columnReference,
161+
NavigablePath navigablePath,
162+
BasicValuedModelPart mapping,
163+
TableGroup tableGroup,
164+
@Nullable String affectedTableName) {
140165
super( navigablePath, mapping, tableGroup );
141166
assert columnReference != null;
142167
this.columnReference = columnReference;
168+
this.affectedTableName = affectedTableName;
143169
}
144170

145171
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -150,13 +176,21 @@ public Expression getSqlExpression() {
150176
return columnReference;
151177
}
152178

179+
@Override
180+
public @Nullable String getAffectedTableName() {
181+
return affectedTableName;
182+
}
183+
153184
@Override
154185
public ColumnReference getColumnReference() {
155186
return columnReference;
156187
}
157188

158189
@Override
159190
public void accept(SqlAstWalker sqlTreeWalker) {
191+
if ( affectedTableName != null && sqlTreeWalker instanceof SqlAstTranslator<?> ) {
192+
( (SqlAstTranslator<?>) sqlTreeWalker ).addAffectedTableName( affectedTableName );
193+
}
160194
columnReference.accept( sqlTreeWalker );
161195
}
162196

hibernate-core/src/main/java/org/hibernate/query/sqm/sql/internal/EmbeddableValuedPathInterpretation.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
import org.hibernate.metamodel.MappingMetamodel;
1212
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
13+
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
1314
import org.hibernate.metamodel.mapping.EntityMappingType;
1415
import org.hibernate.metamodel.mapping.ModelPartContainer;
1516
import org.hibernate.metamodel.model.domain.EntityDomainType;
@@ -18,6 +19,7 @@
1819
import org.hibernate.query.sqm.tree.domain.SqmPath;
1920
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
2021
import org.hibernate.spi.NavigablePath;
22+
import org.hibernate.sql.ast.SqlAstTranslator;
2123
import org.hibernate.sql.ast.SqlAstWalker;
2224
import org.hibernate.sql.ast.tree.expression.ColumnReference;
2325
import org.hibernate.sql.ast.tree.expression.Expression;
@@ -26,6 +28,8 @@
2628
import org.hibernate.sql.ast.tree.from.TableGroup;
2729
import org.hibernate.sql.ast.tree.update.Assignable;
2830

31+
import org.checkerframework.checker.nullness.qual.Nullable;
32+
2933
import static jakarta.persistence.metamodel.Type.PersistenceType.ENTITY;
3034
import static org.hibernate.query.sqm.internal.SqmUtil.getTargetMappingIfNeeded;
3135

@@ -82,23 +86,53 @@ else if ( lhs.getNodeType() instanceof EntityDomainType ) {
8286
}
8387

8488
private final SqlTuple sqlExpression;
89+
private final @Nullable String affectedTableName;
8590

8691
public EmbeddableValuedPathInterpretation(
8792
SqlTuple sqlExpression,
8893
NavigablePath navigablePath,
8994
EmbeddableValuedModelPart mapping,
9095
TableGroup tableGroup) {
96+
this( sqlExpression, navigablePath, mapping, tableGroup, determineAffectedTableName( tableGroup, mapping ) );
97+
}
98+
99+
public EmbeddableValuedPathInterpretation(
100+
SqlTuple sqlExpression,
101+
NavigablePath navigablePath,
102+
EmbeddableValuedModelPart mapping,
103+
TableGroup tableGroup,
104+
@Nullable String affectedTableName) {
91105
super( navigablePath, mapping, tableGroup );
92106
this.sqlExpression = sqlExpression;
107+
this.affectedTableName = affectedTableName;
108+
}
109+
110+
private static @Nullable String determineAffectedTableName(TableGroup tableGroup, EmbeddableValuedModelPart mapping) {
111+
final ModelPartContainer modelPart = tableGroup.getModelPart();
112+
if ( modelPart instanceof EntityAssociationMapping ) {
113+
final EntityAssociationMapping associationMapping = (EntityAssociationMapping) modelPart;
114+
if ( !associationMapping.containsTableReference( mapping.getContainingTableExpression() ) ) {
115+
return associationMapping.getAssociatedEntityMappingType().getMappedTableDetails().getTableName();
116+
}
117+
}
118+
return null;
93119
}
94120

95121
@Override
96122
public SqlTuple getSqlExpression() {
97123
return sqlExpression;
98124
}
99125

126+
@Override
127+
public @Nullable String getAffectedTableName() {
128+
return affectedTableName;
129+
}
130+
100131
@Override
101132
public void accept(SqlAstWalker sqlTreeWalker) {
133+
if ( affectedTableName != null && sqlTreeWalker instanceof SqlAstTranslator<?> ) {
134+
( (SqlAstTranslator<?>) sqlTreeWalker ).addAffectedTableName( affectedTableName );
135+
}
102136
sqlExpression.accept( sqlTreeWalker );
103137
}
104138

0 commit comments

Comments
 (0)