functions/Export-DbaDiagnosticQuery.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
function Export-DbaDiagnosticQuery {
    <#
        .SYNOPSIS
            Export-DbaDiagnosticQuery can convert ouput generated by Invoke-DbaDiagnosticQuery to CSV or Excel
 
        .DESCRIPTION
            The default output format of Invoke-DbaDiagnosticQuery is a custom object. It can also output to CSV and Excel.
            However, CSV output can generate a lot of files and Excel output depends on the ImportExcel module by Doug Fike (https://github.com/dfinke/ImportExcel)
            Export-DbaDiagnosticQuery can be used to convert from the default export type to the other available export types.
 
        .PARAMETER InputObject
            Specifies the objects to convert
 
        .PARAMETER ConvertTo
            Specifies the output type. Valid choices are Excel and CSV. CSV is the default.
 
        .PARAMETER Path
            Specifies the path to the output files.
 
        .PARAMETER Suffix
            Suffix for the filename. It's datetime by default.
 
        .PARAMETER NoPlanExport
            Use this switch to suppress exporting of .sqlplan files
 
        .PARAMETER NoQueryExport
            Use this switch to suppress exporting of .sql files
 
        .PARAMETER EnableException
            By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.
            This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting.
            Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch.
 
        .NOTES
            Tags: Query
            Author: Andre Kamman (@AndreKamman), http://clouddba.io
 
            Website: https://dbatools.io
            Copyright: (C) Chrissy LeMaire, clemaire@gmail.com
            License: MIT https://opensource.org/licenses/MIT
 
        .LINK
            https://dbatools.io/Export-DbaDiagnosticQuery
 
        .EXAMPLE
            Invoke-DbaDiagnosticQuery -SqlInstance sql2016 | Export-DbaDiagnosticQuery -Path c:\temp
 
            Converts output from Invoke-DbaDiagnosticQuery to multiple CSV files
 
        .EXAMPLE
            $output = Invoke-DbaDiagnosticQuery -SqlInstance sql2016
            Export-DbaDiagnosticQuery -InputObject $output -ConvertTo Excel
 
            Converts output from Invoke-DbaDiagnosticQuery to Excel worksheet(s) in the Documents folder
    #>

    [CmdletBinding()]
    param (
        [parameter(Mandatory = $true, ValueFromPipeline = $true)]
        [object[]]$InputObject,
        [ValidateSet("Excel", "Csv")]
        [string]$ConvertTo = "Csv",
        [System.IO.FileInfo]$Path = [Environment]::GetFolderPath("mydocuments"),
        [string]$Suffix = "$(Get-Date -format 'yyyyMMddHHmmssms')",
        [switch]$NoPlanExport,
        [switch]$NoQueryExport,
        [Alias('Silent')]
        [switch]$EnableException
    )

    begin {
        if ($ConvertTo -eq "Excel") {
            try {
                Import-Module ImportExcel -ErrorAction Stop
            }
            catch {
                $message = "Failed to load module, exporting to Excel feature is not available
                            Install the module from: https://github.com/dfinke/ImportExcel
                            Valid alternative conversion format is csv"

                Stop-Function -Message $message
                return
            }
        }

        if (!$(Test-Path $Path)) {
            try {
                New-Item $Path -ItemType Directory -ErrorAction Stop | Out-Null
                Write-Message -Level Output -Message "Created directory $Path"
            }
            catch {
                Stop-Function -Message "Failed to create directory $Path" -Continue
            }
        }

        Function Remove-InvalidFileNameChars {
            [CmdletBinding()]
            param (
                [Parameter(Mandatory = $true,
                    Position = 0,
                    ValueFromPipeline = $true,
                    ValueFromPipelineByPropertyName = $true)]
                [String]$Name
            )
            $Name = $Name.Replace(" ", "-")
            $invalidChars = [IO.Path]::GetInvalidFileNameChars() -join ''
            $re = "[{0}]" -f [RegEx]::Escape($invalidChars)
            return ($Name -replace $re)
        }
    }

    process {
        if (Test-FunctionInterrupt) { return }

        foreach ($row in $InputObject) {
            $result = $row.Result
            $name = $row.Name
            $SqlInstance = $row.SqlInstance.Replace("\", "$")
            $dbname = $row.Database
            $number = $row.Number
            $note = $row.Note

            if ($null -eq $result) {
                Stop-Function -Message "Result was empty for $name" -Target $result -Continue
            }

            $queryname = Remove-InvalidFileNameChars -Name $Name
            $excelfilename = "$Path\$SqlInstance-DQ-$Suffix.xlsx"
            $exceldbfilename = "$Path\$SqlInstance-DQ-$dbname-$Suffix.xlsx"
            $csvdbfilename = "$Path\$SqlInstance-$dbname-DQ-$number-$queryname-$Suffix.csv"
            $csvfilename = "$Path\$SqlInstance-DQ-$number-$queryname-$Suffix.csv"

            $columnnameoptions = "Query Plan", "QueryPlan", "Query_Plan", "query_plan_xml"
            if (($result | Get-Member | Where-Object Name -in $columnnameoptions).Count -gt 0) {
                $plannr = 0
                $columnname = ($result | Get-Member | Where-Object Name -In $columnnameoptions).Name
                foreach ($plan in $result."$columnname") {
                    $plannr += 1
                    if ($row.DatabaseSpecific) {
                        $planfilename = "$Path\$SqlInstance-$dbname-DQ-$number-$queryname-$plannr-$Suffix.sqlplan"
                    }
                    else {
                        $planfilename = "$Path\$SqlInstance-DQ-$number-$queryname-$plannr-$Suffix.sqlplan"
                    }

                    if (!$NoPlanExport) {
                        Write-Message -Level Output -Message "Exporting $planfilename"
                        if ($plan) {$plan | Out-File -FilePath $planfilename}
                    }
                }

                $result = $result | Select-Object * -ExcludeProperty "$columnname"
            }

            $columnnameoptions = "Complete Query Text", "QueryText", "Query Text", "Query_Text", "query_sql_text"
            if (($result | Get-Member | Where-Object Name -In $columnnameoptions ).Count -gt 0) {
                $sqlnr = 0
                $columnname = ($result | Get-Member | Where-Object Name -In $columnnameoptions).Name
                foreach ($sql in $result."$columnname") {
                    $sqlnr += 1
                    if ($row.DatabaseSpecific) {
                        $sqlfilename = "$Path\$SqlInstance-$dbname-DQ-$number-$queryname-$sqlnr-$Suffix.sql"
                    }
                    else {
                        $sqlfilename = "$Path\$SqlInstance-DQ-$number-$queryname-$sqlnr-$Suffix.sql"
                    }

                    if (!$NoQueryExport) {
                        Write-Message -Level Output -Message "Exporting $sqlfilename"
                        if ($sql) {$sql | Out-File -FilePath $sqlfilename}
                    }
                }

                $result = $result | Select-Object * -ExcludeProperty "$columnname"
            }

            switch ($ConvertTo) {
                "Excel" {
                    if ($row.DatabaseSpecific) {
                        Write-Message -Level Output -Message "Exporting $exceldbfilename"
                        $result | Export-Excel -Path $exceldbfilename -WorkSheetname $Name -AutoSize -AutoFilter -BoldTopRow -FreezeTopRow
                    }
                    else {
                        Write-Message -Level Output -Message "Exporting $excelfilename"
                        $result | Export-Excel -Path $excelfilename -WorkSheetname $Name -AutoSize -AutoFilter -BoldTopRow -FreezeTopRow
                    }
                }
                "csv" {
                    if ($row.DatabaseSpecific) {
                        Write-Message -Level Output -Message "Exporting $csvdbfilename"
                        $result | Export-Csv -Path $csvdbfilename -NoTypeInformation -Append
                    }
                    else {
                        Write-Message -Level Output -Message "Exporting $csvfilename"
                        $result | Export-Csv -Path $csvfilename -NoTypeInformation -Append
                    }
                }
            }
        }
    }
}