Skip to content

Commit adee718

Browse files
committed
HHH-18563 Add foreign key target tables to affected tables
1 parent 07393b5 commit adee718

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
@@ -21,6 +21,7 @@
2121
import org.hibernate.query.sqm.FetchClauseType;
2222
import org.hibernate.query.sqm.FrameExclusion;
2323
import org.hibernate.query.sqm.FrameKind;
24+
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
2425
import org.hibernate.sql.ast.Clause;
2526
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
2627
import org.hibernate.sql.ast.spi.SqlSelection;
@@ -52,6 +53,7 @@
5253
import org.hibernate.sql.ast.tree.select.QuerySpec;
5354
import org.hibernate.sql.ast.tree.select.SelectClause;
5455
import org.hibernate.sql.ast.tree.select.SortSpecification;
56+
import org.hibernate.sql.ast.tree.update.Assignable;
5557
import org.hibernate.sql.ast.tree.update.Assignment;
5658
import org.hibernate.sql.ast.tree.update.UpdateStatement;
5759
import org.hibernate.sql.exec.spi.JdbcOperation;
@@ -690,6 +692,13 @@ private boolean supportsOffsetFetchClause() {
690692

691693
@Override
692694
protected void visitSetAssignment(Assignment assignment) {
695+
final Assignable assignable = assignment.getAssignable();
696+
if ( assignable instanceof SqmPathInterpretation<?> ) {
697+
final String affectedTableName = ( (SqmPathInterpretation<?>) assignable ).getAffectedTableName();
698+
if ( affectedTableName != null ) {
699+
addAffectedTableName( affectedTableName );
700+
}
701+
}
693702
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
694703
if ( columnReferences.size() == 1 ) {
695704
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
@@ -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.SqlSelection;
2425
import org.hibernate.sql.ast.tree.Statement;
@@ -49,6 +50,7 @@
4950
import org.hibernate.sql.ast.tree.select.QuerySpec;
5051
import org.hibernate.sql.ast.tree.select.SelectClause;
5152
import org.hibernate.sql.ast.tree.select.SortSpecification;
53+
import org.hibernate.sql.ast.tree.update.Assignable;
5254
import org.hibernate.sql.ast.tree.update.Assignment;
5355
import org.hibernate.sql.ast.tree.update.UpdateStatement;
5456
import org.hibernate.sql.exec.spi.JdbcOperation;
@@ -633,6 +635,13 @@ private boolean supportsOffsetFetchClause() {
633635

634636
@Override
635637
protected void visitSetAssignment(Assignment assignment) {
638+
final Assignable assignable = assignment.getAssignable();
639+
if ( assignable instanceof SqmPathInterpretation<?> ) {
640+
final String affectedTableName = ( (SqmPathInterpretation<?>) assignable ).getAffectedTableName();
641+
if ( affectedTableName != null ) {
642+
addAffectedTableName( affectedTableName );
643+
}
644+
}
636645
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
637646
if ( columnReferences.size() == 1 ) {
638647
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
@@ -980,23 +980,39 @@ public List<Assignment> visitSetClause(SqmSetClause setClause) {
980980
targetColumnReferences = pathSqlExpression.getColumnReference().getColumnReferences();
981981
}
982982
if ( assignmentValueParameter != null ) {
983+
final ArrayList<Expression> expressions = new ArrayList<>( targetColumnReferences.size() );
983984
consumeSqmParameter(
984985
assignmentValueParameter,
985986
assignedPathInterpretation.getExpressionType(),
986-
(index, jdbcParameter) -> addAssignment(
987-
assignments,
988-
aggregateColumnAssignmentHandler,
989-
targetColumnReferences.get( index ),
990-
jdbcParameter
991-
)
987+
(index, jdbcParameter) -> expressions.add( jdbcParameter )
992988
);
989+
if ( pathSqlExpression instanceof SqlTuple ) {
990+
addAssignment(
991+
assignments,
992+
aggregateColumnAssignmentHandler,
993+
(Assignable) assignedPathInterpretation,
994+
targetColumnReferences,
995+
new SqlTuple( expressions, assignedPathInterpretation.getExpressionType() )
996+
);
997+
}
998+
else {
999+
assert expressions.size() == 1;
1000+
addAssignment(
1001+
assignments,
1002+
aggregateColumnAssignmentHandler,
1003+
(Assignable) assignedPathInterpretation,
1004+
targetColumnReferences,
1005+
expressions.get( 0 )
1006+
);
1007+
}
9931008
}
9941009
else if ( assignmentValue instanceof SqmLiteralNull<?> ) {
9951010
for ( ColumnReference columnReference : targetColumnReferences ) {
9961011
addAssignment(
9971012
assignments,
9981013
aggregateColumnAssignmentHandler,
9991014
columnReference,
1015+
targetColumnReferences,
10001016
new QueryLiteral<>( null, (BasicValuedMapping) columnReference.getExpressionType() )
10011017
);
10021018
}
@@ -1017,27 +1033,13 @@ else if ( assignmentValue instanceof SqmLiteralNull<?> ) {
10171033

10181034
assert assignedPathJdbcCount == valueExprJdbcCount;
10191035

1020-
if ( valueExpression instanceof SqlTuple ) {
1021-
final List<? extends Expression> expressions = ( (SqlTuple) valueExpression ).getExpressions();
1022-
assert targetColumnReferences.size() == expressions.size();
1023-
for ( int i = 0; i < targetColumnReferences.size(); i++ ) {
1024-
final ColumnReference columnReference = targetColumnReferences.get( i );
1025-
addAssignment( assignments, aggregateColumnAssignmentHandler, columnReference, expressions.get( i ) );
1026-
}
1027-
}
1028-
else if ( valueExpression instanceof EmbeddableValuedPathInterpretation<?> ) {
1029-
final List<? extends Expression> expressions = ( (EmbeddableValuedPathInterpretation<?>) valueExpression ).getSqlTuple().getExpressions();
1030-
assert targetColumnReferences.size() == expressions.size();
1031-
for ( int i = 0; i < targetColumnReferences.size(); i++ ) {
1032-
final ColumnReference columnReference = targetColumnReferences.get( i );
1033-
addAssignment( assignments, aggregateColumnAssignmentHandler, columnReference, expressions.get( i ) );
1034-
}
1035-
}
1036-
else {
1037-
for ( ColumnReference columnReference : targetColumnReferences ) {
1038-
addAssignment( assignments, aggregateColumnAssignmentHandler, columnReference, valueExpression );
1039-
}
1040-
}
1036+
addAssignment(
1037+
assignments,
1038+
aggregateColumnAssignmentHandler,
1039+
(Assignable) assignedPathInterpretation,
1040+
targetColumnReferences,
1041+
valueExpression
1042+
);
10411043
}
10421044
}
10431045
finally {
@@ -1056,12 +1058,15 @@ else if ( valueExpression instanceof EmbeddableValuedPathInterpretation<?> ) {
10561058
private void addAssignment(
10571059
List<Assignment> assignments,
10581060
AggregateColumnAssignmentHandler aggregateColumnAssignmentHandler,
1059-
ColumnReference columnReference,
1061+
Assignable assignable,
1062+
List<ColumnReference> targetColumnReferences,
10601063
Expression valueExpression) {
10611064
if ( aggregateColumnAssignmentHandler != null ) {
1062-
aggregateColumnAssignmentHandler.addAssignment( assignments.size(), columnReference );
1065+
for ( ColumnReference targetColumnReference : targetColumnReferences ) {
1066+
aggregateColumnAssignmentHandler.addAssignment( assignments.size(), targetColumnReference );
1067+
}
10631068
}
1064-
assignments.add( new Assignment( columnReference, valueExpression ) );
1069+
assignments.add( new Assignment( assignable, valueExpression ) );
10651070
}
10661071

10671072
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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
@@ -12,6 +12,7 @@
1212

1313
import org.hibernate.metamodel.MappingMetamodel;
1414
import org.hibernate.metamodel.mapping.BasicValuedModelPart;
15+
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
1516
import org.hibernate.metamodel.mapping.EntityMappingType;
1617
import org.hibernate.metamodel.mapping.MappingType;
1718
import org.hibernate.metamodel.mapping.ModelPart;
@@ -25,6 +26,7 @@
2526
import org.hibernate.query.sqm.tree.domain.SqmPath;
2627
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
2728
import org.hibernate.spi.NavigablePath;
29+
import org.hibernate.sql.ast.SqlAstTranslator;
2830
import org.hibernate.sql.ast.SqlAstWalker;
2931
import org.hibernate.sql.ast.tree.expression.ColumnReference;
3032
import org.hibernate.sql.ast.tree.expression.Expression;
@@ -33,6 +35,8 @@
3335
import org.hibernate.sql.ast.tree.from.TableReference;
3436
import org.hibernate.sql.ast.tree.update.Assignable;
3537

38+
import org.checkerframework.checker.nullness.qual.Nullable;
39+
3640
import static jakarta.persistence.metamodel.Type.PersistenceType.ENTITY;
3741
import static org.hibernate.internal.util.NullnessUtil.castNonNull;
3842
import static org.hibernate.query.sqm.internal.SqmUtil.getTargetMappingIfNeeded;
@@ -133,15 +137,37 @@ else if ( expression instanceof SqlSelectionExpression ) {
133137
}
134138

135139
private final ColumnReference columnReference;
140+
private final @Nullable String affectedTableName;
136141

137142
public BasicValuedPathInterpretation(
138143
ColumnReference columnReference,
139144
NavigablePath navigablePath,
140145
BasicValuedModelPart mapping,
141146
TableGroup tableGroup) {
147+
this( columnReference, navigablePath, mapping, tableGroup, determineAffectedTableName( tableGroup, mapping ) );
148+
}
149+
150+
private static @Nullable String determineAffectedTableName(TableGroup tableGroup, BasicValuedModelPart mapping) {
151+
final ModelPartContainer modelPart = tableGroup.getModelPart();
152+
if ( modelPart instanceof EntityAssociationMapping ) {
153+
final EntityAssociationMapping associationMapping = (EntityAssociationMapping) modelPart;
154+
if ( !associationMapping.containsTableReference( mapping.getContainingTableExpression() ) ) {
155+
return associationMapping.getAssociatedEntityMappingType().getMappedTableDetails().getTableName();
156+
}
157+
}
158+
return null;
159+
}
160+
161+
public BasicValuedPathInterpretation(
162+
ColumnReference columnReference,
163+
NavigablePath navigablePath,
164+
BasicValuedModelPart mapping,
165+
TableGroup tableGroup,
166+
@Nullable String affectedTableName) {
142167
super( navigablePath, mapping, tableGroup );
143168
assert columnReference != null;
144169
this.columnReference = columnReference;
170+
this.affectedTableName = affectedTableName;
145171
}
146172

147173
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -152,13 +178,21 @@ public Expression getSqlExpression() {
152178
return columnReference;
153179
}
154180

181+
@Override
182+
public @Nullable String getAffectedTableName() {
183+
return affectedTableName;
184+
}
185+
155186
@Override
156187
public ColumnReference getColumnReference() {
157188
return columnReference;
158189
}
159190

160191
@Override
161192
public void accept(SqlAstWalker sqlTreeWalker) {
193+
if ( affectedTableName != null && sqlTreeWalker instanceof SqlAstTranslator<?> ) {
194+
( (SqlAstTranslator<?>) sqlTreeWalker ).addAffectedTableName( affectedTableName );
195+
}
162196
columnReference.accept( sqlTreeWalker );
163197
}
164198

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
@@ -12,6 +12,7 @@
1212

1313
import org.hibernate.metamodel.MappingMetamodel;
1414
import org.hibernate.metamodel.mapping.EmbeddableValuedModelPart;
15+
import org.hibernate.metamodel.mapping.EntityAssociationMapping;
1516
import org.hibernate.metamodel.mapping.EntityMappingType;
1617
import org.hibernate.metamodel.mapping.ModelPartContainer;
1718
import org.hibernate.metamodel.model.domain.EntityDomainType;
@@ -20,6 +21,7 @@
2021
import org.hibernate.query.sqm.tree.domain.SqmPath;
2122
import org.hibernate.query.sqm.tree.domain.SqmTreatedPath;
2223
import org.hibernate.spi.NavigablePath;
24+
import org.hibernate.sql.ast.SqlAstTranslator;
2325
import org.hibernate.sql.ast.SqlAstWalker;
2426
import org.hibernate.sql.ast.tree.expression.ColumnReference;
2527
import org.hibernate.sql.ast.tree.expression.Expression;
@@ -28,6 +30,8 @@
2830
import org.hibernate.sql.ast.tree.from.TableGroup;
2931
import org.hibernate.sql.ast.tree.update.Assignable;
3032

33+
import org.checkerframework.checker.nullness.qual.Nullable;
34+
3135
import static jakarta.persistence.metamodel.Type.PersistenceType.ENTITY;
3236
import static org.hibernate.query.sqm.internal.SqmUtil.getTargetMappingIfNeeded;
3337

@@ -84,23 +88,53 @@ else if ( lhs.getNodeType() instanceof EntityDomainType ) {
8488
}
8589

8690
private final SqlTuple sqlExpression;
91+
private final @Nullable String affectedTableName;
8792

8893
public EmbeddableValuedPathInterpretation(
8994
SqlTuple sqlExpression,
9095
NavigablePath navigablePath,
9196
EmbeddableValuedModelPart mapping,
9297
TableGroup tableGroup) {
98+
this( sqlExpression, navigablePath, mapping, tableGroup, determineAffectedTableName( tableGroup, mapping ) );
99+
}
100+
101+
public EmbeddableValuedPathInterpretation(
102+
SqlTuple sqlExpression,
103+
NavigablePath navigablePath,
104+
EmbeddableValuedModelPart mapping,
105+
TableGroup tableGroup,
106+
@Nullable String affectedTableName) {
93107
super( navigablePath, mapping, tableGroup );
94108
this.sqlExpression = sqlExpression;
109+
this.affectedTableName = affectedTableName;
110+
}
111+
112+
private static @Nullable String determineAffectedTableName(TableGroup tableGroup, EmbeddableValuedModelPart mapping) {
113+
final ModelPartContainer modelPart = tableGroup.getModelPart();
114+
if ( modelPart instanceof EntityAssociationMapping ) {
115+
final EntityAssociationMapping associationMapping = (EntityAssociationMapping) modelPart;
116+
if ( !associationMapping.containsTableReference( mapping.getContainingTableExpression() ) ) {
117+
return associationMapping.getAssociatedEntityMappingType().getMappedTableDetails().getTableName();
118+
}
119+
}
120+
return null;
95121
}
96122

97123
@Override
98124
public SqlTuple getSqlExpression() {
99125
return sqlExpression;
100126
}
101127

128+
@Override
129+
public @Nullable String getAffectedTableName() {
130+
return affectedTableName;
131+
}
132+
102133
@Override
103134
public void accept(SqlAstWalker sqlTreeWalker) {
135+
if ( affectedTableName != null && sqlTreeWalker instanceof SqlAstTranslator<?> ) {
136+
( (SqlAstTranslator<?>) sqlTreeWalker ).addAffectedTableName( affectedTableName );
137+
}
104138
sqlExpression.accept( sqlTreeWalker );
105139
}
106140

0 commit comments

Comments
 (0)