Skip to content

Commit 9e257df

Browse files
Uwe Jankeclaude
andcommitted
Fix invalid DMV columns in three report functions (1.6.4.0)
Found via live runs against a local SQL 2022 plus a static validation of every DMV query through sys.dm_exec_describe_first_result_set. - Get-sqmMissingIndexes: join used mid.index_group_handle, which does not exist in sys.dm_db_missing_index_details (only index_handle). Fixed to mid.index_handle = mig.index_handle. - Get-sqmOperationStatus: AutoSeed query used non-existent columns total_size_bytes / start_time / estimated_completion_time_ms from sys.dm_hadr_physical_seeding_stats. Switched to the real columns database_size_bytes / start_time_utc / estimate_time_complete_utc (remaining time via DATEDIFF ms), aliased to the names the PowerShell side expects. - Get-sqmAlwaysOnFailoverHistory: optional SQL supplement read ars.role_start_time, which does not exist in sys.dm_hadr_availability_replica_states. Replaced with the valid column current_configuration_commit_start_time_utc (UTC approximation; Event Log 1480 stays authoritative), plus UTC comparison and NULL guard. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 2a02d7c commit 9e257df

5 files changed

Lines changed: 39 additions & 15 deletions

File tree

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# sqmSQLTool — Changelog
22

3+
## [1.6.4.0] — 2026-06-22
4+
5+
### 🔧 Fixes — ungültige DMV-Spalten (gefunden per Live-Lauf + statischer DMV-Validierung gegen SQL 2022)
6+
7+
- **Get-sqmMissingIndexes**: Join referenzierte `mid.index_group_handle`, das es in
8+
`sys.dm_db_missing_index_details` nicht gibt (nur `index_handle`). Query lieferte „Ungültiger
9+
Spaltenname index_group_handle" → keine Ergebnisse. Join korrigiert auf
10+
`mid.index_handle = mig.index_handle`.
11+
- **Get-sqmOperationStatus**: AutoSeed-Query nutzte die nicht existierenden Spalten `total_size_bytes`,
12+
`start_time` und `estimated_completion_time_ms` aus `sys.dm_hadr_physical_seeding_stats`. Korrigiert
13+
auf die realen Spalten `database_size_bytes`, `start_time_utc` und `estimate_time_complete_utc`
14+
(Restzeit per `DATEDIFF` in ms), per Alias auf die erwarteten Namen abgebildet.
15+
- **Get-sqmAlwaysOnFailoverHistory**: optionale SQL-Ergänzung las `ars.role_start_time`, das es in
16+
`sys.dm_hadr_availability_replica_states` nicht gibt. Ersetzt durch die valide Spalte
17+
`current_configuration_commit_start_time_utc` (UTC-Näherung; maßgeblich bleibt das Event Log,
18+
EventID 1480). UTC-Vergleich und NULL-Schutz ergänzt.
19+
320
## [1.6.3.0] — 2026-06-22
421

522
### 🔧 Fixes — dbatools-Parameter-/Cmdlet-Drift (gefunden per statischem Audit gegen dbatools 2.8.1, validiert gegen lokalen SQL 2022)

