Skip to content

Set-DbaDbQueryStoreOption - Refresh the Query Store options after changing them with T-SQL - #10593

Merged
potatoqualitee merged 1 commit into
developmentfrom
fix-set-querystoreoption-refresh
Aug 22, 2026
Merged

Set-DbaDbQueryStoreOption - Refresh the Query Store options after changing them with T-SQL#10593
potatoqualitee merged 1 commit into
developmentfrom
fix-set-querystoreoption-refresh

Conversation

@andreasjordan

Copy link
Copy Markdown
Collaborator

Type of Change

Purpose

MaxPlansPerQuery, WaitStatsCaptureMode and the four CustomCapturePolicy* options are changed with an ALTER DATABASE statement rather than through SMO. The SMO object knows nothing about that and still holds what it read before, so the command reported the values from before its own change and left the object of the caller saying the same:

returned by Set     : MaxPlansPerQuery=200
the instance has    : MaxPlansPerQuery=555

This is not the staleness that a reused connection brings with it. It happens on every call, including one where the command opens the connection itself, because the command reads $db.QueryStoreOptions before it runs the statement and that fills the cache.

Copy-DbaDbQueryStoreOption is fixed with it, because it copies the settings by calling this command.

Approach

The SMO path a few lines above already does the right thing:

$db.QueryStoreOptions.DesiredState = $State
$db.QueryStoreOptions.Alter()
$db.QueryStoreOptions.Refresh()

The T-SQL path now gets the same treatment, right after the statement:

if ($query -ne "") {
    $null = $server.Query($query)
    $db.QueryStoreOptions.Refresh()
}

That is one round trip per database, and only for the calls that actually use one of these options. What a reused connection reports about changes made elsewhere is unaffected, as it should be.

Commands to test

$server = Connect-DbaInstance -SqlInstance $instance
$null = Set-DbaDbQueryStoreOption -SqlInstance $server -Database $dbName -State ReadWrite

Set-DbaDbQueryStoreOption -SqlInstance $server -Database $dbName -MaxPlansPerQuery 555 -WaitStatsCaptureMode Off |
    Select-Object MaxPlansPerQuery, WaitStatsCaptureMode      # 555 / Off, was 200 / On

Tests

A Context that sets both options and expects:

  • the returned object to carry them
  • the SMO object of the caller to carry them, which is the part a Get- command cannot paper over
  • the instance to really have them, which passes either way and says the T-SQL was never the problem

The first two fail against development with Expected 555, but got 200.

Set-DbaDbQueryStoreOption: 11 tests, all passing, no leftovers in the lab.

Note on the test fixture

The new Context uses the database that the Describe already creates rather than one of its own. A CREATE DATABASE at that point fails intermittently with

Could not obtain exclusive lock on database 'model'. Retry the operation later.

because the tests above it read Query Store on model and leave a session parked in it. That is the leak #10584 fixes, which is not merged yet - worth knowing that it now reaches test files that have nothing to do with connection handling.


This text was created by Claude and reviewed by Andreas Jordan.

…nging them with T-SQL

MaxPlansPerQuery, WaitStatsCaptureMode and the four CustomCapturePolicy options are changed with an
ALTER DATABASE statement rather than through SMO. The SMO object knows nothing about that and still
holds what it read before, so the command reported the values from before its own change and left the
object of the caller saying the same. This is not the staleness a reused connection brings with it: it
happens on every call, because the command reads $db.QueryStoreOptions before it runs the statement
and that fills the cache.

The SMO path a few lines above already does Alter followed by Refresh. The T-SQL path now does the
same, right after the statement, which is one round trip and only for the calls that use one of these
options. Copy-DbaDbQueryStoreOption is fixed with it, because it copies the settings through this
command.

Fixes #10561.

Tests: a Context that sets MaxPlansPerQuery and WaitStatsCaptureMode and expects the returned object
and the SMO object of the caller to carry them, plus a check that the instance really has them, which
passes either way and says the T-SQL was never the problem. Both new assertions fail against
development with "Expected 555, but got 200".

It uses the database of the Describe rather than creating one: a CREATE DATABASE at that point 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 merged yet.

(do Set-DbaDbQueryStoreOption, Copy-DbaDbQueryStoreOption)
@potatoqualitee
potatoqualitee merged commit b86bb5f into development Aug 22, 2026
23 of 24 checks passed
@potatoqualitee
potatoqualitee deleted the fix-set-querystoreoption-refresh branch August 22, 2026 17:04
@potatoqualitee

Copy link
Copy Markdown
Member

looks good 👌🏼 ty

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Set-DbaDbQueryStoreOption - Returns the old values for the settings it changes with T-SQL

2 participants