Skip to content

Commit 8252c8d

Browse files
committed
HHH-18563 Add foreign key target tables to affected tables
1 parent 866ddd6 commit 8252c8d

File tree

11 files changed

+221
-39
lines changed

11 files changed

+221
-39
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
@@ -22,6 +22,7 @@
2222
import org.hibernate.query.common.FetchClauseType;
2323
import org.hibernate.query.common.FrameExclusion;
2424
import org.hibernate.query.common.FrameKind;
25+
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
2526
import org.hibernate.sql.ast.Clause;
2627
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
2728
import org.hibernate.sql.ast.spi.AbstractSqlAstTranslator;
@@ -56,6 +57,7 @@
5657
import org.hibernate.sql.ast.tree.select.QuerySpec;
5758
import org.hibernate.sql.ast.tree.select.SelectClause;
5859
import org.hibernate.sql.ast.tree.select.SortSpecification;
60+
import org.hibernate.sql.ast.tree.update.Assignable;
5961
import org.hibernate.sql.ast.tree.update.Assignment;
6062
import org.hibernate.sql.ast.tree.update.UpdateStatement;
6163
import org.hibernate.sql.exec.spi.JdbcOperation;
@@ -717,6 +719,13 @@ private boolean supportsOffsetFetchClause() {
717719

718720
@Override
719721
protected void visitSetAssignment(Assignment assignment) {
722+
final Assignable assignable = assignment.getAssignable();
723+
if ( assignable instanceof SqmPathInterpretation<?> ) {
724+
final String affectedTableName = ( (SqmPathInterpretation<?>) assignable ).getAffectedTableName();
725+
if ( affectedTableName != null ) {
726+
addAffectedTableName( affectedTableName );
727+
}
728+
}
720729
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
721730
if ( columnReferences.size() == 1 ) {
722731
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
@@ -20,6 +20,7 @@
2020
import org.hibernate.query.common.FetchClauseType;
2121
import org.hibernate.query.common.FrameExclusion;
2222
import org.hibernate.query.common.FrameKind;
23+
import org.hibernate.query.sqm.sql.internal.SqmPathInterpretation;
2324
import org.hibernate.sql.ast.Clause;
2425
import org.hibernate.sql.ast.SqlAstNodeRenderingMode;
2526
import org.hibernate.sql.ast.spi.SqlSelection;
@@ -54,6 +55,7 @@
5455
import org.hibernate.sql.ast.tree.select.QuerySpec;
5556
import org.hibernate.sql.ast.tree.select.SelectClause;
5657
import org.hibernate.sql.ast.tree.select.SortSpecification;
58+
import org.hibernate.sql.ast.tree.update.Assignable;
5759
import org.hibernate.sql.ast.tree.update.Assignment;
5860
import org.hibernate.sql.ast.tree.update.UpdateStatement;
5961
import org.hibernate.sql.exec.spi.JdbcOperation;
@@ -670,6 +672,13 @@ private boolean supportsOffsetFetchClause() {
670672

671673
@Override
672674
protected void visitSetAssignment(Assignment assignment) {
675+
final Assignable assignable = assignment.getAssignable();
676+
if ( assignable instanceof SqmPathInterpretation<?> ) {
677+
final String affectedTableName = ( (SqmPathInterpretation<?>) assignable ).getAffectedTableName();
678+
if ( affectedTableName != null ) {
679+
addAffectedTableName( affectedTableName );
680+
}
681+
}
673682
final List<ColumnReference> columnReferences = assignment.getAssignable().getColumnReferences();
674683
if ( columnReferences.size() == 1 ) {
675684
columnReferences.get( 0 ).appendColumnForWrite( this );

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

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -977,31 +977,47 @@ public List<Assignment> visitSetClause(SqmSetClause setClause) {
977977
? (List<ColumnReference>) sqlTuple.getExpressions()
978978
: pathSqlExpression.getColumnReference().getColumnReferences();
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
}
10001016
}
10011017
else {
10021018
addAssignments(
10031019
(Expression) assignmentValue.accept( this ),
1004-
assignedPathInterpretation.getExpressionType(),
1020+
assignedPathInterpretation,
10051021
targetColumnReferences,
10061022
assignments,
10071023
aggregateColumnAssignmentHandler
@@ -1023,33 +1039,18 @@ else if ( assignmentValue instanceof SqmLiteralNull<?> ) {
10231039

10241040
private void addAssignments(
10251041
Expression valueExpression,
1026-
ModelPart assignedPathType,
1042+
SqmPathInterpretation<?> assignedPathInterpretation,
10271043
List<ColumnReference> targetColumnReferences,
10281044
ArrayList<Assignment> assignments,
10291045
AggregateColumnAssignmentHandler aggregateColumnAssignmentHandler) {
1030-
checkAssignment( valueExpression, assignedPathType );
1031-
1032-
if ( valueExpression instanceof SqlTuple sqlTuple ) {
1033-
final List<? extends Expression> expressions = sqlTuple.getExpressions();
1034-
assert targetColumnReferences.size() == expressions.size();
1035-
for ( int i = 0; i < targetColumnReferences.size(); i++ ) {
1036-
final ColumnReference columnReference = targetColumnReferences.get( i );
1037-
addAssignment( assignments, aggregateColumnAssignmentHandler, columnReference, expressions.get( i ) );
1038-
}
1039-
}
1040-
else if ( valueExpression instanceof EmbeddableValuedPathInterpretation<?> embeddable ) {
1041-
final List<? extends Expression> expressions = embeddable.getSqlTuple().getExpressions();
1042-
assert targetColumnReferences.size() == expressions.size();
1043-
for ( int i = 0; i < targetColumnReferences.size(); i++ ) {
1044-
final ColumnReference columnReference = targetColumnReferences.get( i );
1045-
addAssignment( assignments, aggregateColumnAssignmentHandler, columnReference, expressions.get( i ) );
1046-
}
1047-
}
1048-
else {
1049-
for ( ColumnReference columnReference : targetColumnReferences ) {
1050-
addAssignment( assignments, aggregateColumnAssignmentHandler, columnReference, valueExpression );
1051-
}
1052-
}
1046+
checkAssignment( valueExpression, assignedPathInterpretation.getExpressionType() );
1047+
addAssignment(
1048+
assignments,
1049+
aggregateColumnAssignmentHandler,
1050+
(Assignable) assignedPathInterpretation,
1051+
targetColumnReferences,
1052+
valueExpression
1053+
);
10531054
}
10541055

10551056
private void checkAssignment(Expression valueExpression, ModelPart assignedPathType) {
@@ -1070,12 +1071,15 @@ private void checkAssignment(Expression valueExpression, ModelPart assignedPathT
10701071
private void addAssignment(
10711072
List<Assignment> assignments,
10721073
AggregateColumnAssignmentHandler aggregateColumnAssignmentHandler,
1073-
ColumnReference columnReference,
1074+
Assignable assignable,
1075+
List<ColumnReference> targetColumnReferences,
10741076
Expression valueExpression) {
10751077
if ( aggregateColumnAssignmentHandler != null ) {
1076-
aggregateColumnAssignmentHandler.addAssignment( assignments.size(), columnReference );
1078+
for ( ColumnReference targetColumnReference : targetColumnReferences ) {
1079+
aggregateColumnAssignmentHandler.addAssignment( assignments.size(), targetColumnReference );
1080+
}
10771081
}
1078-
assignments.add( new Assignment( columnReference, valueExpression ) );
1082+
assignments.add( new Assignment( assignable, valueExpression ) );
10791083
}
10801084

10811085
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

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)