Repository navigation
Fixes #3081 - #3085
Fixes #3081#3085
Conversation
CONTRIBUTING.md's T-SQL Style list opens "All T-SQL code must follow" and nothing enforced any of it: PR #3078 introduced COUNT(*) and COUNT(DISTINCT ...) into a new collector query and passed the Linux build, the PostgreSQL tests, all four whole-tree guards, the command-deadline family, review and verify. TsqlConventionGuardTests scans string literals that OPEN a T-SQL statement across the shared libraries and both SKUs' app trees, and enforces four of the nine bullets: COUNT_BIG() over COUNT(), ROWCOUNT_BIG() over @@rowcount, block comments over --, no tabs, and lowercase data types. The other five bullets, and the abbreviation half of the data-type bullet, are recorded with their reasons and carry a fixture each whose expected answer is empty. The nine pre-existing violations of the covered subset are fixed here, so the guard lands with no waiver list: two COUNT(*) in DatabaseSizeStatsCollector and one inside sp_executesql in Lite's FinOps recommendations, one -- comment in DarlingServerConnector's T-SQL probe (its PostgreSQL twin keeps its own, correctly), and NVARCHAR(500), VARBINARY(64), NVARCHAR(128) and two nvarchar(MAX) spellings.
The Functions bullet's phrase list asked for COUNT_BIG(), and rewriting CONTRIBUTING.md's COUNT_BIG() to COUNTBIG() left the check green: two words later ROWCOUNT_BIG() still contains COUNT_BIG() as a substring, so the Contains was satisfied by the wrong token. Found by mutating the document rather than by reading the list. The phrases now carry the backticks the document writes them with, and EveryRequiredPhrase_IsLoadBearingOnItsOwn deletes each one from the real bullet text in turn and requires the check to red - so a phrase absorbed by a longer neighbour cannot pass again.
Two claims had no case that could distinguish them, and a mutation of each survived. The nested-block-comment fixture put its -- BEFORE the inner close, where a nesting and a non-nesting walk both read it as comment. It now sits after the inner close and before the outer one, which only the nesting walk keeps inside a comment. The MAX length spec's requirement that the name in front of it be a data type changed no answer on any fixture, because none had (MAX) after a non-type identifier. MAX(MAX) - legal T-SQL, since MAX is not reserved and a column may be named it - is textually IDENT ( max ) and reds without the anchor.
Removing the lookbehind from the COUNT( pattern changed no answer on any fixture. COUNT_BIG( and ROWCOUNT_BIG() are rescued by the underscore that follows COUNT rather than by what precedes it, and @@rowcount is never followed by an open parenthesis - so the lookbehind's whole job is an identifier that ends in Count and is then called. dbo.RowCount(...) is that shape.
…lity Two things, one change. A per-tree floor is satisfied by any file in the tree, so each group now names an anchor whose T-SQL must stay visible: the file #3078's violation landed in, and the two non-shared files this change fixed. A glob that reaches part of a tree, or a marker set that goes blind on one file's shape, now fails by name. And the anchors are separator-bearing path literals, which is the first arm of CrossAppGuardCiGateTests' C# matcher. The bare "Lite" in ScannedTrees is the collection-declared-in-one-member shape that matcher records as invisible, so before the anchors existed this file's read of Lite was not in its found set at all - pointing a root at Lite.Tests, which the darling filter cannot reach, changed nothing. With the anchors it reds.
CrossAppGuardCiGateTests drops references that do not resolve on disk, so the first attempt at proving the anchor reaches its found set used a filename that was not there and reported a pass that meant nothing.
The Data types bullet's abbreviation half is left uncovered on a cost - 33 int-for-integer sites across 7 files - and a cost written down once goes stale by exactly the mechanism this guard exists to stop. The detector for the rule now lives beside the enforced ones, reads the same population and the same code view, and its count is compared against the figure the scope note states. The direction that matters is downward: when those sites are fixed the pin says to move the rule to the covered side, rather than leaving an unguarded rule behind a reason that has expired.
"twenty-three times" was 21, which is what an unpinned numeral in prose does. That one and the command-deadline family's test count are gone; the figure they were decorating was never the point. The .sql-tree measurement stays because it is the evidence for a scope decision, but it now says it was taken once and not re-taken, so nobody reads it as a live figure. The only live count left is the abbreviation cost, and a pin holds that one.
The token checks read single-quoted spans other than XQuery arguments, so a string VALUE containing a banned token would be reported as the token. There is none, and the direction is a spurious red on correct SQL rather than a hidden violation - but the alternative is missing every violation inside dynamic SQL, and one sp_executesql body held one of the nine fixed here. Worth saying out loud rather than leaving to be rediscovered.
An audit of every numeral in the file found three more that were simply wrong: "three bullets are split" (two are), "six files carry a -- inside a block comment" (five do), and "four N'' literals inside one sp_executesql" (three). Each was decorating a point the numeral was not making. The split bullets are now named rather than counted, and a set-equality assertion holds the naming, so a third one reds instead of leaving the prose incomplete. The rest are named instances or structural facts.
|
Reviewed the diff (6 production files + the new Production fixes ( New test file (
One low-severity, non-blocking observation: No correctness bugs, security issues, or Lite/Darling parity drift found. No missing-index-DMV suggestions to make. |
PR #3084 landed while this was open and wrote the three spellings CrossAppGuardCiGateTests can see into CONTRIBUTING.md, naming a segment array declared in another member as silent by construction. That is the shape this file's root list has, and the anchors are the first of the three - so the claim now points at the document rather than at the guard's own doc comment, and the red-proof was re-run against the merged matcher.
|
Reviewed. This is a well-constructed, exhaustively self-tested PR — the analysis below focuses on what could still be wrong despite the 54-mutation red-proof already documented. Production T-SQL fixes (7 files, small diffs): all semantics-preserving and consistent with
Lite/Darling parity: checked for a Darling counterpart to each touched Lite-only file ( The new guard itself ( Left one inline comment on a minor, non-blocking gap in the quoted-identifier ( No security, missing-index-DMV, or performance concerns — this PR only adds a test file and fixes casing/function-name violations in existing collector SQL. |
The summary claimed every read of a monitored SQL Server goes through a DMV, a catalog view or a built-in, so nothing T-SQL could fall outside the population. That is a universal quantifier, and testing it instead of stating it found two counter-examples in the population's complement. One mattered: DarlingXeSessions' provisioning DDL - CREATE/ALTER/DROP EVENT SESSION with sqlserver.* events and package0.ring_buffer targets - is real T-SQL sent to production servers on every session repair, and carried no marker at all. TsqlMarkers now reaches EVENT SESSION, sqlserver. and package0., and two of those statements are population fixtures. They carry no violation of the covered rules. What remains is FactRemediation's cursor fetch, twice, and TheTsqlTheMarkerSetCannotSee_IsTheseAndNoOthers holds it at set equality over the complement so a third cannot arrive unnoticed. The complement is 500-odd literals; the discriminator that makes it readable is the parameter spelling, @name being the one thing neither store dialect writes. Also closes the ]] escape in the quoted-identifier walk, which the review of this change flagged as the asymmetry with the '' arm beside it.
sqlserver. and package0. went in beside EVENT SESSION. Measured: zero statements in the corpus carry either without also carrying EVENT SESSION, so no fixture could show them mattering and a mutation deleting them stayed green. A marker nothing depends on is a claim nothing holds. EVENT SESSION is the one that earns its line, and it is red-proofed.
|
Reviewed. This is a test-infrastructure PR (new Production diffs (6 files) — all six are pure case/spelling fixes with identical semantics:
Test file — read the whole thing against the working tree (not just the per-commit patches). The span-classifier ( Lite/Darling parity: the guard lives only in No correctness, security, or performance issues found. Nothing here touches missing-index DMVs. This is a well-scoped, unusually heavily self-tested change (68 mutation runs cited); I have no findings beyond what the PR description already documents as known limitations (e.g., the abbreviation half of the Data types rule, the 500-literal marker residue). |
* Rewrite the abbreviated `int` data types to `integer` and bring the rule in scope CONTRIBUTING.md's Data types bullet states two properties. #3085 enforced the case half and left the abbreviation half uncovered on a remediation cost, with the cost derived and pinned rather than written down. The 33 sites across 7 files are rewritten, so UnabbreviatedTypes moves to the Data types bullet's Covered side, Findings emits it, it gains hazard fixtures and the near-miss benign fixtures that hold its two anchors, and the cost pin goes with the cost. Data types stops being a split bullet, so the split-pair assertion names only Indentation. Lite.Tests' memory-collector parity pin asserts the Azure variant's `CONVERT(int, NULL)` verbatim and moves with the query it pins. * Assert the abbreviation ratchet at its bullet, in both directions The set equalities in TheDispositionMap_PartitionsTheBulletsContributingStates are over the flattened union of every bullet's Covered and Uncovered arrays, so they cannot see which bullet a rule sits under: UnabbreviatedTypes could move to the Functions bullet and all of them would still hold, while the map claimed this guard enforces a sentence CONTRIBUTING.md does not have it enforcing. Naming both sides at the Data types bullet closes that, and it is also what stops the rule drifting back to Uncovered while Findings still emits it. * Keep only the ratchet assertion that can fail Two DoesNotContain lines guarding the Uncovered direction sat after the flattened set equalities and the disjointness assertion, and every state that would trip them trips one of those first - so neither could ever be the assertion that reds. They read as load-bearing while nothing held them. The bullet-level Covered membership stays, because reparenting the rule to another bullet is the one drift the unions cannot see, and the comment now names what holds the other direction so the decorative form does not come back. * Drop a wrong numeral from a fixture comment A hazard fixture's comment said nine of the corpus's spellings sat in DDL type positions. Seven did, and nothing held the figure now that the derived cost pin is gone - so the comment states the shape instead: a temp table's and a table variable's column types were both among them, which is what a check anchored only on CONVERT( would have missed.
CONTRIBUTING.md's T-SQL Style list opens "All T-SQL code must follow" and nothing enforced any of it.TsqlConventionGuardTestsenforces four of the nine bullets, records the other five and the uncovered half of a sixth, and the nine pre-existing violations of the covered subset are fixed here so it lands with no waiver list.Which rules are covered, and which are not
RuleBulletscarries one entry per bullet with an explicit disposition, andTheDispositionMap_PartitionsTheBulletsContributingStatescompares its keys against the bullets parsed out ofCONTRIBUTING.mdfor equality — a tenth bullet, or a renamed one, reds and forces a scope decision instead of being silently unguarded. Each entry also names the wording its checks were derived from, asserted still present, so the document cannot be edited to say the opposite of what the detector enforces. The two bullets that are split rather than all-or-nothing are named in that map's own summary, and a set-equality assertion holds the naming, so a third split bullet reds instead of leaving the prose quietly incomplete.:355)COUNT(→COUNT_BIG(),@@ROWCOUNT→ROWCOUNT_BIG():354)--line comments:350)CASEarms and the two-spaceONrule all indent by amounts the bullet does not enumerate, so a depth check needs the layout rules rather than the character:348)intwhereintegeris meant stands at 33 sites in 7 files, all inside T-SQL that runs against monitored production servers, two of themsp_executesqlparameter declarations that nothing in this repository executes. Rewriting live query strings belongs in a change whose subject is that rewrite:347):349)nvarchar(128)is right for a wait type and wrong for a database name:351)FROMlist ends:352):353)Every uncovered rule has a fixture in
TheUncoveredRules_AreViolatedByFixturesThisGuardDoesNotFlag— a statement that genuinely violates it, asserted to be inside the population so its empty answer records something, with the expected finding set empty and a positive control spliced through the same detector so a deadFindingsfails the control rather than satisfying the emptiness. The fixture set's rule coverage is compared to the map's uncovered side at set equality.The abbreviation half is the one exception to "recorded and left alone": its detector lives beside the enforced ones, reads the same population and the same code view, and
TheAbbreviationScopeNote_CountsTheSitesItClaimscompares its count to the figure the scope note states. A cost written down once goes stale by exactly the mechanism this guard exists to stop, and the direction that matters is downward — when those sites are fixed, the pin says to move the rule to the covered side rather than leaving an unguarded rule behind an expired reason.The population, and what it is not
A string literal is judged when, with its own SQL comments blanked, it begins with a T-SQL statement keyword and carries a token only T-SQL has. Both halves earn their keep, measured:
ScheduleManager's collector descriptions namesys.dm_*twenty-three times; the two MCP instruction blobs are 40 kB and 57 kB of markdown about SQL Server.COUNT_BIG()does not exist and--is idiomatic.DarlingServerConnectoris the clean demonstration: it carries the same-- #2228comment twice, once in a T-SQL probe (fixed here) and once in a PostgreSQL probe (left alone, correctly).IF.Scanned: the seven shared
PerformanceMonitor.*libraries, all ofDarling/, all ofLite/. Measured on this branch: 1,038 files, 35,001 string literals, 140 T-SQL statements across 67 files.Stated bounds, each with a live instance rather than left implied:
FactRemediationrenders a remediation script onesb.Appendper line, soDECLARE @plan_handle varbinary(64);is in and the-- STEP 2line above it is not — a literal that is only a comment opens no statement..sql. Measured: the retired Full edition'sinstall/carries 6COUNT(), 6--comments and 75 uppercase data types;upgrades/carries 3@@ROWCOUNT; the rigs and CI scripts undertools/and.github/sql/carry 9COUNT()and 101--comments. Bringing them in means ~200 waivers or a remediation of a retired SKU's code, and a guard whose waiver list dwarfs its findings has stopped being one.BuildQuery(context).Text, so a violation cannot exist in the copy without existing in the shipped query — and this file's own fixtures deliberately carry every banned shape.The claim that was wrong, and what testing it found
The first draft of this said "every read of a monitored SQL Server goes through a DMV, a catalog view or a built-in, so nothing T-SQL falls outside the population." That is a universal quantifier, and a universal quantifier names the one counter-example that would break it while a count only tells you to count again. So it was tested rather than stated: enumerate the population's complement — literals that open a statement and carry no marker — and read the members.
The complement is 500-odd literals, most of them prose that happens to start with a keyword and store SQL for the other two dialects. What separates T-SQL from both is the parameter spelling:
@nameis T-SQL's,$1is Npgsql's. Filtering on that gives a set small enough to read, and reading it found two things a tally never could:DarlingXeSessions' Extended Events provisioning DDL was entirely outside the population.CREATE EVENT SESSION [...] ON SERVER ADD EVENT sqlserver.xml_deadlock_report ADD TARGET package0.ring_buffer (...), and itsALTER/DROPsiblings, are real T-SQL sent to production servers on every session repair, and carried no marker at all.TsqlMarkersnow reachesEVENT SESSION, and two of those statements are population fixtures. They carry no violation of the covered rules — but they were unjudged, which is this guard's whole failure direction.FactRemediation's cursor fetch, twice —FETCH NEXT FROM plan_cursor INTO @plan_handle;, the one line of that rendered script with no DMV, no catalog view and no built-in in it.TheTsqlTheMarkerSetCannotSee_IsTheseAndNoOthersholds the remainder at set equality over the complement, with the complement itself floored, so a third cannot arrive unnoticed. Injecting aUPDATE STATISTICS … WITH FULLSCANline into that script reds it by name.sqlserver.andpackage0.went in besideEVENT SESSIONand were then removed: measured, every statement carrying either also carriesEVENT SESSION, so no fixture could show them mattering and a mutation deleting them stayed green. A marker nothing depends on is a claim nothing holds.Pre-existing violations: nine, all fixed, no waiver list
DatabaseSizeStatsCollector×2SELECT COUNT(*) FROM sys.dm_db_log_info(…)CONVERT(integer, COUNT_BIG(*))— theStallWaitProbepattern, keeping the expression's type identical for anintegerdestinationLocalDataService.FinOps.RecommendationsN'SELECT @c = COUNT(*) FROM sys.availability_groups…'CONVERT(integer, COUNT_BIG(*))DarlingServerConnector-- #2228: …in the T-SQL probe/* … */; the PostgreSQL probe's identical comment is untouchedQueryStoreCollector@sql NVARCHAR(500)nvarchar(500)FactRemediationDECLARE @plan_handle VARBINARY(64);varbinary(64)LocalDataService.FinOps.RecommendationsAS NVARCHAR(128),AS INTnvarchar(128),integerDatabaseSizeStatsCollector,LocalDataService.FinOps.ServerPropertiesnvarchar(MAX)nvarchar(max)None of these sites is verbatim-pinned by a parity test, checked before editing. The covered subset then measures zero, so there is no waiver mechanism at all — a waiver mechanism nobody needs is a mechanism the next exception takes for granted.
Population floors
Derived rather than counted, since a count floor goes stale by the same mechanism:
files scanned > 0,literals extracted > 0andstatements read > 0, each a separate assertion fromviolations == 0.Darling/andLite/must contribute at least one T-SQL statement, and the tree loop must have run for every tree. A union floored only in total passes while one tree is dark.StallWaitProbe.cs(where Fixes #2880 #3078's violation landed) and the two non-shared files this change fixed. A glob reaching part of a tree, or a marker set going blind on one file's shape, now fails by name.CollectorCatalog, which is the authority on engine (TargetEnginedefaults toSqlServer;PostgresCollectorDefinitionBaseseals it toPostgreSql). Every SQL Server definition's source must contribute a T-SQL statement; no PostgreSQL definition's may — while still being required to contain a statement the walk could see, which is the load-bearing half of the negative. Guessing from filenames would be wrong:PgPlanFetcheris named for the Postgres store and its SQL is T-SQL, fetched from a monitored SQL Server. The one definition carrying no SQL at all (pg_cpu_utilization, ingested from Performance Insights) is named at set equality and its entry is corroborated against the source's own wording.Both SKUs
The scan reads the shared libraries and both app trees — #3078's violation landed in
PerformanceMonitor.Collectors, which both products build on, and Lite'sRemoteCollectorServiceandLocalDataService.FinOps.*send T-SQL of their own. Each tree is floored separately and spelled identically, because an arm written as a special case is how the next tree inherits the sibling bug #3067 was filed for.One class rather than two: the
darlingfilter reachesLite/**/*.csandcorereaches every shared library, so the "Run Darling tests" step fires on a change to any tree this reads, anddarling-tree-guardsruns the whole suite on the arm where it did not.What holds that reachability, stated precisely.
CrossAppGuardCiGateTestsrequires every cross-app read to be filter-reachable, andCONTRIBUTING.md's Writing a Test That Reads the Other SKU's Source — added by #3084, merged intodevwhile this was open — names the three spellings it can see. A bare root iterated out of astring[]field is not one of them; it is the "segment array declared in another member" case that section calls silent by construction, and the bare"Lite"inScannedTreesis exactly it. Verified: before the anchors existed, pointing a root atLite.Testschanged nothing in that guard. The anchors are repo-rooted path literals at the site that reads them, which is the first of the three, soLite/Services/LocalDataService.FinOps.Recommendations.csis now in its found set; with them in place the same injection reds by name — re-run against #3084's rewritten matcher after mergingdevin. (The injected path has to exist on disk: that guard drops unresolvable references, and the first attempt at this red-proof used a filename that was not there and proved nothing.)Red-proof evidence
68 mutation runs, applied to a committed tree, each built (build success asserted separately from running, so a stale dll cannot print a clean result), run, restored with an absolute pathspec, and the restore verified by
git diff --exit-code HEADon that path plus a token check — with the baseline run last, reportingFailed: 0, Not Run: 0every time. 59 killed on the run. The count is derived by enumerating the mutation specs, not added up.One never applied (a bad anchor; re-specified and killed). Of the eight survivals:
sqlserver./package0., deleted rather than given a fixture it could not have;offenders.Count >= 0twice,anchorStatements >= 0once). No other test catches that by construction — it is deletion of the pin, not a defect in it, and the evidence that matters for those is the eight product-file and anchor-file mutations below, which exercise the whole path from a file on disk to a named offender with the assertions intact.Against the real tree, all naming
NoTsqlStatementViolatesACoveredConvention:COUNT(*)inDatabaseSizeStatsCollector[COUNT_BIG-not-COUNT]at the site--inDarlingServerConnector[block-comments-not-double-dash]NVARCHAR(500)/nvarchar(MAX)[data-types-lowercase]@@ROWCOUNTintoLatchStatsCollector[ROWCOUNT_BIG-not-@@ROWCOUNT]LatchStatsCollector[spaces-not-tabs]SourceFilesyields nothingfiles scanned > 0IsTsqlStatementalways falseDarling.Tests, so this file's own fixtures are scannedAgainst the residue pin and the walk: dropping
EVENT SESSION(the XE fixtures go unrecognised), inverting the named-parameter tell, injecting a third unmarked T-SQL statement intoFactRemediation, marking its fetch so it leaves the residue, and dropping the]]escape arm from the quoted-identifier walk — the last of these was a finding from the review of this PR, and[a]]INT]is the fixture that holds it.Against the detector and the discriminator, each killing the fixture that names it: neutering the
@@ROWCOUNTcheck, neutering the tab check, letting the tab check see string values, reverting the XQuery-argument window, de-nesting block comments, mis-handling the''escape, addingtableto the type vocabulary, dropping theFOR XML/AT TIME ZONEcollision blanking, keeping quoted identifiers, unanchoring the(max)length spec, removing theCOUNT(lookbehind, making the case check case-blind, emptyingFindings, replacing the span-kind--test with a bare text search, anchoring the statement opener at any line start, dropping either half of the population test, and reading markers without blanking comments.Against the document and the map: renaming a bullet heading, removing a bullet, rewriting a required phrase, adding a covered rule id with no bullet, moving the abbreviation rule to the covered side without a check, splitting a third bullet while keeping both rule-id unions identical (which only the split-pair assertion can see), narrowing the marker set until collectors go blind (which names them), widening it into PostgreSQL vocabulary (which names
PgBlockingCollector), falsifying either field of the no-SQL entry, bumping either figure in the scope note, making that figure unparseable, neutering the abbreviation detector, and fixing oneintsite without moving the rule.Three mutations that survived, and what came of each:
--before the inner close, where a nesting and a non-nesting walk both read it as comment — it recorded nothing. Moved after the inner close; re-killed.(max)length spec changed no answer, because no fixture had(MAX)after a non-type identifier.MAX(MAX)— legal T-SQL, sinceMAXis not reserved — is textuallyIDENT ( max ); re-killed.COUNT(lookbehind changed no answer:COUNT_BIG(andROWCOUNT_BIG()are rescued by the underscore that followsCOUNT, and@@ROWCOUNTis never followed by(. The lookbehind's whole job is an identifier ending inCountthat is then called;dbo.RowCount(…)is that shape; re-killed.A fourth, found by mutating the document rather than by reading the list: the Functions bullet asked for the phrase
COUNT_BIG(), and rewriting the document'sCOUNT_BIG()toCOUNTBIG()stayed green, becauseROWCOUNT_BIG()two words later still containsCOUNT_BIG()as a substring. The phrases now carry their backticks, andEveryRequiredPhrase_IsLoadBearingOnItsOwndeletes each one from the real bullet text in turn and requires the check to red.Two further red-proofs confirm the harnesses read the edited file rather than a stale copy: adding a line-prefix comment filter makes
CommentFilterAdoptionTestsnameTsqlConventionGuardTests.cs, and pointing the Lite anchor at a realLite.Testspath makesCrossAppGuardCiGateTestsname it.What was verified locally, and what was not
No query in this diff was executed against a SQL Server, of any version, anywhere. Nine hand-edits to T-SQL that runs against monitored production instances, and the verification for all nine is inspection: mine, and the review bot's independently. Four are keyword case, which T-SQL is insensitive to; one turns a
--comment into a/* */comment; three wrapCOUNT_BIGinCONVERT(integer, …)so the expression's type is unchanged at anintegerdestination; one changesAS INTtoAS integerin aCAST. That is the right level of confidence for changes of this shape, but it is inspection and not execution, and nothing below should be read as covering it — the test suites exercise the guard, not the queries.Darling.TestsandLite.Testsarenet10.0-windowsand cannot run on macOS. The eight tests here,CrossAppGuardCiGateTests(12), andCommentFilterAdoptionTests+DocCommentHygieneTests+FleetIdentifierScrubTests(46) were compiled from the actual.csfiles into throwawaynet10.0xunit v3 harnesses staged in the gitignored projectbin/and run —Failed: 0, Not Run: 0on all three, re-run after mergingdevin so the 12 are #3084's rewritten matcher rather than the one this branch started from. Both test projects and the four edited product projects compile with-p:EnableWindowsTargeting=true.CI on
b098a76c4: 8/8 green.build8m28s ranDarling.Tests(Total: 7814, Failed: 0, Not Run: 0) andLite.Tests(Total: 3429, Failed: 0, Not Run: 0);Darling PostgreSQL tests4m12s ran the Darling suite against a live store (Failed: 0, Skipped: 6, Not Run: 0).TsqlConventionGuardTestsappears in neither the FAIL nor the SKIP list in either job, andNot Run: 0means nothing was discovered-but-unrun — so the tests here executed rather than merely compiled. The suite totals are not read as a delta:devmoved during this PR (#3084 merged and is merged in).Windows CI and the nightly are the arbiters for the suites; neither runs a query from this diff against a SQL Server, per the note that opens this section.