@@ -1475,9 +1475,109 @@ void Iso(string name, HeapColumn[] columns, Func<Parser.BatchContext, Database,
14751475 new ( "credential_id" , SqlType . Int32 , null , true ) ,
14761476 ] , EnumerateSysMasterFiles ) ;
14771477
1478+ // sys.database_query_store_options: per-database view (join key is the
1479+ // current database context, not a database_id column). Query Store is
1480+ // never enabled in the simulator, so a user database returns exactly
1481+ // one OFF row and a system database (master/tempdb/model/msdb) returns
1482+ // zero rows — the exact split a live SQL Server 2025 returns
1483+ // (probe-confirmed 2026-07-15). SSMS's Query Store probe gates on
1484+ // OBJECT_ID(N'[sys].[database_query_store_options]') resolving and then
1485+ // reads actual_state. nvarchar(60) _desc columns carry the probed
1486+ // max_length=120 bytes; actual_state_additional_info is nvarchar(4000)
1487+ // (probed max_length=8000 bytes), surfaced as the empty string.
1488+ Sys ( "database_query_store_options" ,
1489+ [
1490+ new ( "desired_state" , SqlType . SmallInt , null , false ) ,
1491+ new ( "desired_state_desc" , nvarchar60Catalog , 60 , true ) ,
1492+ new ( "actual_state" , SqlType . SmallInt , null , false ) ,
1493+ new ( "actual_state_desc" , nvarchar60Catalog , 60 , true ) ,
1494+ new ( "readonly_reason" , SqlType . Int32 , null , true ) ,
1495+ new ( "current_storage_size_mb" , SqlType . BigInt , null , true ) ,
1496+ new ( "flush_interval_seconds" , SqlType . BigInt , null , true ) ,
1497+ new ( "interval_length_minutes" , SqlType . BigInt , null , true ) ,
1498+ new ( "max_storage_size_mb" , SqlType . BigInt , null , true ) ,
1499+ new ( "stale_query_threshold_days" , SqlType . BigInt , null , true ) ,
1500+ new ( "max_plans_per_query" , SqlType . BigInt , null , true ) ,
1501+ new ( "query_capture_mode" , SqlType . SmallInt , null , false ) ,
1502+ new ( "query_capture_mode_desc" , nvarchar60Catalog , 60 , true ) ,
1503+ new ( "capture_policy_execution_count" , SqlType . Int32 , null , true ) ,
1504+ new ( "capture_policy_total_compile_cpu_time_ms" , SqlType . BigInt , null , true ) ,
1505+ new ( "capture_policy_total_execution_cpu_time_ms" , SqlType . BigInt , null , true ) ,
1506+ new ( "capture_policy_stale_threshold_hours" , SqlType . Int32 , null , true ) ,
1507+ new ( "size_based_cleanup_mode" , SqlType . SmallInt , null , false ) ,
1508+ new ( "size_based_cleanup_mode_desc" , nvarchar60Catalog , 60 , true ) ,
1509+ new ( "wait_stats_capture_mode" , SqlType . SmallInt , null , false ) ,
1510+ new ( "wait_stats_capture_mode_desc" , nvarchar60Catalog , 60 , true ) ,
1511+ new ( "actual_state_additional_info" , SqlType . NVarchar , 4000 , true ) ,
1512+ ] , EnumerateSysDatabaseQueryStoreOptions ) ;
1513+
1514+ // sys.query_store_runtime_stats: per-plan runtime-statistics capture.
1515+ // The simulator never runs Query Store, so no runtime stats are ever
1516+ // captured and the view is always empty. SSMS's Query Store probe does
1517+ // IF EXISTS (SELECT TOP(1) 1 FROM sys.query_store_runtime_stats), which
1518+ // must resolve and return zero rows. Column shape probe-confirmed
1519+ // against SQL Server 2025 (2026-07-15): the first nine metric groups
1520+ // carry NOT NULL last/min/max columns, the last four NULL.
1521+ Sys ( "query_store_runtime_stats" ,
1522+ BuildQueryStoreRuntimeStatsColumns ( nvarchar60Catalog ) ,
1523+ static ( _ , _ ) => EmptyCatalogRows ) ;
1524+
14781525 return views ;
14791526 }
14801527
1528+ /// <summary>
1529+ /// Column shape for <c>sys.query_store_runtime_stats</c>. The nine
1530+ /// "core" metrics (duration, cpu_time, logical/physical IO, clr_time,
1531+ /// dop, query_max_used_memory, rowcount) expose NOT NULL last/min/max
1532+ /// columns; the four "extended" metrics (num_physical_io_reads,
1533+ /// log_bytes_used, tempdb_space_used, page_server_io_reads) expose them
1534+ /// NULL — matching the probed SQL Server 2025 catalog shape. The view is
1535+ /// always empty, so the column set only ever backs metadata reads.
1536+ /// </summary>
1537+ private static HeapColumn [ ] BuildQueryStoreRuntimeStatsColumns ( NVarcharSqlType nvarchar60Catalog )
1538+ {
1539+ var columns = new List < HeapColumn >
1540+ {
1541+ new ( "runtime_stats_id" , SqlType . BigInt , null , false ) ,
1542+ new ( "plan_id" , SqlType . BigInt , null , false ) ,
1543+ new ( "runtime_stats_interval_id" , SqlType . BigInt , null , false ) ,
1544+ new ( "execution_type" , SqlType . TinyInt , null , false ) ,
1545+ new ( "execution_type_desc" , nvarchar60Catalog , 60 , true ) ,
1546+ new ( "first_execution_time" , SqlType . GetDateTimeOffset ( 7 ) , null , false ) ,
1547+ new ( "last_execution_time" , SqlType . GetDateTimeOffset ( 7 ) , null , false ) ,
1548+ new ( "count_executions" , SqlType . BigInt , null , false ) ,
1549+ } ;
1550+
1551+ void Metric ( string metric , bool aggregatesNullable )
1552+ {
1553+ columns . Add ( new ( "avg_" + metric , SqlType . Float , null , true ) ) ;
1554+ columns . Add ( new ( "last_" + metric , SqlType . BigInt , null , aggregatesNullable ) ) ;
1555+ columns . Add ( new ( "min_" + metric , SqlType . BigInt , null , aggregatesNullable ) ) ;
1556+ columns . Add ( new ( "max_" + metric , SqlType . BigInt , null , aggregatesNullable ) ) ;
1557+ columns . Add ( new ( "stdev_" + metric , SqlType . Float , null , true ) ) ;
1558+ }
1559+
1560+ foreach ( var metric in new [ ]
1561+ {
1562+ "duration" , "cpu_time" , "logical_io_reads" , "logical_io_writes" ,
1563+ "physical_io_reads" , "clr_time" , "dop" , "query_max_used_memory" , "rowcount" ,
1564+ } )
1565+ {
1566+ Metric ( metric , aggregatesNullable : false ) ;
1567+ }
1568+
1569+ foreach ( var metric in new [ ]
1570+ {
1571+ "num_physical_io_reads" , "log_bytes_used" , "tempdb_space_used" , "page_server_io_reads" ,
1572+ } )
1573+ {
1574+ Metric ( metric , aggregatesNullable : true ) ;
1575+ }
1576+
1577+ columns . Add ( new ( "replica_group_id" , SqlType . BigInt , null , false ) ) ;
1578+ return [ .. columns ] ;
1579+ }
1580+
14811581 /// <summary>
14821582 /// Shared empty row set for the AlwaysOn Availability-Group catalog views
14831583 /// (<c>sys.availability_replicas</c> / <c>sys.availability_groups</c> /
@@ -3211,6 +3311,49 @@ private static IEnumerable<SqlValue[]> EnumerateSysDatabaseMirroring(Parser.Batc
32113311 }
32123312 }
32133313
3314+ /// <summary>
3315+ /// Rows for <c>sys.database_query_store_options</c> — one OFF row per user
3316+ /// database, zero rows for a system database (master/tempdb/model/msdb per
3317+ /// <see cref="Simulation.SystemDatabaseNames"/>). The simulator never
3318+ /// enables Query Store, so the single row is the fixed "disabled" shape a
3319+ /// live SQL Server 2025 returns for a Query-Store-off user database
3320+ /// (desired/actual OFF, query_capture_mode CUSTOM). The join key is the
3321+ /// database context (<paramref name="database"/>), so a three-part
3322+ /// <c>master.sys.database_query_store_options</c> read returns nothing.
3323+ /// </summary>
3324+ private static IEnumerable < SqlValue [ ] > EnumerateSysDatabaseQueryStoreOptions ( Parser . BatchContext batch , Database database )
3325+ {
3326+ _ = batch ;
3327+ if ( Simulation . SystemDatabaseNames . Contains ( database . Name ) )
3328+ yield break ;
3329+
3330+ var off = SqlValue . FromNVarchar ( "OFF" ) ;
3331+ yield return [
3332+ SqlValue . FromInt16 ( 0 ) , // desired_state
3333+ off , // desired_state_desc
3334+ SqlValue . FromInt16 ( 0 ) , // actual_state
3335+ off , // actual_state_desc
3336+ SqlValue . FromInt32 ( 0 ) , // readonly_reason
3337+ SqlValue . FromInt64 ( 0 ) , // current_storage_size_mb
3338+ SqlValue . FromInt64 ( 900 ) , // flush_interval_seconds
3339+ SqlValue . FromInt64 ( 60 ) , // interval_length_minutes
3340+ SqlValue . FromInt64 ( 1000 ) , // max_storage_size_mb
3341+ SqlValue . FromInt64 ( 30 ) , // stale_query_threshold_days
3342+ SqlValue . FromInt64 ( 200 ) , // max_plans_per_query
3343+ SqlValue . FromInt16 ( 4 ) , // query_capture_mode
3344+ SqlValue . FromNVarchar ( "CUSTOM" ) , // query_capture_mode_desc
3345+ SqlValue . FromInt32 ( 30 ) , // capture_policy_execution_count
3346+ SqlValue . FromInt64 ( 1000 ) , // capture_policy_total_compile_cpu_time_ms
3347+ SqlValue . FromInt64 ( 100 ) , // capture_policy_total_execution_cpu_time_ms
3348+ SqlValue . FromInt32 ( 24 ) , // capture_policy_stale_threshold_hours
3349+ SqlValue . FromInt16 ( 0 ) , // size_based_cleanup_mode
3350+ off , // size_based_cleanup_mode_desc
3351+ SqlValue . FromInt16 ( 0 ) , // wait_stats_capture_mode
3352+ off , // wait_stats_capture_mode_desc
3353+ SqlValue . FromNVarchar ( string . Empty ) , // actual_state_additional_info
3354+ ] ;
3355+ }
3356+
32143357 /// <summary>
32153358 /// Rows for <c>sys.master_files</c> — one data file (<c>type</c> 0, ROWS)
32163359 /// and one log file (<c>type</c> 1, LOG) per database, join key
0 commit comments