Skip to content

[BUG] query_store_health collects nothing on Azure SQL DB logical-server registrations: the same three-part [db].sys.sp_executesql that #3755 removed from database_scoped_config #3764

Closed

Description

@erikdarlingdata

Component

Darling

Performance Monitor Version

dev @ 59f2ed3 (after #3760)

Describe the Bug

query_store_health carries the defect #3755 fixed in database_scoped_config, identically. QueryStoreHealthCollector.BuildPerItemQuery runs every per-database read through a three-part reference under the same comment:

/* Use [dbname].sys.sp_executesql to run in database context (Azure SQL DB compatible). One row ... */
EXECUTE [{item...}].sys.sp_executesql

Azure SQL DB resolves a three-part name only when the named database IS the connection's current database, so on a logical-server registration (connection in master, every enumerated database some other database) every fan-out item is rejected with Reference to database and/or server name in '<db>.sys.sp_executesql' is not supported in this version of SQL Server, the host tolerates each as a per-database skip, and the run lands SUCCESS, rows=0 (the swallowing itself is #3754).

The collector branches for Azure only in its database LIST (context.Target.IsAzureSqlDb ? AzureDatabaseListQueryText : OnPremDatabaseListQueryText, QueryStoreHealthCollector.cs:131), has no RunsPerDatabase override, and its header (:27-29) says its enumeration shape is DatabaseScopedConfigCollector's "verbatim" - a cross-reference #3760 made stale, since that collector now declares RunsPerDatabase(target) => target.IsAzureSqlDb and runs one shared payload body on the host's per-database connection loop.

Found by the #3755 lane's out-of-lane sweep of the five enumerated collectors: query_store, plan_correction and index_object_stats already ride the per-database loop on Azure; query_store_health is the last one on the three-part idiom. This matters more for query_store_health than for a config snapshot: the collector exists to catch the actual_state / readonly_reason / cap-hit transition to READ_ONLY (#2319), and on Azure logical-server registrations it has never observed one.

Expected Behavior

Same fix shape as #3760: RunsPerDatabase(target) => target.IsAzureSqlDb; BuildQuery returns the bare payload on Azure and throws off it; BuildEnumerationQuery returns null on Azure and the dead Azure list query is deleted; one shared payload body that the on-prem sp_executesql wrapper quote-doubles; the (Azure SQL DB compatible) comment and the "verbatim" cross-reference rewritten to what is true. Pin: with IsAzureSqlDb = true the produced query text matches no \]\.sys\.sp_executesql, and on-prem/MI/RDS keep enumerating.

Note the census: after #3760, CollectorDatabaseScopeRungTests / the enumerator inventories expect query_store_health to be the ONLY enumerator on the Azure target; this fix empties that set, so those pins move with it.

Additional Context

Prose that also drifted with #3760 (not pinned, cosmetic): the get_collection_health tool description in DarlingMcpDataTools.cs says "eight more fan out over a per-database connection loop when the target is Azure SQL DB" - it was nine before #3760 (long_query_completions was the ninth) and is ten now; the same "eight" appears in doc comments in PgMigrations.cs, CollectionLogFanoutRollupStoreTests.cs and CollectorDatabaseScopeRungTests.cs. Whichever lane takes this one can make it eleven and say so once.

Activity

  1. erikdarlingdata commented on Sep 20, 2026

    @erikdarlingdata
    OwnerAuthor

    Closed by #3777 (merged to dev).

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions