internal/functions/generation/Resolve-SldgForeignKeyFallback.ps1
|
function Resolve-SldgForeignKeyFallback { <# .SYNOPSIS Batch-loads missing FK parent values from the database. .DESCRIPTION For each FK column in a table plan where parent values are not yet in $FkValues, queries the database for distinct parent PK values. Groups queries by parent table to minimize round-trips. #> [CmdletBinding()] param ( [Parameter(Mandatory)] [SqlLabDataGenerator.TablePlan]$TablePlan, [Parameter(Mandatory)] [hashtable]$FkValues, [Parameter(Mandatory)] [SqlLabDataGenerator.Connection]$ConnectionInfo, [System.Data.Common.DbTransaction]$Transaction, [int]$FkQueryLimit = 1000, [int]$CommandTimeout = 30 ) if (-not $TablePlan.ForeignKeys -or $TablePlan.ForeignKeys.Count -eq 0) { return } $fallbackStats = [System.Collections.Generic.List[object]]::new() # Group FK columns by parent table to minimize database round-trips $fkByParent = @{} foreach ($fk in $TablePlan.ForeignKeys) { $refKey = "$($fk.ReferencedSchema).$($fk.ReferencedTable).$($fk.ReferencedColumn)" if (-not $FkValues.ContainsKey($refKey) -or $FkValues[$refKey].Count -eq 0) { $parentKey = "$($fk.ReferencedSchema).$($fk.ReferencedTable)" if (-not $fkByParent.ContainsKey($parentKey)) { $fkByParent[$parentKey] = @() } $fkByParent[$parentKey] += $fk } } foreach ($parentKey in $fkByParent.Keys) { $parentFks = $fkByParent[$parentKey] $firstFk = $parentFks[0] $dialect = $ConnectionInfo.GetDialect() $safeRef = $dialect.QualifiedName($firstFk.ReferencedSchema, $firstFk.ReferencedTable) try { $safeCols = @($parentFks | ForEach-Object { $dialect.QuoteIdentifier($_.ReferencedColumn) } | Select-Object -Unique) $cmd = $ConnectionInfo.DbConnection.CreateCommand() if ($Transaction) { $cmd.Transaction = $Transaction } $cmd.CommandText = $dialect.SelectLimited(($safeCols -join ', '), $safeRef, $FkQueryLimit, $true, ($safeCols -join ', ')) $cmd.CommandTimeout = $CommandTimeout $reader = $cmd.ExecuteReader() $colLists = @{} foreach ($fk in $parentFks) { $colLists[$fk.ReferencedColumn] = [System.Collections.Generic.List[object]]::new() } while ($reader.Read()) { foreach ($fk in $parentFks) { $ordinal = $reader.GetOrdinal($fk.ReferencedColumn) if (-not $reader.IsDBNull($ordinal)) { $colLists[$fk.ReferencedColumn].Add($reader.GetValue($ordinal)) } } } $reader.Close() $reader.Dispose() $cmd.Dispose() foreach ($fk in $parentFks) { $refKey = "$($fk.ReferencedSchema).$($fk.ReferencedTable).$($fk.ReferencedColumn)" if ($colLists[$fk.ReferencedColumn].Count -gt 0) { $FkValues[$refKey] = $colLists[$fk.ReferencedColumn].ToArray() $fallbackStats.Add([SqlLabDataGenerator.ForeignKeyFallback]@{ ReferenceKey = $refKey ValueCount = $colLists[$fk.ReferencedColumn].Count TableName = $TablePlan.FullName }) Write-PSFMessage -Level Verbose -Message ($script:strings.'Generation.FKFallbackLoaded' -f $refKey, $colLists[$fk.ReferencedColumn].Count) } } } catch { foreach ($fk in $parentFks) { $refKey = "$($fk.ReferencedSchema).$($fk.ReferencedTable).$($fk.ReferencedColumn)" Write-PSFMessage -Level Warning -Message ($script:strings.'Generation.FKFallbackFailed' -f $refKey, $_) } } } $fallbackStats.ToArray() } |