internal/functions/generation/Group-SldgTablesByLevel.ps1
|
function Group-SldgTablesByLevel { <# .SYNOPSIS Groups topologically-ordered tables into dependency levels for parallel processing. .DESCRIPTION Assigns each table a dependency level: level 0 has no FK dependencies, level 1 depends only on level 0 tables, etc. Tables at the same level are independent and can be generated in parallel. #> [CmdletBinding()] param ( [Parameter(Mandatory)] [object[]]$Tables ) $levelMap = @{} foreach ($table in $Tables) { $levelMap[$table.FullName] = 0 } # Iteratively compute levels based on FK dependencies # Safety limit prevents infinite loop with circular FK dependencies (A→B→A) $maxIterations = $Tables.Count $iteration = 0 $changed = $true $lastLevelSum = -1 while ($changed) { if ($iteration++ -ge $maxIterations) { Write-PSFMessage -Level Warning -Message ($script:strings.'Generation.LevelComputationStopped' -f $maxIterations) break } $changed = $false foreach ($table in $Tables) { if (-not $table.ForeignKeys) { continue } $deps = $table.ForeignKeys | Where-Object { "$($_.ReferencedSchema).$($_.ReferencedTable)" -ne $table.FullName } | ForEach-Object { "$($_.ReferencedSchema).$($_.ReferencedTable)" } | Select-Object -Unique foreach ($dep in $deps) { if ($levelMap.ContainsKey($dep)) { $requiredLevel = $levelMap[$dep] + 1 if ($requiredLevel -gt $levelMap[$table.FullName]) { $levelMap[$table.FullName] = $requiredLevel $changed = $true } } } } # Convergence early exit: if level sums haven't changed, no further progress is possible $currentLevelSum = 0 foreach ($v in $levelMap.Values) { $currentLevelSum += $v } if ($currentLevelSum -eq $lastLevelSum) { break } $lastLevelSum = $currentLevelSum } # Group by level, preserving original order within each level $maxLevel = 0 foreach ($v in $levelMap.Values) { if ($v -gt $maxLevel) { $maxLevel = $v } } $groups = [System.Collections.Generic.List[object]]::new() for ($level = 0; $level -le $maxLevel; $level++) { $levelTables = @($Tables | Where-Object { $levelMap[$_.FullName] -eq $level }) if ($levelTables.Count -gt 0) { $groups.Add([PSCustomObject]@{ Level = $level Tables = $levelTables }) } } $firstGroupCount = if ($groups.Count -gt 0) { $groups[0].Tables.Count } else { 0 } Write-PSFMessage -Level Verbose -Message ($script:strings.'Generation.DependencyLevels' -f $groups.Count, $firstGroupCount) $groups.ToArray() } |