diff --git a/public/Set-DbaDbQueryStoreOption.ps1 b/public/Set-DbaDbQueryStoreOption.ps1 index 04a1de36dcf..271098a5c94 100644 --- a/public/Set-DbaDbQueryStoreOption.ps1 +++ b/public/Set-DbaDbQueryStoreOption.ps1 @@ -345,6 +345,12 @@ function Set-DbaDbQueryStoreOption { if ($query -ne "") { $null = $server.Query($query) + # These options are changed with T-SQL rather than through SMO, so the SMO + # object knows nothing about it and still holds what it read before. Without + # this the command reports the values from before its own change, and leaves + # the object of the caller saying the same. It is the treatment the SMO path + # above already gets after its Alter. See #10561. + $db.QueryStoreOptions.Refresh() } } catch { Stop-Function -Message "Could not modify configuration." -Category InvalidOperation -InnerErrorRecord $_ -Target $db -Continue diff --git a/tests/Set-DbaDbQueryStoreOption.Tests.ps1 b/tests/Set-DbaDbQueryStoreOption.Tests.ps1 index d2b4769e4f8..99896617c29 100644 --- a/tests/Set-DbaDbQueryStoreOption.Tests.ps1 +++ b/tests/Set-DbaDbQueryStoreOption.Tests.ps1 @@ -37,6 +37,14 @@ Describe $CommandName -Tag UnitTests { } Describe $CommandName -Tag IntegrationTests { + BeforeDiscovery { + # MaxPlansPerQuery and WaitStatsCaptureMode arrived with SQL Server 2017. The value decides a + # Skip, which Pester needs while it discovers the tests, so it cannot be read in BeforeAll. + $discoveryServer = Connect-DbaInstance -SqlInstance $TestConfig.InstanceMulti1 + $multi1VersionMajor = $discoveryServer.VersionMajor + $null = $discoveryServer | Disconnect-DbaInstance + } + BeforeAll { Get-DbaDatabase -SqlInstance $TestConfig.InstanceMulti1, $TestConfig.InstanceMulti2 | Where-Object Name -Match "dbatoolsci" | Remove-DbaDatabase New-DbaDatabase -SqlInstance $TestConfig.InstanceMulti1, $TestConfig.InstanceMulti2 -Name dbatoolsciqs @@ -144,4 +152,48 @@ Describe $CommandName -Tag IntegrationTests { } } } + + Context "When an option is changed that needs T-SQL" -Skip:($multi1VersionMajor -lt 14) { + BeforeAll { + $PSDefaultParameterValues["*-Dba*:EnableException"] = $true + + # The database of the Describe rather than one of its own. A CREATE DATABASE here fails + # intermittently with "Could not obtain exclusive lock on database 'model'", because the tests + # above read Query Store on model and leave a session parked in it. That is #10584, which is + # not in development yet, and this Context does not need a database of its own anyway. + $refreshDbName = "dbatoolsciqs" + + # The server object is kept, because the point of this is what the command leaves behind on it. + $refreshServer = Connect-DbaInstance -SqlInstance $TestConfig.InstanceMulti1 + $null = Set-DbaDbQueryStoreOption -SqlInstance $refreshServer -Database $refreshDbName -State ReadWrite + + # MaxPlansPerQuery and WaitStatsCaptureMode are changed with ALTER DATABASE rather than through + # SMO, so the SMO object knows nothing about it and still holds what it read before. See #10561. + $resultsRefresh = Set-DbaDbQueryStoreOption -SqlInstance $refreshServer -Database $refreshDbName -MaxPlansPerQuery 555 -WaitStatsCaptureMode Off + + $PSDefaultParameterValues.Remove("*-Dba*:EnableException") + } + + AfterAll { + $PSDefaultParameterValues["*-Dba*:EnableException"] = $true + + $null = $refreshServer | Disconnect-DbaInstance + + $PSDefaultParameterValues.Remove("*-Dba*:EnableException") + } + + It "Returns the values it has just set" { + $resultsRefresh.MaxPlansPerQuery | Should -Be 555 + $resultsRefresh.WaitStatsCaptureMode | Should -Be "Off" + } + + It "Leaves the SMO object of the caller with the new values" { + $refreshServer.Databases[$refreshDbName].QueryStoreOptions.MaxPlansPerQuery | Should -Be 555 + } + + It "Really changed them on the instance" { + $verifyQuery = "SELECT max_plans_per_query AS MaxPlansPerQuery FROM sys.database_query_store_options" + (Invoke-DbaQuery -SqlInstance $TestConfig.InstanceMulti1 -Database $refreshDbName -Query $verifyQuery).MaxPlansPerQuery | Should -Be 555 + } + } } \ No newline at end of file