functions/Test-DbaDbQueryStore.ps1
function Test-DbaDbQueryStore { <# .SYNOPSIS Compares Query Store settings against best practices. .DESCRIPTION Evaluates Query Store against a set of rules to match best practices. The rules are: * ActualState = ReadWrite (This means Query Store is enabled and collecting data.) * DataFlushIntervalInSeconds = 900 (Recommended to leave this at the default of 900 seconds (15 mins).) * MaxPlansPerQuery = 200 (Number of distinct plans per query. 200 is a good starting point for most environments.) * MaxStorageSizeInMB = 2048 (How much disk space Query Store will use. 2GB is a good starting point.) * QueryCaptureMode = Auto (With auto, queries that are insignificant from a resource utilization perspective, or executed infrequently, are not captured.) * SizeBasedCleanupMode = Auto (With auto, as Query Store gets close to out of space it will automatically purge older data.) * StaleQueryThresholdInDays = 30 (Determines how much historic data to keep. 30 days is a good value here.) * StatisticsCollectionIntervalInMinutes = 30 (Time window that runtime stats will be aggregated. Use 30 unless you have space concerns, then leave at the default (60).) * WaitStatsCaptureMode = ON (Adds valuable data when troubleshooting.) * Trace Flag 7745 enabled * Trace Flag 7752 enabled .PARAMETER SqlInstance The target SQL Server instance or instances. .PARAMETER SqlCredential Login to the target instance using alternative credentials. Accepts PowerShell credentials (Get-Credential). Windows Authentication, SQL Server Authentication, Active Directory - Password, and Active Directory - Integrated are all supported. For MFA support, please use Connect-DbaInstance. .PARAMETER Database The database(s) to process. This list is auto-populated from the server. If unspecified, all user databases will be processed. .PARAMETER ExcludeDatabase The database(s) to exclude. This list is auto-populated from the server. .PARAMETER InputObject Enables piped input from Get-DbaDatabase. .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: QueryStore Author: Jess Pomfret (@jpomfret), jesspomfret.com Website: https://dbatools.io Copyright: (c) 2018 by dbatools, licensed under MIT License: MIT https://opensource.org/licenses/MIT Based on Erin Stellato's (@erinstellato) Query Store Best Practices - https://www.sqlskills.com/blogs/erin/query-store-best-practices/ .LINK https://dbatools.io/Test-DbaDbQueryStore .EXAMPLE PS C:\> Test-DbaDbQueryStore -SqlInstance localhost Checks that Query Store is enabled and meets best practices for all user databases on the localhost machine. .EXAMPLE PS C:\> Test-DbaDbQueryStore -SqlInstance localhost -Database AdventureWorks2017 Checks that Query Store is enabled and meets best practices for the AdventureWorks2017 database on the localhost machine. .EXAMPLE PS C:\> Test-DbaDbQueryStore -SqlInstance localhost -ExcludeDatabase AdventureWorks2017 Checks that Query Store is enabled and meets best practices for all user databases except AdventureWorks2017 on the localhost machine. .EXAMPLE PS C:\> $databases = Get-DbaDatabase -SqlInstance localhost PS C:\> $databases | Test-DbaDbQueryStore Checks that Query Store is enabled and meets best practices for all databases that are piped on the localhost machine. #> [CmdletBinding()] param ( [DbaInstance[]]$SqlInstance, [PSCredential]$SqlCredential, [object[]]$Database, [object[]]$ExcludeDatabase, [parameter(ValueFromPipeline)] [object[]]$InputObject, [switch]$EnableException ) process { if (Test-FunctionInterrupt) { return } if (-not $InputObject -and -not $SqlInstance) { Stop-Function -Message "You must pipe in a database or a server, or specify a SqlInstance" return } if ($SqlInstance) { $InputObject = $SqlInstance } foreach ($input in $InputObject) { $inputType = $input.GetType().FullName switch ($inputType) { 'Sqlcollaborative.Dbatools.Parameter.DbaInstanceParameter' { Write-Message -Level Verbose -Message "Processing DbaInstanceParameter through InputObject" $dbDatabases = Get-DbaDatabase -SqlInstance $input -SqlCredential $SqlCredential -Database $Database -ExcludeDatabase $ExcludeDatabase -ExcludeSystem -OnlyAccessible } 'Microsoft.SqlServer.Management.Smo.Server' { Write-Message -Level Verbose -Message "Processing Server through InputObject" $dbDatabases = Get-DbaDatabase -SqlInstance $input -SqlCredential $SqlCredential -Database $Database -ExcludeDatabase $ExcludeDatabase -ExcludeSystem -OnlyAccessible } 'Microsoft.SqlServer.Management.Smo.Database' { Write-Message -Level Verbose -Message "Processing Database through InputObject" $dbDatabases = $input | Where-Object { -not $_.IsSystemObject } } default { Stop-Function -Message "InputObject is not a server or database." return } } try { $smo = Connect-SqlInstance -SqlInstance $dbDatabases[0].Parent -SqlCredential $SqlCredential -MinimumVersion 13 } catch { Stop-Function -Message "Error occurred while establishing connection to $instance" -Category ConnectionError -ErrorRecord $_ -Target $instance -Continue } if ($Database) { $dbDatabases = $dbDatabases | Where-Object { $Database -contains $_.Name } } if ($ExcludeDatabase) { $dbDatabases = $dbDatabases | Where-Object Name -NotIn $ExcludeDatabase } $desiredState = [PSCustomObject]@{ Property = 'ActualState' Value = 'ReadWrite' Justification = 'This means Query Store is enabled and collecting data.' }, [PSCustomObject]@{ Property = 'DataFlushIntervalInSeconds' Value = '900' Justification = 'Recommended to leave this at the default of 900 seconds (15 mins).' }, [PSCustomObject]@{ Property = 'MaxPlansPerQuery' Value = '200' Justification = 'Number of distinct plans per query. 200 is a good starting point for most environments.' }, [PSCustomObject]@{ Property = 'MaxStorageSizeInMB' Value = '2048' Justification = 'How much disk space Query Store will use. 2GB is a good starting point.' }, [PSCustomObject]@{ Property = 'QueryCaptureMode' Value = 'Auto' Justification = 'With auto, queries that are insignificant from a resource utilization perspective, or executed infrequently, are not captured.' }, [PSCustomObject]@{ Property = 'SizeBasedCleanupMode' Value = 'Auto' Justification = 'With auto, as Query Store gets close to out of space it will automatically purge older data.' }, [PSCustomObject]@{ Property = 'StaleQueryThresholdInDays' Value = '30' Justification = 'Determines how much historic data to keep. 30 days is a good value here.' }, [PSCustomObject]@{ Property = 'StatisticsCollectionIntervalInMinutes' Value = '30' Justification = 'Time window that runtime stats will be aggregated. Use 30 unless you have space concerns, then leave at the default (60).' }, [PSCustomObject]@{ Property = 'WaitStatsCaptureMode' Value = 'ON' Justification = 'Adds valuable data when troubleshooting.' } try { Write-Message -Level Verbose -Message "Evaluating Query Store options" $currentOptions = Get-DbaDbQueryStoreOption -SqlInstance $smo -Database $dbDatabases.name foreach ($db in $currentOptions) { $props = $db.GetPropertySet() | Where-Object Name -NotIn ('CurrentStorageSizeInMB', 'ReadOnlyReason', 'DesiredState') foreach ($property in $props) { [PSCustomObject]@{ ComputerName = $db.ComputerName InstanceName = $db.InstanceName SqlInstance = $db.SqlInstance Database = $db.Database Name = $property.Name Value = $property.Value RecommendedValue = ($desiredState | Where-Object Property -EQ $property.Name).Value IsBestPractice = ($property.Value -eq ($desiredState | Where-Object Property -EQ $property.Name).Value) Justification = ($desiredState | Where-Object Property -EQ $property.Name).Justification } } } } catch { Stop-Function -Message "Unable to get Query Store data $smo" -Target $smo -ErrorRecord $_ } # Trace flags $queryStoreTF = [PSCustomObject]@{ TraceFlag = '7745' Justification = 'SQL Server will not wait to write Query Store data to disk on shutdown\failover (can cause lose of Query Store data).' }, [PSCustomObject]@{ TraceFlag = '7752' Justification = 'Load Query Store data asynchronously on SQL Server startup.' } try { foreach ($tf in $queryStoreTF) { $tfEnabled = Get-DbaTraceFlag -SqlInstance $smo -TraceFlag $tf.TraceFlag [PSCustomObject]@{ ComputerName = $smo.ComputerName InstanceName = $smo.DbaInstanceName SqlInstance = $smo.Name Name = ('Trace Flag {0} Enabled' -f $tf.TraceFlag) Value = if ($tfEnabled) { 'Enabled' } else { 'Disabled' } RecommendedValue = $tf.TraceFlag IsBestPractice = ($tfEnabled.TraceFlag -eq $tf.TraceFlag) Justification = $tf.Justification } $tfEnabled = $null } } catch { Stop-Function -Message "Unable to get Trace Flag data $smo" -Target $smo -ErrorRecord $_ } } } } # SIG # Begin signature block # MIIZewYJKoZIhvcNAQcCoIIZbDCCGWgCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB # gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR # AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUUMAKrOZSwvl9Gpj4Oox4F5TF # WK+gghSJMIIE/jCCA+agAwIBAgIQDUJK4L46iP9gQCHOFADw3TANBgkqhkiG9w0B # AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz # c3VyZWQgSUQgVGltZXN0YW1waW5nIENBMB4XDTIxMDEwMTAwMDAwMFoXDTMxMDEw # NjAwMDAwMFowSDELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkRpZ2lDZXJ0LCBJbmMu # MSAwHgYDVQQDExdEaWdpQ2VydCBUaW1lc3RhbXAgMjAyMTCCASIwDQYJKoZIhvcN # AQEBBQADggEPADCCAQoCggEBAMLmYYRnxYr1DQikRcpja1HXOhFCvQp1dU2UtAxQ # tSYQ/h3Ib5FrDJbnGlxI70Tlv5thzRWRYlq4/2cLnGP9NmqB+in43Stwhd4CGPN4 # bbx9+cdtCT2+anaH6Yq9+IRdHnbJ5MZ2djpT0dHTWjaPxqPhLxs6t2HWc+xObTOK # fF1FLUuxUOZBOjdWhtyTI433UCXoZObd048vV7WHIOsOjizVI9r0TXhG4wODMSlK # XAwxikqMiMX3MFr5FK8VX2xDSQn9JiNT9o1j6BqrW7EdMMKbaYK02/xWVLwfoYer # vnpbCiAvSwnJlaeNsvrWY4tOpXIc7p96AXP4Gdb+DUmEvQECAwEAAaOCAbgwggG0 # MA4GA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMBYGA1UdJQEB/wQMMAoGCCsG # AQUFBwMIMEEGA1UdIAQ6MDgwNgYJYIZIAYb9bAcBMCkwJwYIKwYBBQUHAgEWG2h0 # dHA6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzAfBgNVHSMEGDAWgBT0tuEgHf4prtLk # YaWyoiWyyBc1bjAdBgNVHQ4EFgQUNkSGjqS6sGa+vCgtHUQ23eNqerwwcQYDVR0f # BGowaDAyoDCgLoYsaHR0cDovL2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJl # ZC10cy5jcmwwMqAwoC6GLGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFz # c3VyZWQtdHMuY3JsMIGFBggrBgEFBQcBAQR5MHcwJAYIKwYBBQUHMAGGGGh0dHA6 # Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBPBggrBgEFBQcwAoZDaHR0cDovL2NhY2VydHMu # ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3VyZWRJRFRpbWVzdGFtcGluZ0NB # LmNydDANBgkqhkiG9w0BAQsFAAOCAQEASBzctemaI7znGucgDo5nRv1CclF0CiNH # o6uS0iXEcFm+FKDlJ4GlTRQVGQd58NEEw4bZO73+RAJmTe1ppA/2uHDPYuj1UUp4 # eTZ6J7fz51Kfk6ftQ55757TdQSKJ+4eiRgNO/PT+t2R3Y18jUmmDgvoaU+2QzI2h # F3MN9PNlOXBL85zWenvaDLw9MtAby/Vh/HUIAHa8gQ74wOFcz8QRcucbZEnYIpp1 # FUL1LTI4gdr0YKK6tFL7XOBhJCVPst/JKahzQ1HavWPWH1ub9y4bTxMd90oNcX6X # t/Q/hOvB46NJofrOp79Wz7pZdmGJX36ntI5nePk2mOHLKNpbh6aKLzCCBRowggQC # oAMCAQICEAMFu4YhsKFjX7/erhIE520wDQYJKoZIhvcNAQELBQAwcjELMAkGA1UE # BhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3LmRpZ2lj # ZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElEIENvZGUg # U2lnbmluZyBDQTAeFw0yMDA1MTIwMDAwMDBaFw0yMzA2MDgxMjAwMDBaMFcxCzAJ # BgNVBAYTAlVTMREwDwYDVQQIEwhWaXJnaW5pYTEPMA0GA1UEBxMGVmllbm5hMREw # DwYDVQQKEwhkYmF0b29sczERMA8GA1UEAxMIZGJhdG9vbHMwggEiMA0GCSqGSIb3 # DQEBAQUAA4IBDwAwggEKAoIBAQC8v2N7q+O/vggBtpjmteofFo140k73JXQ5sOD6 # QLzjgija+scoYPxTmFSImnqtjfZFWmucAWsDiMVVro/6yGjsXmJJUA7oD5BlMdAK # fuiq4558YBOjjc0Bp3NbY5ZGujdCmsw9lqHRAVil6P1ZpAv3D/TyVVq6AjDsJY+x # rRL9iMc8YpD5tiAj+SsRSuT5qwPuW83ByRHqkaJ5YDJ/R82ZKh69AFNXoJ3xCJR+ # P7+pa8tbdSgRf25w4ZfYPy9InEvsnIRVZMeDjjuGvqr0/Mar73UI79z0NYW80yN/ # 7VzlrvV8RnniHWY2ib9ehZligp5aEqdV2/XFVPV4SKaJs8R9AgMBAAGjggHFMIIB # wTAfBgNVHSMEGDAWgBRaxLl7KgqjpepxA8Bg+S32ZXUOWDAdBgNVHQ4EFgQU8MCg # +7YDgENO+wnX3d96scvjniIwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsG # AQUFBwMDMHcGA1UdHwRwMG4wNaAzoDGGL2h0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNv # bS9zaGEyLWFzc3VyZWQtY3MtZzEuY3JsMDWgM6Axhi9odHRwOi8vY3JsNC5kaWdp # Y2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcxLmNybDBMBgNVHSAERTBDMDcGCWCG # SAGG/WwDATAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20v # Q1BTMAgGBmeBDAEEATCBhAYIKwYBBQUHAQEEeDB2MCQGCCsGAQUFBzABhhhodHRw # Oi8vb2NzcC5kaWdpY2VydC5jb20wTgYIKwYBBQUHMAKGQmh0dHA6Ly9jYWNlcnRz # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1cmVkSURDb2RlU2lnbmluZ0NB # LmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQCPzflwlQwf1jak # EqymPOc0nBxiY7F4FwcmL7IrTLhub6Pjg4ZYfiC79Akz5aNlqO+TJ0kqglkfnOsc # jfKQzzDwcZthLVZl83igzCLnWMo8Zk/D2d4ZLY9esFwqPNvuuVDrHvgh7H6DJ/zP # Vm5EOK0sljT0UQ6HQEwtouH5S8nrqCGZ8jKM/+DeJlm+rCAGGf7TV85uqsAn5JqD # En/bXE1AlyG1Q5YiXFGS5Sf0qS4Nisw7vRrZ6Qc4NwBty4cAYjzDPDixorWI8+FV # OUWKMdL7tV8i393/XykwsccCstBCp7VnSZN+4vgzjEJQql5uQfysjcW9rrb/qixp # csPTKYRHMIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1U0O1b5VQCDANBgkqhkiG9w0B # AQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD # VQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVk # IElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcNMjgxMDIyMTIwMDAwWjByMQsw # CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu # ZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQg # Q29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA # +NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid2zLXcep2nQUut4/6kkPApfmJ # 1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH03sjlOSRI5aQd4L5oYQjZhJUM1B0 # sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxKhwjfDPXiTWAYvqrEsq5wMWYzcT6s # cKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzLfnQ5Ng2Q7+S1TqSp6moKq4Tz # rGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR93O8vYWxYoNzQYIH5DiLanMg # 0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckwEgYDVR0TAQH/BAgwBgEB/wIB # ADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYIKwYBBQUHAwMweQYIKwYBBQUH # AQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wQwYI # KwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFz # c3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgwOqA4oDaGNGh0dHA6Ly9jcmw0 # LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwOqA4oDaG # NGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RD # QS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIEMCowKAYIKwYBBQUHAgEWHGh0 # dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYIYIZIAYb9bAMwHQYDVR0OBBYE # FFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6en # IZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1aJLPzItEVyCx8JSl2qB1dHC06 # GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbRknUPUbRupY5a4l4kgU4QpO4/cY5j # DhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7uq+1UcKNJK4kxscnKqEpKBo6cSgC # PC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7qPjFEmifz0DLQESlE/DmZAwlCEIy # sjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPas7CM1ekN3fYBIM6ZMWM9CBoYs4Gb # T8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhsRDKyZqHnGKSaZFHvMIIFMTCC # BBmgAwIBAgIQCqEl1tYyG35B5AXaNpfCFTANBgkqhkiG9w0BAQsFADBlMQswCQYD # VQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGln # aWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew # HhcNMTYwMTA3MTIwMDAwWhcNMzEwMTA3MTIwMDAwWjByMQswCQYDVQQGEwJVUzEV # MBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29t # MTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQgSUQgVGltZXN0YW1waW5n # IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvdAy7kvNj3/dqbqC # mcU5VChXtiNKxA4HRTNREH3Q+X1NaH7ntqD0jbOI5Je/YyGQmL8TvFfTw+F+CNZq # FAA49y4eO+7MpvYyWf5fZT/gm+vjRkcGGlV+Cyd+wKL1oODeIj8O/36V+/OjuiI+ # GKwR5PCZA207hXwJ0+5dyJoLVOOoCXFr4M8iEA91z3FyTgqt30A6XLdR4aF5FMZN # JCMwXbzsPGBqrC8HzP3w6kfZiFBe/WZuVmEnKYmEUeaC50ZQ/ZQqLKfkdT66mA+E # f58xFNat1fJky3seBdCEGXIX8RcG7z3N1k3vBkL9olMqT4UdxB08r8/arBD13ays # 6Vb/kwIDAQABo4IBzjCCAcowHQYDVR0OBBYEFPS24SAd/imu0uRhpbKiJbLIFzVu # MB8GA1UdIwQYMBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMBIGA1UdEwEB/wQIMAYB # Af8CAQAwDgYDVR0PAQH/BAQDAgGGMBMGA1UdJQQMMAoGCCsGAQUFBwMIMHkGCCsG # AQUFBwEBBG0wazAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29t # MEMGCCsGAQUFBzAChjdodHRwOi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNl # cnRBc3N1cmVkSURSb290Q0EuY3J0MIGBBgNVHR8EejB4MDqgOKA2hjRodHRwOi8v # Y3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMDqg # OKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURS # b290Q0EuY3JsMFAGA1UdIARJMEcwOAYKYIZIAYb9bAACBDAqMCgGCCsGAQUFBwIB # FhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BTMAsGCWCGSAGG/WwHATANBgkq # hkiG9w0BAQsFAAOCAQEAcZUS6VGHVmnN793afKpjerN4zwY3QITvS4S/ys8DAv3F # p8MOIEIsr3fzKx8MIVoqtwU0HWqumfgnoma/Capg33akOpMP+LLR2HwZYuhegiUe # xLoceywh4tZbLBQ1QwRostt1AuByx5jWPGTlH0gQGF+JOGFNYkYkh2OMkVIsrymJ # 5Xgf1gsUpYDXEkdws3XVk4WTfraSZ/tTYYmo9WuWwPRYaQ18yAGxuSh1t5ljhSKM # Ycp5lH5Z/IwP42+1ASa2bKXuh1Eh5Fhgm7oMLSttosR+u8QlK0cCCHxJrhO24XxC # QijGGFbPQTS2Zl22dHv1VjMiLyI2skuiSpXY9aaOUjGCBFwwggRYAgEBMIGGMHIx # CzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3 # dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNIQTIgQXNzdXJlZCBJ # RCBDb2RlIFNpZ25pbmcgQ0ECEAMFu4YhsKFjX7/erhIE520wCQYFKw4DAhoFAKB4 # MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcNAQkDMQwGCisGAQQB # gjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwIwYJKoZIhvcNAQkE # MRYEFLpiJ6RhFSrQ8YtBWzCrMqm397a9MA0GCSqGSIb3DQEBAQUABIIBADScl4Q4 # T5eZryjEqWtEegHYxFRwr9VUi0ZW1P13q8ZT8GKADrvDEXvZFc3kUZUSAX9bVuFf # 3WDg4LoD1f1GXHoHsqsztmFQydLmnHGHP1xLqfVOQ5do1H8AKElblLWtNI8Bc2kT # QfHD7MPfxppynLW8oisVJ5+a2CZKvpWKtDIf1Mo6nPHxrRrIyb93tVn7xvR15hLC # FWgE04wE8IgWHeWvnF5PinMU8wZU8Fu3/GwJ1KJMTLF6ZDy0zFBWZe9FJ/cAq7Mt # vc4Qj1O+1PXuXFZdfiXtcEEbA1jw4+IvqS1B5B8xnLksEVSgVlabb5DM8A6vCPPG # m7lLnZS1RcfQsPShggIwMIICLAYJKoZIhvcNAQkGMYICHTCCAhkCAQEwgYYwcjEL # MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3 # LmRpZ2ljZXJ0LmNvbTExMC8GA1UEAxMoRGlnaUNlcnQgU0hBMiBBc3N1cmVkIElE # IFRpbWVzdGFtcGluZyBDQQIQDUJK4L46iP9gQCHOFADw3TANBglghkgBZQMEAgEF # AKBpMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTIx # MDczMDA4MDAxNFowLwYJKoZIhvcNAQkEMSIEIJh2+mL1PnvT/8Nv3tf41CKYnW64 # 4YeQOpQtb+AJEkN0MA0GCSqGSIb3DQEBAQUABIIBAD7CPsJDloS9T+tPJqoWRldy # SzrtZxAsS1TW0DiVDnzemISBVIF2PlDYVskjJZufTL6hfyFZw11CihNsKWrYbS7Q # 2bOuJ8oIskvt7agvrSlx4zO1vXABMetFd5E+P/nNnxfUbOXiBefa9T50te3Aw4Wz # TYb/xOxIBO0rGaI7xqUdlYZu49DvtNK6JB1Z7Sr7tZz1K6OlGhp9LKY+Bxuh4+GX # 7xyyqzIXQQ4/kS+cuGNlRe2R3Tgtp5+orbqCujd3A90uaGllaqADEsF69wJyad0t # BlARiJQxCjyAEubO8Yk/1N1oK4SBMxbThcHUlO9Gxf1xxmx8uxLTJ7nfcDTu9r0= # SIG # End signature block |