functions/Compare-SqlQuery.ps1
function Compare-SqlQuery { [CmdletBinding()] param( [String]$SqlInstance, [String]$Database, [String]$Path, [String[]]$File, [String[]]$Accept, [String[]]$Investigate, [Switch]$StopOnFirst, [String]$IdColumn = $null, [PSCustomObject]$Parameters = @{} ) process { $template = $null; $templateFile = ""; $currentFile = ""; $executionStats = @{}; if (@($File).Length -eq 1) { $File = @("$File.previous", $File) } @($File).foreach{ $issuesFound = 0; $filePath = (Join-Path -Path $Path -ChildPath $psitem) $currentFile = $psitem Write-PSFMessage -Function "Compare-DbpQuery" -Level Verbose "Executing $filePath" $ts = Get-Date $current = Invoke-DbaQuery -SqlInstance $SqlInstance -Database $Database -File $filePath -SqlParameters $Parameters -EnableException $executionStats.Add($psitem, @{ Query = $psitem; ExecutionTime = ((Get-Date)-$ts);}) if ($null -eq $current) { Write-PSFMessage -Function "Compare-DbpQuery" -Level Critical "there is no data to look at" return } if ($null -eq $template){ Write-PSFMessage -Function "Compare-DbpQuery" -Level Verbose "Assinging $psitem as the template" $template = $current $templateFile = $psitem $templateColumns = ($template[0] | Get-Member -MemberType Property) } else { Write-PSFMessage -Function "Compare-DbpQuery" -Level Output "Comparing results from $currentFile against $templateFile" #check the number of rows if ($template.Length -ne $current.Length) { ++$issuesFound; Write-PSFMessage -Function "Compare-DbpQuery" -Level Output " PROBLEM: Expected $($template.Length) rows but found $($current.Length)" return } else { Write-PSFMessage -Function "Compare-DbpQuery" -Level Verbose " Row numbers match ($($template.Length))" } #check column numbers $currentColumns = ($current[0] | Get-Member -MemberType Property) if ($templateColumns.Length -ne $currentColumns.Length) { ++$issuesFound; Write-PSFMessage -Function "Compare-DbpQuery" -Level Output "PROBLEM: Expected $($templateColumns.Length) columns but found $($currentColumns.Length)" return } else { Write-PSFMessage -Function "Compare-DbpQuery" -Level Verbose " Column numbers match ($($templateColumns.Length))" } Write-PSFMessage -Function "Compare-DbpQuery" -Level Output "Checking $($templateColumns.Length) columns and $($template.Length) rows" #Check column names and types for($i = 0; $i -lt $templateColumns.Length; ++$i){ if ($templateColumns[$i].Name -ne $currentColumns[$i].Name) { ++$issuesFound; Write-PSFMessage -Function "Compare-DbpQuery" -Level Output " PROBLEM: Exepcted column $($templateColumns[$i].Name) at index $i but $($currentColumns[$i].Name) was found." if ($StopOnFirst -eq $true) { return } } } #test data column after column for($i = 0; $i -lt $templateColumns.Length; ++$i){ $rowsAffected = 0 $firstAffectedRow = 0; $expectedValue = $null; $actualValue = $null if (![String]::IsNullOrEmpty($templateColumns[$i].Name) -and $templateColumns[$i].Name -in @($Investigate)){ Write-PSFMessage -Function "Compare-DbpQuery" -Level Output " Investigating column $($templateColumns[$i].Name)" } for($j = 0; $j -lt $template.Length; ++$j) { if ($template[$j][$templateColumns[$i].Name] -cne $current[$j][$currentColumns[$i].Name]) { if ($rowsAffected++ -eq 0) { $firstAffectedRow = $j+1 $expectedValue = $template[$j][$templateColumns[$i].Name] $actualValue = $current[$j][$currentColumns[$i].Name] } if ($templateColumns[$i].Name -in @($Investigate)){ if ($null -ne $IdColumn) { $IdString = " (ID=$($template[$j][$IdColumn]))" } Write-PSFMessage -Function "Compare-DbpQuery" -Level Output " Row $($j+1)$($IdString): Expected $($template[$j][$templateColumns[$i].Name]) but found $($current[$j][$currentColumns[$i].Name])" } } } if ($templateColumns[$i].Name -in @($Accept)){ Write-PSFMessage -Function "Compare-DbpQuery" -Level Output " ACCEPTED: $rowsAffected differences in column $($templateColumns[$i].Name) have been accepted." } else { if ($rowsAffected -gt 0) { ++$issuesFound; Write-PSFMessage -Function "Compare-DbpQuery" -Level Output " PROBLEM: Value of $($templateColumns[$i].Name) in row $($firstAffectedRow) should be $($expectedValue) but was $($actualValue). ($rowsAffected rows affected)." if ($StopOnFirst -eq $true) { return } } else { Write-PSFMessage -Function "Compare-DbpQuery" -Level Verbose " Data in column $($templateColumns[$i].Name) matches exactly" } } } if ($issuesFound -eq 0){ Write-PSFMessage -Function "Compare-DbpQuery" -Level Output "No issues found in $psitem" } } } $executionStats.Values | Select Query, ExecutionTime } } |