Commit f89e164
committed
BACPAC loader follow-ups — boolean-parser paren-wrapped value LHS + SqlPermissionStatement dispatcher. Two small bundles in one commit; combined, WWI's Skipped category count drops 4 → 2, AW's Skipped category count drops to 1 (collation-only). Both bundles ship permanent direct-SQL test coverage in addition to the bacpac round-trip regression.
**Boolean-parser paren-wrapped value LHS** (`SqlServerSimulator/Parser/BooleanExpression.cs`). The previous `ParseAtom` treated every leading `(` as a boolean group, so `WHERE (a + b) = 5` / `CHECK (((case_sum) = (1)))` / `HAVING (sum(v)) > 25` all surfaced as Msg 4145 syntax errors (probe-confirmed against SQL Server 2025: real SQL Server accepts every one of these). New `LookaheadValueLhs` saves a `ParserContext.SaveCheckpoint`, scans tokens forward tracking paren nesting until the matching `)`, peeks the next token, and restores. When the post-`)` token is a comparison or arithmetic operator (= < > <> != !< !> + - * / % & | ^) or one of LIKE / IS / IN / BETWEEN / NOT, the leading `(` is the start of a value expression on the LHS of a comparison — `ParseAtom` routes through `Expression.Parse` (which handles `Parenthesized` via its own grouped-expression dispatch) and then `ParseComparison`. Otherwise the existing boolean-group path runs. A top-level `,` inside the outer parens disqualifies the value-LHS interpretation (preserves the row-constructor `(a, b) IN (...)` Msg 4145 "near ','" wording from `RowConstructorIn_RejectedWithMatchingMsg4145`). No exceptions for control flow, no side-effects on aggregate / window collectors. Unblocks WWI's `CK_Sales_SpecialDeals_Exactly_One_NOT_NULL_Pricing_Option_Is_Required` (parsed shape `((case_sum) = (1))`). Permanent regression tests: 3 in `CheckConstraintTests.cs` (accept-conforming / reject-two-set / reject-all-null on the WWI CHECK shape) + 8 in `WhereTests.cs` (paren-arith LHS, doubly-paren LHS, BETWEEN with paren LHS, IN with paren LHS, paren-LHS coexisting with outer boolean-group, HAVING with paren-aggregate LHS, CASE-WHEN with paren-LHS, doubly-paren COMPARISON).
**SqlPermissionStatement dispatcher** (`SqlServerSimulator/Storage/Bacpac/ModelXmlReader.cs`). Adds the phase-7 dispatcher slot + `EmitPermissionStatement`. AW + WWI each carried 2 SqlPermissionStatement model elements (`Grant.ViewAnyColumnEncryptionKeyDefinition.Database` / `Grant.ViewAnyColumnMasterKeyDefinition.Database`, both granting to the pre-seeded `public` role) that previously landed on Skipped as "Element type not yet handled by the loader". The new emitter parses the element's `Name`-encoded `[Action.PermissionCamelCase.Scope].[grantee].[grantor]` triple, splits the camel-case permission identifier via the new `CamelToSpaceSeparatedUpper` helper, pulls the grantee from the `Grantee` relationship, and dispatches a `GRANT|REVOKE|DENY <permission> TO <grantee>` statement through the existing GRANT parser (which already accepted the multi-word encryption-key permission keywords — only the loader-side translation was missing). Schema- / object-scope GRANTs would route through the same path with the `SecuredObject` relationship translated to an `ON` clause; deferred until a bacpac exercises that surface. Permanent regression test: `Load_WWI_Encryption_Key_Grants_Land_In_sys_database_permissions` confirms both `VIEW ANY COLUMN ENCRYPTION KEY DEFINITION` and `VIEW ANY COLUMN MASTER KEY DEFINITION` round-trip through `sys.database_permissions`.
**Test-expectation + doc updates**:
- `Load_WWI_Known_Gaps_Recorded_In_Skipped` drops the SqlCheckConstraint and SqlPermissionStatement category assertions; expected counts now: 81 SqlExtendedProperty + 1 SqlDatabaseOptions.
- `Load_AW_Unhandled_Elements_Recorded_In_Skipped` no longer expects SqlPermissionStatement to appear on Skipped (AW's permission grants now land).
- `docs/claude/bacpac-prerequisites.md`: step 8 + step 9 in the order-of-operations checklist capture the two new shipped bundles; the WWI gap inventory (step 12) strikes through both newly-cleared categories; the Status section reflects the new WWI count census (`7/7 CHECK constraints`, `2/2 encryption-key GRANTs` added to the row-by-row tally).
- `CLAUDE.md`: the BACPAC import deep-dive pointer's WWI Skipped tally drops SqlCheckConstraint and SqlPermissionStatement.1 parent d7442e4 commit f89e164
7 files changed
Lines changed: 336 additions & 24 deletions
File tree
- SqlServerSimulator.Tests.Internal/Storage
- SqlServerSimulator.Tests
- SqlServerSimulator
- Parser
- Storage/Bacpac
- docs/claude
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
164 | 164 | | |
165 | 165 | | |
166 | 166 | | |
167 | | - | |
| 167 | + | |
168 | 168 | | |
169 | 169 | | |
170 | 170 | | |
| |||
Lines changed: 60 additions & 6 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
99 | 99 | | |
100 | 100 | | |
101 | 101 | | |
102 | | - | |
103 | | - | |
104 | | - | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
105 | 105 | | |
106 | 106 | | |
107 | 107 | | |
108 | 108 | | |
109 | 109 | | |
110 | | - | |
| 110 | + | |
111 | 111 | | |
112 | 112 | | |
113 | 113 | | |
| |||
613 | 613 | | |
614 | 614 | | |
615 | 615 | | |
| 616 | + | |
| 617 | + | |
616 | 618 | | |
617 | | - | |
618 | | - | |
619 | 619 | | |
620 | 620 | | |
621 | 621 | | |
| |||
635 | 635 | | |
636 | 636 | | |
637 | 637 | | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
| 690 | + | |
| 691 | + | |
638 | 692 | | |
639 | 693 | | |
640 | 694 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
251 | 251 | | |
252 | 252 | | |
253 | 253 | | |
| 254 | + | |
| 255 | + | |
| 256 | + | |
| 257 | + | |
| 258 | + | |
| 259 | + | |
| 260 | + | |
| 261 | + | |
| 262 | + | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
| 272 | + | |
| 273 | + | |
| 274 | + | |
| 275 | + | |
| 276 | + | |
| 277 | + | |
| 278 | + | |
| 279 | + | |
| 280 | + | |
| 281 | + | |
| 282 | + | |
| 283 | + | |
| 284 | + | |
| 285 | + | |
| 286 | + | |
| 287 | + | |
| 288 | + | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
254 | 299 | | |
0 commit comments