Repository navigation
Finish CONTRIBUTING.md's data-type rule: rewrite the 33 abbreviated int sites and move UnabbreviatedTypes in scope #3087
Description
CONTRIBUTING.md's Data types bullet states two independent properties — "lowercase, never abbreviated (integer not int, nvarchar(max) not nvarchar(MAX))". #3081 / #3085 enforced the case half and deliberately left the abbreviation half uncovered, on a stated remediation cost rather than on detectability. TsqlConventionGuardTests already carries the detector (AbbreviatedTypeUse) and the measurement (AbbreviatedTypeSites()); Findings just declines to emit the rule.
That was the right call for a change whose subject was the guard. It is a half-state now, and the guard says so in its own words: TheAbbreviationScopeNote_CountsTheSitesItClaims reds the moment the count moves, and its message names the follow-through — "move UnabbreviatedTypes from the Data types bullet's Uncovered side to its Covered side, emit it from Findings, and give it a hazard fixture."
This issue is that follow-through: rewrite the sites, then move the rule in scope.
The count, re-derived
Driven through the guard's own AbbreviatedTypeSites() — the same population, the same code view, and the same TypeNameClauseCollisions blanking the enforced checks read — rather than a fresh grep:
33 sites in 7 files. Agrees with the figure the scope note carries, and every site enumerates back to a distinct regex match, so the total is not covering for a collapsed key.
| File | Sites |
|---|---|
Lite/Services/LocalDataService.FinOps.ServerProperties.cs |
10 |
PerformanceMonitor.Collectors/DatabaseSizeStatsCollector.cs |
9 |
PerformanceMonitor.Collectors/ServerPropertiesCollector.cs |
5 |
Lite/Services/LocalDataService.FinOps.Recommendations.cs |
4 |
Darling/PerformanceMonitor.Darling.Analysis/PgPlanFetcher.cs |
2 |
Lite/Services/LocalDataService.QueryStats.cs |
2 |
PerformanceMonitor.Collectors/MemoryStatsCollector.cs |
1 |
int is the only abbreviation present. dec for decimal and double precision for float are the others T-SQL accepts and neither appears — a bound on the figure, not on the rule.
Scope of the in-scope move
All of it, or the disposition map contradicts itself:
UnabbreviatedTypesmoves from theData typesbullet'sUncoveredarray to itsCoveredarray.Findingsemits it.- It gets a hazard fixture in
TheDetector_FlagsEveryCoveredRule_AndNoBenignForm, whose rule coverage is asserted at set equality againstCoveredRules. - Its fixture is deleted from
TheUncoveredRules_AreViolatedByFixturesThisGuardDoesNotFlag, whose fixture set is asserted at set equality againstUncoveredRules. - The abbreviation-cost pin (
TheAbbreviationScopeNote_CountsTheSitesItClaims) and the note text it parses are deleted — a cost pin for a cost nobody is paying any more is a pin that can only go stale. - The split-pair assertion in
TheDispositionMap_PartitionsTheBulletsContributingStatesdrops to{ "Indentation" }, sinceData typesstops being split. That assertion names the split bullets rather than counting them, so it reds rather than drifting — which is the whole reason it is shaped that way.
Two things that need care rather than a sweep
1. Three of the seven files carry an sp_executesql PARAMETER DECLARATION, not a query body
PgPlanFetcher.cs and LocalDataService.QueryStats.cs both hold N'@h varbinary(64), @stmt_start int, @stmt_end int', and LocalDataService.FinOps.Recommendations.cs holds N'@c int OUTPUT' — the same class, and the scope note only named the first shape.
A parameter declaration is not a statement body, so "DECLARE @x integer is valid, therefore this is too" is an inference about a grammar position rather than a fact about it. Nothing in this repository executes that path, so no test here can settle it and a green build would mean nothing.
It wants a live parse check, and the check should not be run against a monitored production server.
2. Every edit is inside a query string that runs against monitored production servers
The compiler cannot see a typo in one, so the parity pins are the only thing between a bad edit and a shipped one. #3085 established that none of the nine sites it fixed was verbatim-pinned by a *CollectorDefinitionTests parity constant — but these are different files, and that conclusion should not be inherited. Establish it per file, and re-run the guard afterwards.
Acceptance
- 33 → 0, re-derived through
AbbreviatedTypeSites()rather than asserted. - The rule reads as
Coveredand reds by name onUnabbreviatedTypeswhen one of the rewritten sites is reverted. A rule moved toCoveredthat cannot fail is worse than one honestly left uncovered. - The detector must not match
intinside a longer token —integer,bigint,smallint,tinyint,int_col,sysint— and those belong in the benign fixture set, where a greedy or unanchored match reds.
Activity
Fixes #3087 (#3092)
erikdarlingdata commentedon Sep 6, 2026
Claude posting for Erik Darling
Fixed by #3092, merged to
devas6b336da37b9. Closing by hand — a closing keyword does not fire on adev-targeted PR here.33 abbreviated
inttype positions rewritten tointegeracross 7 files, andUnabbreviatedTypesmoved from the guard'sUncoveredtoCovered.CONTRIBUTING.md's data-type bullet is now enforced in both halves.The count is 33 only in the right unit, and that matters for anyone re-deriving it. The diff carries 41 added lines containing
integer, minus 9 in the guard's own test file and 1 parity pin, leaving 31 production lines. Two of those lines carry two declarations each — thevarbinary/@stmt_start/@stmt_endline in bothPgPlanFetcher.csandLocalDataService.QueryStats.cs. Counting type positions, which is the unit the rule operates on, gives 31 + 2 = 33. A line count and a word count both disagree with it, and both are the wrong unit.Two care items broke the expected way:
Lite.Tests/MemoryCollectorsDefinitionTests.cs:35pinnedCONVERT(int, NULL)againstMemoryStatsCollector's Azure variant, found by scanning 56,098 string literals across 757 test files. It moved with the query in this PR; reverting the query while leaving the pin redsBuildQuery_SelectsVariantByTarget. Editing the query without it would have failedbuild.sp_executesqlparse question was the weak half.integerparses inside a parameter-declaration string and binds asint— so the parse alone establishes nothing, because SQL Server normalises the synonym and any read-back reportsint. What was established instead: nothing reads the declaration back. ZeroDeriveParameters, zerosys.parameters, zerosys.typesacross the shipped trees, withSqlDbTypeas a positive control returning three files so the search was alive. The oneGetSchemaTablehit is a pass-through decorator reading result-set metadata, not parameter metadata.A third declaration site the original scope note never named —
N'@c int OUTPUT'inFinOps.Recommendations— was found and probed. Thesp_executesqlshape is now a permanent hazard fixture rather than a memory.Probes ran on stage (SQL Server 2022, 16.0.4215.2) via SSM port-forward. No production server was touched.
Not verified: no query in this diff was executed in the form the diff ships it. Only purpose-built read-only probes of each shape it uses. Worth knowing that these collectors run every minute across the fleet, so the next nightly carrying this build is the first time these queries execute in production.
Zero abbreviated type positions remain, with a before/after that proves the pattern was alive: the detector pattern matches 5 files on the pre-merge
devand 0 on this branch. A zero from a pattern that also returned zero beforehand would have proved nothing.