39 lines
2.4 KiB
Diff
39 lines
2.4 KiB
Diff
# UNDF: UNDF-2026-000000464
|
|
--- a/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java
|
|
+++ b/hibernate-core/src/main/java/org/hibernate/boot/internal/InFlightMetadataCollectorImpl.java
|
|
@@ -1803,7 +1803,8 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
|
|
// using the isADependencyOf map we order the FkSecondPass recursively instances into the right order for processing
|
|
final LinkedHashSet<FkSecondPass> orderedFkSecondPassesSet = new LinkedHashSet<>();
|
|
for ( String tableName : isADependencyOf.keySet() ) {
|
|
- buildRecursiveOrderedFkSecondPasses( orderedFkSecondPassesSet, isADependencyOf, tableName, tableName );
|
|
+ buildRecursiveOrderedFkSecondPasses( orderedFkSecondPassesSet, isADependencyOf, tableName, tableName,
|
|
+ new HashSet<>() );
|
|
}
|
|
// Reconstruct ordered list from set (order maintained by LinkedHashSet insertion sequence)
|
|
final List<FkSecondPass> orderedFkSecondPasses = new ArrayList<>( orderedFkSecondPassesSet );
|
|
@@ -1835,9 +1836,16 @@ public class InFlightMetadataCollectorImpl implements InFlightMetadataCollector
|
|
private void buildRecursiveOrderedFkSecondPasses(
|
|
LinkedHashSet<FkSecondPass> orderedFkSecondPasses,
|
|
Map<String, Set<FkSecondPass>> isADependencyOf,
|
|
String startTable,
|
|
- String currentTable) {
|
|
+ String currentTable,
|
|
+ Set<String> visitedTables) {
|
|
+ // hibernate-0007 fix: guard against diamond-graph exponential re-visitation.
|
|
+ // The original startTable identity check only prevented direct self-cycles;
|
|
+ // it did not prevent intermediate diamond nodes from being visited O(2^D) times.
|
|
+ // Adding visitedTables reduces the recursion from O(2^D) to O(T+E).
|
|
+ if ( !visitedTables.add( currentTable ) ) {
|
|
+ return;
|
|
+ }
|
|
final Set<FkSecondPass> dependencies = isADependencyOf.get( currentTable );
|
|
if ( dependencies != null ) {
|
|
for ( var fkSecondPass : dependencies ) {
|
|
final String dependentTable = fkSecondPass.getValue().getTable().getQualifiedTableName().render();
|
|
if ( dependentTable.compareTo( startTable ) != 0 ) {
|
|
- buildRecursiveOrderedFkSecondPasses( orderedFkSecondPasses, isADependencyOf, startTable, dependentTable );
|
|
+ buildRecursiveOrderedFkSecondPasses( orderedFkSecondPasses, isADependencyOf, startTable,
|
|
+ dependentTable, visitedTables );
|
|
}
|
|
// O(1) with LinkedHashSet; was O(N) ArrayList.contains() + O(N) add(0,...)
|
|
orderedFkSecondPasses.add( fkSecondPass );
|