From 52e4c13f536c14b6ef207795eb732fc87cd56f36 Mon Sep 17 00:00:00 2001 From: Chrissy LeMaire Date: Fri, 12 Apr 2024 17:47:26 +0200 Subject: [PATCH 1/8] Address CVE in RestSharp Dangler --- .github/workflows/gallery.yml | 2 +- .github/workflows/integration-tests-repl.yml | 6 +++--- .github/workflows/integration-tests.yml | 4 ++-- .github/workflows/xplat-import.yml | 2 +- dbatools.psd1 | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/.github/workflows/gallery.yml b/.github/workflows/gallery.yml index 512404e88e..0ce64ca72a 100644 --- a/.github/workflows/gallery.yml +++ b/.github/workflows/gallery.yml @@ -24,7 +24,7 @@ jobs: - name: Install and cache PowerShell modules uses: potatoqualitee/psmodulecache@v5.2 with: - modules-to-cache: dbatools.library:2024.3.9 + modules-to-cache: dbatools.library:2024.4.12 - name: Download dbatools from Gallery run: | diff --git a/.github/workflows/integration-tests-repl.yml b/.github/workflows/integration-tests-repl.yml index 58b5ad66ef..c9b7b49f17 100644 --- a/.github/workflows/integration-tests-repl.yml +++ b/.github/workflows/integration-tests-repl.yml @@ -15,7 +15,7 @@ jobs: - name: Install and cache PowerShell modules uses: potatoqualitee/psmodulecache@v5.2 with: - modules-to-cache: dbatools.library:2024.3.9 + modules-to-cache: dbatools.library:2024.4.12 - name: Set encryption values run: | @@ -64,7 +64,7 @@ jobs: - name: Install and cache PowerShell modules uses: potatoqualitee/psmodulecache@v5.2 with: - modules-to-cache: dbatools.library:2024.3.9 + modules-to-cache: dbatools.library:2024.4.12 - name: Set encryption values run: | @@ -114,7 +114,7 @@ jobs: - name: Install and cache PowerShell modules uses: potatoqualitee/psmodulecache@v5.2 with: - modules-to-cache: dbatools.library:2024.3.9 + modules-to-cache: dbatools.library:2024.4.12 - name: Set encryption values run: | diff --git a/.github/workflows/integration-tests.yml b/.github/workflows/integration-tests.yml index 33c3029795..0e228153a4 100644 --- a/.github/workflows/integration-tests.yml +++ b/.github/workflows/integration-tests.yml @@ -21,7 +21,7 @@ jobs: - name: Install and cache PowerShell modules uses: potatoqualitee/psmodulecache@v5.2 with: - modules-to-cache: dbatools.library:2024.3.9 + modules-to-cache: dbatools.library:2024.4.12 - name: Set encryption values run: | @@ -71,7 +71,7 @@ jobs: uses: potatoqualitee/psmodulecache@v5.2 with: shell: powershell, pwsh - modules-to-cache: dbatools.library:2024.3.9 + modules-to-cache: dbatools.library:2024.4.12 - name: Install SQL Server localdb uses: potatoqualitee/mssqlsuite@v1.3 diff --git a/.github/workflows/xplat-import.yml b/.github/workflows/xplat-import.yml index bdb509fd4b..ac61736498 100644 --- a/.github/workflows/xplat-import.yml +++ b/.github/workflows/xplat-import.yml @@ -18,7 +18,7 @@ jobs: - name: Install and cache PowerShell modules uses: potatoqualitee/psmodulecache@v5.2 with: - modules-to-cache: dbatools.library:2024.3.9 + modules-to-cache: dbatools.library:2024.4.12 - name: Perform the import shell: pwsh diff --git a/dbatools.psd1 b/dbatools.psd1 index ac4e172077..26d6a45018 100644 --- a/dbatools.psd1 +++ b/dbatools.psd1 @@ -11,7 +11,7 @@ RootModule = 'dbatools.psm1' # Version number of this module. - ModuleVersion = '2.1.13' + ModuleVersion = '2.1.14' # ID used to uniquely identify this module GUID = '9d139310-ce45-41ce-8e8b-d76335aa1789' @@ -29,7 +29,7 @@ Description = "The community module that enables SQL Server Pros to automate database development and server administration" # Modules that must be imported into the global environment prior to importing this module - RequiredModules = @{ ModuleName = 'dbatools.library'; ModuleVersion = '2024.3.9' } + RequiredModules = @{ ModuleName = 'dbatools.library'; ModuleVersion = '2024.4.12' } # Assemblies that must be loaded prior to importing this module RequiredAssemblies = @() From 866a66fcaf6b94fcd4d1888e2adf5af43d5086e5 Mon Sep 17 00:00:00 2001 From: mwilsonin <99306324+mwilsonin@users.noreply.github.com> Date: Fri, 10 May 2024 06:55:13 -0400 Subject: [PATCH 2/8] Update Set-DbaNetworkCertificate to work with PowerShell Core when using RSA certificates (#9342) --- public/Set-DbaNetworkCertificate.ps1 | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/public/Set-DbaNetworkCertificate.ps1 b/public/Set-DbaNetworkCertificate.ps1 index 3b56babf62..faea32361e 100644 --- a/public/Set-DbaNetworkCertificate.ps1 +++ b/public/Set-DbaNetworkCertificate.ps1 @@ -168,7 +168,11 @@ function Set-DbaNetworkCertificate { if ($null -ne $cert.PrivateKey) { $keyPath = $env:ProgramData + "\Microsoft\Crypto\RSA\MachineKeys\" - $keyName = $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName + $keyName = switch ($PSEdition) { + Core { $cert.PrivateKey.Key.UniqueName } + Desktop { $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName } + default { $cert.PrivateKey.CspKeyContainerInfo.UniqueKeyContainerName } # for PowerShell v3 and earlier which does not return $PSEdition + } $keyFullPath = $keyPath + $keyName } else { $keyPath = $env:ProgramData + '\Microsoft\Crypto\Keys\' From b51ae6ddf54516ac4d43d23d9a2358b174391257 Mon Sep 17 00:00:00 2001 From: Courtney Woolum <117998701+serenefiresiren@users.noreply.github.com> Date: Thu, 16 May 2024 09:53:37 -0400 Subject: [PATCH 3/8] New Support for Contained Availability Groups (#9345) Co-authored-by: Courtney Woolum Co-authored-by: Dor Breger --- public/New-DbaAvailabilityGroup.ps1 | 34 ++++++++++++++++++++++-- tests/New-DbaAvailabilityGroup.Tests.ps1 | 4 +-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/public/New-DbaAvailabilityGroup.ps1 b/public/New-DbaAvailabilityGroup.ps1 index 5e82eb0271..0b4e4321f5 100644 --- a/public/New-DbaAvailabilityGroup.ps1 +++ b/public/New-DbaAvailabilityGroup.ps1 @@ -1,4 +1,4 @@ -function New-DbaAvailabilityGroup { +function New-DbaAvailabilityGroup { <# .SYNOPSIS Automates the creation of availability groups. @@ -56,6 +56,14 @@ function New-DbaAvailabilityGroup { .PARAMETER Name The name of the Availability Group. + .PARAMETER IsContained + Builds the Availability Group as contained. Only supported in SQL Server 2022 or higher. + + https://learn.microsoft.com/en-us/sql/database-engine/availability-groups/windows/contained-availability-groups-overview + + .PARAMETER ReuseSystemDatabases + Used when rebuilding an availability group with the same name, where system databases already exist for the contained availability group. + .PARAMETER DtcSupport Indicates whether the DtcSupport is enabled @@ -219,6 +227,11 @@ function New-DbaAvailabilityGroup { Creates a basic availability group named BAG1 on sql2016std and does not confirm when setting up + .EXAMPLE + PS C:\> New-DbaAvailabilityGroup -Primary sql2022n01 -Secondary sql2022n02 -Name AgContained -IsContained + + Creates a contained availability group named AgContained on nodes sql2022n01 and sql2022n02 + .EXAMPLE PS C:\> New-DbaAvailabilityGroup -Primary sql2016b -Name AG1 -Dhcp -Database db1 -UseLastBackup @@ -268,6 +281,8 @@ function New-DbaAvailabilityGroup { [parameter(Mandatory)] [string]$Name, + [switch]$IsContained, + [switch]$ReuseSystemDatabases, [switch]$DtcSupport, [ValidateSet('Wsfc', 'External', 'None')] [string]$ClusterType = (Get-DbatoolsConfigValue -FullName 'AvailabilityGroups.Default.ClusterType' -Fallback 'Wsfc'), @@ -366,6 +381,16 @@ function New-DbaAvailabilityGroup { return } + if ($IsContained -and $server.VersionMajor -lt 16) { + Stop-Function -Level Warning -Message "Contained availability groups are only supported in SQL Server 2022 and above" + return + } + + if ($ReuseSystemDatabases -and $IsContained -eq $false) { + Stop-Function -Level Warning -Message "Reuse system databases is only applicable in contained availability groups" + return + } + Write-ProgressHelper -StepNumber ($stepCounter++) -Message "Checking requirements" $requirementsFailed = $false @@ -499,6 +524,11 @@ function New-DbaAvailabilityGroup { $ag.ClusterType = $ClusterType } + if ($server.VersionMajor -ge 16) { + $ag.IsContained = $IsContained + $ag.ReuseSystemDatabases = $ReuseSystemDatabases + } + if ($PassThru) { $defaults = 'LocalReplicaRole', 'Name as AvailabilityGroup', 'PrimaryReplicaServerName as PrimaryReplica', 'AutomatedBackupPreference', 'AvailabilityReplicas', 'AvailabilityDatabases', 'AvailabilityGroupListeners' return (Select-DefaultView -InputObject $ag -Property $defaults) @@ -668,4 +698,4 @@ function New-DbaAvailabilityGroup { # Get results Get-DbaAvailabilityGroup -SqlInstance $Primary -SqlCredential $PrimarySqlCredential -AvailabilityGroup $Name } -} \ No newline at end of file +} diff --git a/tests/New-DbaAvailabilityGroup.Tests.ps1 b/tests/New-DbaAvailabilityGroup.Tests.ps1 index 691713ef8d..b3d3bc615f 100644 --- a/tests/New-DbaAvailabilityGroup.Tests.ps1 +++ b/tests/New-DbaAvailabilityGroup.Tests.ps1 @@ -5,7 +5,7 @@ Write-Host -Object "Running $PSCommandpath" -ForegroundColor Cyan Describe "$commandname Unit Tests" -Tag 'UnitTests' { Context "Validate parameters" { [object[]]$params = (Get-Command $CommandName).Parameters.Keys | Where-Object { $_ -notin ('whatif', 'confirm') } - [object[]]$knownParameters = 'Primary', 'PrimarySqlCredential', 'Secondary', 'SecondarySqlCredential', 'Name', 'DtcSupport', 'ClusterType', 'AutomatedBackupPreference', 'FailureConditionLevel', 'HealthCheckTimeout', 'Basic', 'DatabaseHealthTrigger', 'Passthru', 'Database', 'SharedPath', 'UseLastBackup', 'Force', 'AvailabilityMode', 'FailoverMode', 'BackupPriority', 'ConnectionModeInPrimaryRole', 'ConnectionModeInSecondaryRole', 'SeedingMode', 'Endpoint', 'EndpointUrl', 'Certificate', 'ConfigureXESession', 'IPAddress', 'SubnetMask', 'Port', 'Dhcp', 'EnableException' + [object[]]$knownParameters = 'Primary', 'PrimarySqlCredential', 'Secondary', 'SecondarySqlCredential', 'Name', 'ReuseSystemDatabases', 'IsContained', 'DtcSupport', 'ClusterType', 'AutomatedBackupPreference', 'FailureConditionLevel', 'HealthCheckTimeout', 'Basic', 'DatabaseHealthTrigger', 'Passthru', 'Database', 'SharedPath', 'UseLastBackup', 'Force', 'AvailabilityMode', 'FailoverMode', 'BackupPriority', 'ConnectionModeInPrimaryRole', 'ConnectionModeInSecondaryRole', 'SeedingMode', 'Endpoint', 'EndpointUrl', 'Certificate', 'ConfigureXESession', 'IPAddress', 'SubnetMask', 'Port', 'Dhcp', 'EnableException' $knownParameters += [System.Management.Automation.PSCmdlet]::CommonParameters It "Should only contain our specific parameters" { (@(Compare-Object -ReferenceObject ($knownParameters | Where-Object { $_ }) -DifferenceObject $params).Count ) | Should Be 0 @@ -45,4 +45,4 @@ Describe "$commandname Integration Tests" -Tag "IntegrationTests" { $results.AvailabilityDatabases.Count | Should -Be 0 -Because "No database was named" } } -} #$script:instance2 for appveyor \ No newline at end of file +} #$script:instance2 for appveyor From 0fd8aa0ab1deda76fb859c265e7e71605eb4b59a Mon Sep 17 00:00:00 2001 From: Romain Ferraton <16419423+rferraton@users.noreply.github.com> Date: Thu, 16 May 2024 16:16:58 +0200 Subject: [PATCH 4/8] Backup-DbaDatabase : add a new switch parameter "NoAppendDbNameInPath" to prevent dbname systematically appended at the end of backup path (#9348) --- public/Backup-DbaDatabase.ps1 | 10 +++++++++- tests/Backup-DbaDatabase.Tests.ps1 | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/public/Backup-DbaDatabase.ps1 b/public/Backup-DbaDatabase.ps1 index f7038b29a2..bf8a2d5d2f 100644 --- a/public/Backup-DbaDatabase.ps1 +++ b/public/Backup-DbaDatabase.ps1 @@ -54,6 +54,9 @@ function Backup-DbaDatabase { timestamp - will be replaced with the timestamp (either the default, or the format provided) backuptype - will be replaced with Full, Log or Differential as appropriate + .PARAMETER NoAppendDbNameInPath + A switch that will prevent to systematically appended dbname to the path when creating the backup file path + .PARAMETER CopyOnly If this switch is enabled, CopyOnly backups will be taken. By default function performs a normal backup, these backups interfere with the restore chain of the database. CopyOnly backups will not interfere with the restore chain of the database. @@ -217,6 +220,7 @@ function Backup-DbaDatabase { [string]$FilePath, [switch]$IncrementPrefix, [switch]$ReplaceInName, + [switch]$NoAppendDbNameInPath, [switch]$CopyOnly, [ValidateSet('Full', 'Log', 'Differential', 'Diff', 'Database')] [string]$Type = 'Database', @@ -661,7 +665,11 @@ function Backup-DbaDatabase { for ($i = 0; $i -lt $FinalBackupPath.Count; $i++) { $parent = [IO.Path]::GetDirectoryName($FinalBackupPath[$i]) $leaf = [IO.Path]::GetFileName($FinalBackupPath[$i]) - $FinalBackupPath[$i] = [IO.Path]::Combine($parent, $dbName, $leaf) + if ($NoAppendDbNameInPath) { + $FinalBackupPath[$i] = [IO.Path]::Combine($parent, $leaf) + } else { + $FinalBackupPath[$i] = [IO.Path]::Combine($parent, $dbName, $leaf) + } } } diff --git a/tests/Backup-DbaDatabase.Tests.ps1 b/tests/Backup-DbaDatabase.Tests.ps1 index e4b736b283..26889a9db6 100644 --- a/tests/Backup-DbaDatabase.Tests.ps1 +++ b/tests/Backup-DbaDatabase.Tests.ps1 @@ -5,7 +5,7 @@ Write-Host -Object "Running $PSCommandPath" -ForegroundColor Cyan Describe "$CommandName Unit Tests" -Tag 'UnitTests' { Context "Validate parameters" { [object[]]$params = (Get-Command $CommandName).Parameters.Keys | Where-Object { $_ -notin ('whatif', 'confirm') } - [object[]]$knownParameters = 'SqlInstance', 'SqlCredential', 'Database', 'ExcludeDatabase', 'Path', 'FilePath', 'ReplaceInName', 'CopyOnly', 'Type', 'InputObject', 'CreateFolder', 'FileCount', 'CompressBackup', 'Checksum', 'Verify', 'MaxTransferSize', 'BlockSize', 'BufferCount', 'AzureBaseUrl', 'AzureCredential', 'NoRecovery', 'BuildPath', 'WithFormat', 'Initialize', 'SkipTapeHeader', 'TimeStampFormat', 'IgnoreFileChecks', 'OutputScriptOnly', 'EnableException', 'EncryptionAlgorithm', 'EncryptionCertificate', 'IncrementPrefix', 'Description' + [object[]]$knownParameters = 'SqlInstance', 'SqlCredential', 'Database', 'ExcludeDatabase', 'Path', 'FilePath', 'ReplaceInName', 'NoAppendDbNameInPath', 'CopyOnly', 'Type', 'InputObject', 'CreateFolder', 'FileCount', 'CompressBackup', 'Checksum', 'Verify', 'MaxTransferSize', 'BlockSize', 'BufferCount', 'AzureBaseUrl', 'AzureCredential', 'NoRecovery', 'BuildPath', 'WithFormat', 'Initialize', 'SkipTapeHeader', 'TimeStampFormat', 'IgnoreFileChecks', 'OutputScriptOnly', 'EnableException', 'EncryptionAlgorithm', 'EncryptionCertificate', 'IncrementPrefix', 'Description' $knownParameters += [System.Management.Automation.PSCmdlet]::CommonParameters It "Should only contain our specific parameters" { (@(Compare-Object -ReferenceObject ($knownParameters | Where-Object { $_ }) -DifferenceObject $params).Count ) | Should Be 0 From d4858838be1957d33f538c8b2022476691c41f82 Mon Sep 17 00:00:00 2001 From: DorBreger <75537576+DorBreger@users.noreply.github.com> Date: Thu, 16 May 2024 17:37:16 +0300 Subject: [PATCH 5/8] New-DbaAvailabilityGroup: Add support for contained availability groups (#9352) Co-authored-by: Courtney Woolum Co-authored-by: Courtney Woolum <117998701+serenefiresiren@users.noreply.github.com> Co-authored-by: Chrissy LeMaire Co-authored-by: Chrissy LeMaire --- public/New-DbaAvailabilityGroup.ps1 | 12 ++++++------ tests/New-DbaAvailabilityGroup.Tests.ps1 | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/public/New-DbaAvailabilityGroup.ps1 b/public/New-DbaAvailabilityGroup.ps1 index 0b4e4321f5..f4f6621130 100644 --- a/public/New-DbaAvailabilityGroup.ps1 +++ b/public/New-DbaAvailabilityGroup.ps1 @@ -1,4 +1,4 @@ -function New-DbaAvailabilityGroup { +function New-DbaAvailabilityGroup { <# .SYNOPSIS Automates the creation of availability groups. @@ -382,13 +382,13 @@ } if ($IsContained -and $server.VersionMajor -lt 16) { - Stop-Function -Level Warning -Message "Contained availability groups are only supported in SQL Server 2022 and above" - return + Stop-Function -Message "Contained availability groups are only supported in SQL Server 2022 and above" -Target $Primary + return } if ($ReuseSystemDatabases -and $IsContained -eq $false) { - Stop-Function -Level Warning -Message "Reuse system databases is only applicable in contained availability groups" - return + Stop-Function -Message "Reuse system databases is only applicable in contained availability groups" -Target $Primary + return } Write-ProgressHelper -StepNumber ($stepCounter++) -Message "Checking requirements" @@ -698,4 +698,4 @@ # Get results Get-DbaAvailabilityGroup -SqlInstance $Primary -SqlCredential $PrimarySqlCredential -AvailabilityGroup $Name } -} +} \ No newline at end of file diff --git a/tests/New-DbaAvailabilityGroup.Tests.ps1 b/tests/New-DbaAvailabilityGroup.Tests.ps1 index b3d3bc615f..7f218a624c 100644 --- a/tests/New-DbaAvailabilityGroup.Tests.ps1 +++ b/tests/New-DbaAvailabilityGroup.Tests.ps1 @@ -45,4 +45,4 @@ Describe "$commandname Integration Tests" -Tag "IntegrationTests" { $results.AvailabilityDatabases.Count | Should -Be 0 -Because "No database was named" } } -} #$script:instance2 for appveyor +} #$script:instance2 for appveyor \ No newline at end of file From 836023340f51326759e02eda63d49c6d88a56d5c Mon Sep 17 00:00:00 2001 From: Chrissy LeMaire Date: Fri, 17 May 2024 14:23:12 +0200 Subject: [PATCH 6/8] ConvertTo-DbaDataTable - Fix DbaDateTime issue (#9353) --- public/ConvertTo-DbaDataTable.ps1 | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/public/ConvertTo-DbaDataTable.ps1 b/public/ConvertTo-DbaDataTable.ps1 index bf2adf3ff5..c0bbecd772 100644 --- a/public/ConvertTo-DbaDataTable.ps1 +++ b/public/ConvertTo-DbaDataTable.ps1 @@ -166,6 +166,11 @@ function ConvertTo-DbaDataTable { } } $specialType = 'Size' + } elseif ($type -eq 'Dataplat.Dbatools.Utility.DbaDateTime') { + $special = $true + $value = [System.DateTime]$value.DateTime + $type = 'System.DateTime' + $specialType = 'DateTime' } elseif (-not ($type -in $types)) { # All types which are not found in the array will be converted into strings. # In this way we don't ignore it completely and it will be clear in the end why it looks as it does. @@ -217,6 +222,9 @@ function ConvertTo-DbaDataTable { $Value.$TimeSpanType } } + 'DateTime' { + return [System.DateTime]$Value.DateTime + } } } From 974deef7414d6b3ccc9e78cbc20a733facfd68d1 Mon Sep 17 00:00:00 2001 From: Mikey Bronowski Date: Fri, 17 May 2024 13:23:38 +0100 Subject: [PATCH 7/8] Update dbatools-buildref-index.json SQL 2022 CU13 (#9354) --- bin/dbatools-buildref-index.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/bin/dbatools-buildref-index.json b/bin/dbatools-buildref-index.json index d7b2b96a5d..8d68193030 100644 --- a/bin/dbatools-buildref-index.json +++ b/bin/dbatools-buildref-index.json @@ -1,5 +1,5 @@ { - "LastUpdated": "2024-04-11T00:00:00", + "LastUpdated": "2024-05-16T00:00:00", "Data": [ { "Version": "8.0.47", @@ -4683,6 +4683,11 @@ { "Version": "16.0.4120", "KBList": "5036343" + }, + { + "CU": "CU13", + "Version": "16.0.4125", + "KBList": "5036432" } ] } From 22c7bc9f6c4188a7bfc1bef6866db5ffeff1ef2d Mon Sep 17 00:00:00 2001 From: Chrissy LeMaire Date: Sat, 18 May 2024 07:53:39 +0200 Subject: [PATCH 8/8] v2.1.15 --- bin/dbatools-index.json | Bin 8882510 -> 8886016 bytes .../SQLServerDiagnosticQueries_2012.sql | 6 ++++-- .../SQLServerDiagnosticQueries_2014.sql | 9 +++++---- .../SQLServerDiagnosticQueries_2016.sql | 9 +++++---- .../SQLServerDiagnosticQueries_2016SP2.sql | 9 +++++---- .../SQLServerDiagnosticQueries_2017.sql | 9 +++++---- .../SQLServerDiagnosticQueries_2019.sql | 9 +++++---- .../SQLServerDiagnosticQueries_2022.sql | 9 +++++---- dbatools.psd1 | 2 +- 9 files changed, 35 insertions(+), 27 deletions(-) diff --git a/bin/dbatools-index.json b/bin/dbatools-index.json index ac19f7f5aad124e4f859cd9cd772130706650b0b..fa075fd97b6ab3346dfb0b80c98aa32c6bc02d7e 100644 GIT binary patch delta 1604 zcmb8uTTC2P7zgk(%&;uOf(tAxP{83LH%r-Ku@|rxDCO2&mO?4&mP_SUOJNs!u|Vmz zrQ!oIz!v{nBSLIVO&Wwm9iwT2grFu3!NiBgho(uReX$L+QJbb3|5VeO7>#D~dpIZO zyUdwy7DmPt?WN5DnrW*CjY<*j5H-YnFn! zO394&oQ+{9O(_ox?hu;j636I}XhOr?Tr1w6-)RnPWO(~ZI3|Ac3&%|GF$Ie~vH`Zx znq=Jmw%dfM&{ZZ(o)0qW8E|>`#VDlX5Nzf z|4;rFIlv`4g-f(!;vM-oZ1d?xthpqcp`Dha^q~v#6~F(Q5A3%R?hks3_1hO^^S@>W zGvC9~Ua1)4({i!T`=*9PSj>3+LRi>9@1#r$`ICVH$Vh>tQV^Lam_q0YGE*q6#D|lG zA}Erq6h+Y#L#rs3;wYY;B#ja%k&-Bxo}v^=r8G*X40@VYQzosUEV9vB%BE*%9p%uo zw4OH5M%qNVlt<6eX4*nqX&dEJ0d1#3+CfEBOeIuGWwcZ8owO$x1!RkC4vh_2>yuaE z+Ol1Z`*Vl;n#g=K^%{q+MHJxVRAP8|rYPZz7jP2WIcp7KKPSNceR&eR&gu}~oGS$j z*IG>ek0TORPHNP_pQ(wlEB}c{w6Tbd*a9X#tBZiQL{c8LG+m{>2j{YVmwx^y`$Y*$ z%W>5!YbWaGBm?5p%T&ZK*)6{DNJWpiXYZGAy(RVGky3s0eS3@_#`{cvtig4S?)=qW z%FVtD1R;UF1h%Et6Ua5P4SLoLXwZpnjoWQ&FeuX#3L;cJ@#Q8(*M7@4h2 z3F_jlc8DXqhE8~@HYH%|yK34epPFVRU;PaQLsyMP{H&+Cuyoa;Le1Ty;sR-v6|E1GRY;LZu-)-fe9fvEi>^QwmbQX0XjT3OEEKmH zq1~)ge4Tx1aCjS{9@o_~tPZ6+;&0!SSsUSrYm2~qlPww7$2}H3f7sC|L;Ipoh5PeD zrW|#|;>uY^KI(6EshB$Ji1pQe$Y_t*n2yjMX0KhC?zkeZxG^z?3uE|l;ljB1+&qWh%rj4IWX>V`+c z>6$JbUY9P_sZO&KbC^29y*=RgMhCnhmEqs!UCWrjFDl<-5udx2E!?a>*o* zlucQ`TZW#jy)J`4X~f>Ta<1Q2ZNC%RRYFbNp}3m3gQC3)6gYWN75FE_5Hr)>^q+lU zzg+ChP@WjQ<4ot-LuDxOc$x|&dSB%`dwW$-li?kjPr{FsuQSqRO3%$SLqZQyQ|0yY zK!$_|)Pl=h{R%opz=Z@PVkDA~j8Pbk6pVp^u}H-@q#+#{7>^0aL>4Au5+-8`rozND zOvemlV#@P<>i56$O8A>!cRIfN?`vW&4c3bLn}4N5YpV_C;}8EWO?nzC{uE0e zsCGVDt>B{sXs zC9zPve%Zcfp#qhtLI4}F37Zkb7Hq{fRAW18umd6NgpFO;jXkJE9qQ45z1WBSXhahZ u;2@e2Mhgz%Fpl6Tj^Q{?;3Qgc3a4=fXK@Y@oW})RL>n$S_PzF=&%Xeb4Zs}$ diff --git a/bin/diagnosticquery/SQLServerDiagnosticQueries_2012.sql b/bin/diagnosticquery/SQLServerDiagnosticQueries_2012.sql index eb0a45199c..8e87e2c58b 100644 --- a/bin/diagnosticquery/SQLServerDiagnosticQueries_2012.sql +++ b/bin/diagnosticquery/SQLServerDiagnosticQueries_2012.sql @@ -1,7 +1,7 @@ -- SQL Server 2012 Diagnostic Information Queries -- Glenn Berry --- Last Modified: April 1, 2024 +-- Last Modified: May 2, 2024 -- https://glennsqlperformance.com/ -- https://sqlserverperformance.wordpress.com/ -- YouTube: https://bit.ly/2PkoAM1 @@ -1380,6 +1380,7 @@ ON vfs.[file_id]= df.[file_id] OPTION (RECOMPILE); -- Get most frequently executed queries for this database (Query 52) (Query Execution Counts) SELECT TOP(50) LEFT(t.[text], 50) AS [Short Query Text], qs.execution_count AS [Execution Count], +ISNULL(qs.execution_count/DATEDIFF(Minute, qs.creation_time, GETDATE()), 0) AS [Calls/Minute], qs.total_logical_reads AS [Total Logical Reads], qs.total_logical_reads/qs.execution_count AS [Avg Logical Reads], qs.total_worker_time AS [Total Worker Time], @@ -1387,12 +1388,13 @@ qs.total_worker_time/qs.execution_count AS [Avg Worker Time], qs.total_elapsed_time AS [Total Elapsed Time], qs.total_elapsed_time/qs.execution_count AS [Avg Elapsed Time], CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], -qs.creation_time AS [Creation Time] +qs.last_execution_time AS [Last Execution Time], qs.creation_time AS [Creation Time] --,t.[text] AS [Complete Query Text], qp.query_plan AS [Query Plan] -- uncomment out these columns if not copying results to Excel FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK) CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS t CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qp WHERE t.dbid = DB_ID() +AND DATEDIFF(Minute, qs.creation_time, GETDATE()) > 0 ORDER BY qs.execution_count DESC OPTION (RECOMPILE); ------ diff --git a/bin/diagnosticquery/SQLServerDiagnosticQueries_2014.sql b/bin/diagnosticquery/SQLServerDiagnosticQueries_2014.sql index 9181d2b006..36f5960379 100644 --- a/bin/diagnosticquery/SQLServerDiagnosticQueries_2014.sql +++ b/bin/diagnosticquery/SQLServerDiagnosticQueries_2014.sql @@ -1,7 +1,7 @@ -- SQL Server 2014 Diagnostic Information Queries -- Glenn Berry --- Last Modified: April 1, 2024 +-- Last Modified: May 2, 2024 -- https://glennsqlperformance.com/ -- https://sqlserverperformance.wordpress.com/ -- YouTube: https://bit.ly/2PkoAM1 @@ -1406,20 +1406,21 @@ ON vfs.[file_id]= df.[file_id] OPTION (RECOMPILE); -- Get most frequently executed queries for this database (Query 53) (Query Execution Counts) SELECT TOP(50) LEFT(t.[text], 50) AS [Short Query Text], qs.execution_count AS [Execution Count], +ISNULL(qs.execution_count/DATEDIFF(Minute, qs.creation_time, GETDATE()), 0) AS [Calls/Minute], qs.total_logical_reads AS [Total Logical Reads], qs.total_logical_reads/qs.execution_count AS [Avg Logical Reads], qs.total_worker_time AS [Total Worker Time], qs.total_worker_time/qs.execution_count AS [Avg Worker Time], qs.total_elapsed_time AS [Total Elapsed Time], qs.total_elapsed_time/qs.execution_count AS [Avg Elapsed Time], -CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], -CONVERT(nvarchar(25), qs.last_execution_time, 20) AS [Last Execution Time], -CONVERT(nvarchar(25), qs.creation_time, 20) AS [Plan Cached Time] +CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], +qs.last_execution_time AS [Last Execution Time], qs.creation_time AS [Creation Time] --,t.[text] AS [Complete Query Text], qp.query_plan AS [Query Plan] -- uncomment out these columns if not copying results to Excel FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK) CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS t CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qp WHERE t.dbid = DB_ID() +AND DATEDIFF(Minute, qs.creation_time, GETDATE()) > 0 ORDER BY qs.execution_count DESC OPTION (RECOMPILE); ------ diff --git a/bin/diagnosticquery/SQLServerDiagnosticQueries_2016.sql b/bin/diagnosticquery/SQLServerDiagnosticQueries_2016.sql index 6fa6ef6500..445be6a9ac 100644 --- a/bin/diagnosticquery/SQLServerDiagnosticQueries_2016.sql +++ b/bin/diagnosticquery/SQLServerDiagnosticQueries_2016.sql @@ -1,7 +1,7 @@ -- SQL Server 2016 Diagnostic Information Queries -- Glenn Berry --- Last Modified: April 1, 2024 +-- Last Modified: May 2, 2024 -- https://glennsqlperformance.com/ -- https://sqlserverperformance.wordpress.com/ -- YouTube: https://bit.ly/2PkoAM1 @@ -1470,20 +1470,21 @@ ON vfs.[file_id]= df.[file_id] OPTION (RECOMPILE); -- Get most frequently executed queries for this database (Query 54) (Query Execution Counts) SELECT TOP(50) LEFT(t.[text], 50) AS [Short Query Text], qs.execution_count AS [Execution Count], +ISNULL(qs.execution_count/DATEDIFF(Minute, qs.creation_time, GETDATE()), 0) AS [Calls/Minute], qs.total_logical_reads AS [Total Logical Reads], qs.total_logical_reads/qs.execution_count AS [Avg Logical Reads], qs.total_worker_time AS [Total Worker Time], qs.total_worker_time/qs.execution_count AS [Avg Worker Time], qs.total_elapsed_time AS [Total Elapsed Time], qs.total_elapsed_time/qs.execution_count AS [Avg Elapsed Time], -CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], -FORMAT(qs.last_execution_time, 'yyyy-MM-dd HH:mm:ss', 'en-US') AS [Last Execution Time], -FORMAT(qs.creation_time, 'yyyy-MM-dd HH:mm:ss', 'en-US') AS [Plan Cached Time] +CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], +qs.last_execution_time AS [Last Execution Time], qs.creation_time AS [Creation Time] --,t.[text] AS [Complete Query Text], qp.query_plan AS [Query Plan] -- uncomment out these columns if not copying results to Excel FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK) CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS t CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qp WHERE t.dbid = DB_ID() +AND DATEDIFF(Minute, qs.creation_time, GETDATE()) > 0 ORDER BY qs.execution_count DESC OPTION (RECOMPILE); ------ diff --git a/bin/diagnosticquery/SQLServerDiagnosticQueries_2016SP2.sql b/bin/diagnosticquery/SQLServerDiagnosticQueries_2016SP2.sql index db89811e4d..639d7ad2d8 100644 --- a/bin/diagnosticquery/SQLServerDiagnosticQueries_2016SP2.sql +++ b/bin/diagnosticquery/SQLServerDiagnosticQueries_2016SP2.sql @@ -1,7 +1,7 @@ -- SQL Server 2016 SP2 Diagnostic Information Queries -- Glenn Berry --- Last Modified: April 1, 2024 +-- Last Modified: May 2, 2024 -- https://glennsqlperformance.com/ -- https://sqlserverperformance.wordpress.com/ -- YouTube: https://bit.ly/2PkoAM1 @@ -1485,20 +1485,21 @@ ON vfs.[file_id]= df.[file_id] OPTION (RECOMPILE); -- Get most frequently executed queries for this database (Query 57) (Query Execution Counts) SELECT TOP(50) LEFT(t.[text], 50) AS [Short Query Text], qs.execution_count AS [Execution Count], +ISNULL(qs.execution_count/DATEDIFF(Minute, qs.creation_time, GETDATE()), 0) AS [Calls/Minute], qs.total_logical_reads AS [Total Logical Reads], qs.total_logical_reads/qs.execution_count AS [Avg Logical Reads], qs.total_worker_time AS [Total Worker Time], qs.total_worker_time/qs.execution_count AS [Avg Worker Time], qs.total_elapsed_time AS [Total Elapsed Time], qs.total_elapsed_time/qs.execution_count AS [Avg Elapsed Time], -CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], -CONVERT(nvarchar(25), qs.last_execution_time, 20) AS [Last Execution Time], -CONVERT(nvarchar(25), qs.creation_time, 20) AS [Plan Cached Time] +CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], +qs.last_execution_time AS [Last Execution Time], qs.creation_time AS [Creation Time] --,t.[text] AS [Complete Query Text], qp.query_plan AS [Query Plan] -- uncomment out these columns if not copying results to Excel FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK) CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS t CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qp WHERE t.dbid = DB_ID() +AND DATEDIFF(Minute, qs.creation_time, GETDATE()) > 0 ORDER BY qs.execution_count DESC OPTION (RECOMPILE); ------ diff --git a/bin/diagnosticquery/SQLServerDiagnosticQueries_2017.sql b/bin/diagnosticquery/SQLServerDiagnosticQueries_2017.sql index 410ed3605c..90c9e603c3 100644 --- a/bin/diagnosticquery/SQLServerDiagnosticQueries_2017.sql +++ b/bin/diagnosticquery/SQLServerDiagnosticQueries_2017.sql @@ -1,7 +1,7 @@ -- SQL Server 2017 Diagnostic Information Queries -- Glenn Berry --- Last Modified: April 1, 2024 +-- Last Modified: May 2, 2024 -- https://glennsqlperformance.com/ -- https://sqlserverperformance.wordpress.com/ -- YouTube: https://bit.ly/2PkoAM1 @@ -1521,20 +1521,21 @@ ON vfs.[file_id]= df.[file_id] OPTION (RECOMPILE); -- Get most frequently executed queries for this database (Query 58) (Query Execution Counts) SELECT TOP(50) LEFT(t.[text], 50) AS [Short Query Text], qs.execution_count AS [Execution Count], +ISNULL(qs.execution_count/DATEDIFF(Minute, qs.creation_time, GETDATE()), 0) AS [Calls/Minute], qs.total_logical_reads AS [Total Logical Reads], qs.total_logical_reads/qs.execution_count AS [Avg Logical Reads], qs.total_worker_time AS [Total Worker Time], qs.total_worker_time/qs.execution_count AS [Avg Worker Time], qs.total_elapsed_time AS [Total Elapsed Time], qs.total_elapsed_time/qs.execution_count AS [Avg Elapsed Time], -CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], -CONVERT(nvarchar(25), qs.last_execution_time, 20) AS [Last Execution Time], -CONVERT(nvarchar(25), qs.creation_time, 20) AS [Plan Cached Time] +CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], +qs.last_execution_time AS [Last Execution Time], qs.creation_time AS [Creation Time] --,t.[text] AS [Complete Query Text], qp.query_plan AS [Query Plan] -- uncomment out these columns if not copying results to Excel FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK) CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS t CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qp WHERE t.dbid = DB_ID() +AND DATEDIFF(Minute, qs.creation_time, GETDATE()) > 0 ORDER BY qs.execution_count DESC OPTION (RECOMPILE); ------ diff --git a/bin/diagnosticquery/SQLServerDiagnosticQueries_2019.sql b/bin/diagnosticquery/SQLServerDiagnosticQueries_2019.sql index a77daae461..f51d37b2d8 100644 --- a/bin/diagnosticquery/SQLServerDiagnosticQueries_2019.sql +++ b/bin/diagnosticquery/SQLServerDiagnosticQueries_2019.sql @@ -1,7 +1,7 @@ -- SQL Server 2019 Diagnostic Information Queries -- Glenn Berry --- Last Modified: April 11, 2024 +-- Last Modified: May 2, 2024 -- https://glennsqlperformance.com/ -- https://sqlserverperformance.wordpress.com/ -- YouTube: https://bit.ly/2PkoAM1 @@ -1596,20 +1596,21 @@ ON vfs.[file_id]= df.[file_id] OPTION (RECOMPILE); -- Get most frequently executed queries for this database (Query 60) (Query Execution Counts) SELECT TOP(50) LEFT(t.[text], 50) AS [Short Query Text], qs.execution_count AS [Execution Count], +ISNULL(qs.execution_count/DATEDIFF(Minute, qs.creation_time, GETDATE()), 0) AS [Calls/Minute], qs.total_logical_reads AS [Total Logical Reads], qs.total_logical_reads/qs.execution_count AS [Avg Logical Reads], qs.total_worker_time AS [Total Worker Time], qs.total_worker_time/qs.execution_count AS [Avg Worker Time], qs.total_elapsed_time AS [Total Elapsed Time], qs.total_elapsed_time/qs.execution_count AS [Avg Elapsed Time], -CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], -CONVERT(nvarchar(25), qs.last_execution_time, 20) AS [Last Execution Time], -CONVERT(nvarchar(25), qs.creation_time, 20) AS [Plan Cached Time] +CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], +qs.last_execution_time AS [Last Execution Time], qs.creation_time AS [Creation Time] --,t.[text] AS [Complete Query Text], qp.query_plan AS [Query Plan] -- uncomment out these columns if not copying results to Excel FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK) CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS t CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qp WHERE t.dbid = DB_ID() +AND DATEDIFF(Minute, qs.creation_time, GETDATE()) > 0 ORDER BY qs.execution_count DESC OPTION (RECOMPILE); ------ diff --git a/bin/diagnosticquery/SQLServerDiagnosticQueries_2022.sql b/bin/diagnosticquery/SQLServerDiagnosticQueries_2022.sql index 3d9ab485a6..b73f294600 100644 --- a/bin/diagnosticquery/SQLServerDiagnosticQueries_2022.sql +++ b/bin/diagnosticquery/SQLServerDiagnosticQueries_2022.sql @@ -1,7 +1,7 @@ -- SQL Server 2022 Diagnostic Information Queries -- Glenn Berry --- Last Modified: April 9, 2024 +-- Last Modified: May 2, 2024 -- https://glennsqlperformance.com/ -- https://sqlserverperformance.wordpress.com/ -- YouTube: https://bit.ly/2PkoAM1 @@ -1666,20 +1666,21 @@ ON vfs.[file_id]= df.[file_id] OPTION (RECOMPILE); -- Get most frequently executed queries for this database (Query 62) (Query Execution Counts) SELECT TOP(50) LEFT(t.[text], 50) AS [Short Query Text], qs.execution_count AS [Execution Count], +ISNULL(qs.execution_count/DATEDIFF(Minute, qs.creation_time, GETDATE()), 0) AS [Calls/Minute], qs.total_logical_reads AS [Total Logical Reads], qs.total_logical_reads/qs.execution_count AS [Avg Logical Reads], qs.total_worker_time AS [Total Worker Time], qs.total_worker_time/qs.execution_count AS [Avg Worker Time], qs.total_elapsed_time AS [Total Elapsed Time], qs.total_elapsed_time/qs.execution_count AS [Avg Elapsed Time], -CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], -CONVERT(nvarchar(25), qs.last_execution_time, 20) AS [Last Execution Time], -CONVERT(nvarchar(25), qs.creation_time, 20) AS [Plan Cached Time] +CASE WHEN CONVERT(nvarchar(max), qp.query_plan) COLLATE Latin1_General_BIN2 LIKE N'%%' THEN 1 ELSE 0 END AS [Has Missing Index], +qs.last_execution_time AS [Last Execution Time], qs.creation_time AS [Creation Time] --,t.[text] AS [Complete Query Text], qp.query_plan AS [Query Plan] -- uncomment out these columns if not copying results to Excel FROM sys.dm_exec_query_stats AS qs WITH (NOLOCK) CROSS APPLY sys.dm_exec_sql_text(plan_handle) AS t CROSS APPLY sys.dm_exec_query_plan(plan_handle) AS qp WHERE t.dbid = DB_ID() +AND DATEDIFF(Minute, qs.creation_time, GETDATE()) > 0 ORDER BY qs.execution_count DESC OPTION (RECOMPILE); ------ diff --git a/dbatools.psd1 b/dbatools.psd1 index 26d6a45018..998f59aac6 100644 --- a/dbatools.psd1 +++ b/dbatools.psd1 @@ -11,7 +11,7 @@ RootModule = 'dbatools.psm1' # Version number of this module. - ModuleVersion = '2.1.14' + ModuleVersion = '2.1.15' # ID used to uniquely identify this module GUID = '9d139310-ce45-41ce-8e8b-d76335aa1789'