Public/Get-sqmAlwaysOnFailoverHistory.ps1

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
Liefert die Cluster-Perspektive des Failovers. Nur verfuegbar wenn WSFC
1717
installiert und der Log aktiv ist (-IncludeClusterLog).
1818
19-
Ergaenzung: sys.dm_hadr_availability_replica_states.role_start_time
20-
Zeigt den Zeitpunkt des letzten Rollenwechsels der lokalen Replica.
21-
Wird als zusaetzliche Zeile mit Source 'RoleStartTime' ausgegeben wenn
22-
-SqlInstance angegeben ist.
19+
Ergaenzung: sys.dm_hadr_availability_replica_states.current_configuration_commit_start_time_utc
20+
(Naeherung fuer den Rollenzeitpunkt der lokalen Replica - ein echtes role_start_time gibt es in
21+
dieser DMV nicht). Wird als zusaetzliche Zeile mit Source 'RoleStartTime' ausgegeben wenn
22+
-SqlInstance angegeben ist. Massgeblich bleibt das Event Log (EventID 1480).
2323
2424
FailoverType-Erkennung:
2525
- 'Planned' : EventID 1480, Message enthaelt "user" oder "manual"
@@ -321,7 +321,9 @@ SELECT
321321
ag.name AS AGName,
322322
ar.replica_server_name AS ReplicaName,
323323
ars.role_desc AS CurrentRole,
324-
ars.role_start_time AS RoleStartTime
324+
-- sys.dm_hadr_availability_replica_states hat KEIN role_start_time. Naechstbeste valide Spalte
325+
-- ist current_configuration_commit_start_time_utc (UTC) als Naeherung fuer den Rollenzeitpunkt.
326+
ars.current_configuration_commit_start_time_utc AS RoleStartTime
325327
FROM sys.dm_hadr_availability_replica_states ars
326328
JOIN sys.availability_replicas ar
327329
ON ar.replica_id = ars.replica_id
@@ -336,7 +338,8 @@ WHERE ars.is_local = 1
336338
foreach ($row in $rows)
337339
{
338340
if ($AvailabilityGroup -and $row.AGName -ne $AvailabilityGroup) { continue }
339-
if ($row.RoleStartTime -lt $Since) { continue }
341+
# RoleStartTime ist UTC; gegen UTC vergleichen. NULL (z.B. Secondary) ueberspringen.
342+
if (-not $row.RoleStartTime -or $row.RoleStartTime -lt $Since.ToUniversalTime()) { continue }
340343

341344
$computerResults.Add([PSCustomObject]@{
342345
ComputerName = $computer

Public/Get-sqmMissingIndexes.ps1

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ SELECT TOP $Top
150150
mid.database_id AS DatabaseId,
151151
mid.index_handle AS IndexHandle
152152
FROM sys.dm_db_missing_index_details mid
153-
INNER JOIN sys.dm_db_missing_index_groups mig ON mid.index_group_handle = mig.index_group_handle
153+
-- sys.dm_db_missing_index_details hat KEIN index_group_handle, nur index_handle.
154+
INNER JOIN sys.dm_db_missing_index_groups mig ON mid.index_handle = mig.index_handle
154155
INNER JOIN sys.dm_db_missing_index_group_stats migs ON mig.index_group_handle = migs.group_handle
155156
WHERE DB_NAME(mid.database_id) NOT IN ('master','model','msdb','tempdb')
156157
AND (migs.user_seeks + migs.user_scans) >= $MinSeeks

Public/Get-sqmOperationStatus.ps1

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -110,17 +110,20 @@ WHERE r.command IN ('BACKUP DATABASE', 'RESTORE DATABASE', 'BACKUP LOG', 'RESTOR
110110
# 2. AutoSeed Operationen ueber sys.dm_hadr_physical_seeding_stats abrufen
111111
# Diese DMV existiert ab SQL Server 2016
112112
$autoSeedQuery = @"
113-
SELECT
113+
-- Echte Spalten von sys.dm_hadr_physical_seeding_stats: database_size_bytes (nicht total_size_bytes),
114+
-- start_time_utc (nicht start_time), estimate_time_complete_utc (UTC-Zeit, nicht *_ms). Per Alias auf die
115+
-- vom PowerShell-Teil erwarteten Namen abgebildet; Restzeit aus der UTC-Zielzeit in ms umgerechnet.
116+
SELECT
114117
local_database_name AS database_name,
115118
role_desc,
116119
internal_state_desc,
117120
transfer_rate_bytes_per_second,
118121
transferred_size_bytes,
119-
total_size_bytes,
120-
start_time,
121-
estimated_completion_time_ms,
122-
CASE
123-
WHEN total_size_bytes > 0 THEN (transferred_size_bytes * 100.0 / total_size_bytes)
122+
database_size_bytes AS total_size_bytes,
123+
start_time_utc AS start_time,
124+
DATEDIFF(second, GETUTCDATE(), estimate_time_complete_utc) * 1000 AS estimated_completion_time_ms,
125+
CASE
126+
WHEN database_size_bytes > 0 THEN (transferred_size_bytes * 100.0 / database_size_bytes)
124127
ELSE 0
125128
END AS percent_complete
126129
FROM sys.dm_hadr_physical_seeding_stats

sqmSQLTool.psd1

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
RootModule = 'sqmSQLTool.psm1'
1818

1919
# Version number of this module.
20-
ModuleVersion = '1.6.3.0'
20+
ModuleVersion = '1.6.4.0'
2121

2222
# ID used to uniquely identify this module
2323
GUID = 'c4b10ba2-aee2-4d8d-ad86-a6e97c346ba6'
@@ -243,7 +243,7 @@
243243
# IconUri = ''
244244

245245
# ReleaseNotes of this module
246-
ReleaseNotes = 'See CHANGELOG.md and GitHub: https://github.com/JankeUwe/sqmSQLTool/releases/tag/v1.6.3.0'
246+
ReleaseNotes = 'See CHANGELOG.md and GitHub: https://github.com/JankeUwe/sqmSQLTool/releases/tag/v1.6.4.0'
247247

248248
# External module dependencies
249249
ExternalModuleDependencies = @('dbatools')

0 commit comments

Comments
 (0)