Commit 6ac3196
committed
BACPAC loader — SqlExtendedProperty host-routing for SqlIndexBase + SqlConstraint. WWI's last large remaining structural gap: 81 of 414 extended properties (76 hosted on
**Simulator surface — `ResolveExtendedPropertyTarget`** (`SqlServerSimulator/Simulation/Simulation.ExtendedProperties.cs`). The level2 dispatch was hard-coded to COLUMN-only; now switches across CONSTRAINT / INDEX / COLUMN with Msg 15600 fall-through on anything else. CONSTRAINT-level2 walks `HeapTable.KeyConstraints` (PK + UQ), `CheckConstraints`, `OutgoingForeignKeys`, and `Columns[].DefaultConstraint`, returning a class=1 (OBJECT_OR_COLUMN) key with the constraint's own `ObjectId` as `major_id` and `minor_id=0` — matches real SQL Server, where constraints are first-class objects with their own object_id. INDEX-level2 uses class=7 with `(major_id=table.ObjectId, minor_id=index_id)`; the new `ComputeIndexId` helper mirrors the `sys.indexes` enumeration logic exactly (PK gets `index_id=1`, or HEAP-row 0 if no PK; other key constraints + indexes sequence by ObjectId order). `BuiltInResources.EnumerateSysExtendedProperties` adds the class=7 → `"INDEX"` mapping for the `class_desc` column.
**Loader surface — `EmitExtendedProperty`** (`SqlServerSimulator/Storage/Bacpac/ModelXmlReader.cs`). Two new cases in the host-kind switch:
- `SqlIndexBase` (3-part host `[schema].[table].[index]`) — straightforward translation: `@level0type=SCHEMA, @level1type=TABLE|VIEW, @level2type=INDEX`. Notably WWI's `FK_*`-named indexes (manually created to back FK columns) flow through this path — they're real `SqlIndex` elements that DACFx references through the `SqlIndexBase` host kind.
- `SqlConstraint` (2-part host `[schema].[constraint_name]`) — needs the parent table name for `@level1name` but DACFx doesn't include it in the host reference. Added `LookupConstraintParentTable` which queries `sys.objects.parent_object_id` (constraint rows carry this; tables don't) joined with `sys.schemas`, returning the owning table name via `OBJECT_NAME(parent_object_id)`. The lookup runs once per SqlConstraint extended property — fine since WWI has only 5.
**Test additions (8 new)**:
- `SqlServerSimulator.Tests/ExtendedPropertyTests.cs` (+7): CHECK / PK / FK constraint host round-trip; INDEX host round-trip with class=7 + class_desc=INDEX + minor_id=2 assertion; PK index_id=1 case; missing-name error paths for both CONSTRAINT and INDEX raising Msg 15135.
- `SqlServerSimulator.Tests.Internal/Storage/BacpacLoaderTests.cs` (+1): `Load_WWI_Extended_Properties_Cover_Index_And_Constraint_Hosts` exercises the round-trip on representative WWI samples — `Application.Cities.FK_Application_Cities_StateProvinceID` (INDEX host, class=7), `Sales.CK_Sales_Invoices_ReturnedDeliveryData_Must_Be_Valid_JSON` (CONSTRAINT host, class=1), plus an aggregate count check (`>= 410` of WWI's 414 total Description-named properties).
**Test expectation + doc updates**:
- `Load_WWI_Known_Gaps_Recorded_In_Skipped` swaps the SqlExtendedProperty count assertion for an `IsFalse(grouped.ContainsKey("SqlExtendedProperty"))` — all 414 WWI extended properties land. The only remaining category assertion is `AreEqual(1, grouped["SqlDatabaseOptions"])`.
- `docs/claude/bacpac-prerequisites.md` step 10 captures the bundle; the WWI gap inventory in step 13 strikes through the SqlExtendedProperty entry and adds the SqlDatabaseOptions collation entry as the named final gap.
- `CLAUDE.md`'s BACPAC import deep-dive pointer drops the SqlExtendedProperty entry from the WWI Skipped tally.SqlIndexBase, 5 on SqlConstraint) were landing on Skipped because EmitExtendedProperty's host-kind switch only handled SqlColumn / SqlTableBase / SqlSchema / SqlDatabaseOptions. Two-part fix wires CONSTRAINT and INDEX level2 acceptance through the existing sp_addextendedproperty surface; everything now round-trips through sys.extended_properties. WWI Skipped category count drops from 2 to 1; only the non-default-collation SqlDatabaseOptions entry remains (its own multi-area feature project).1 parent f89e164 commit 6ac3196
7 files changed
Lines changed: 350 additions & 17 deletions
File tree
- SqlServerSimulator.Tests.Internal/Storage
- SqlServerSimulator.Tests
- SqlServerSimulator
- Simulation
- 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: 63 additions & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
615 | 615 | | |
616 | 616 | | |
617 | 617 | | |
618 | | - | |
| 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 | + | |
| 692 | + | |
| 693 | + | |
| 694 | + | |
| 695 | + | |
| 696 | + | |
| 697 | + | |
| 698 | + | |
| 699 | + | |
638 | 700 | | |
639 | 701 | | |
640 | 702 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
286 | 286 | | |
287 | 287 | | |
288 | 288 | | |
| 289 | + | |
| 290 | + | |
| 291 | + | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
| 300 | + | |
| 301 | + | |
| 302 | + | |
| 303 | + | |
| 304 | + | |
| 305 | + | |
| 306 | + | |
| 307 | + | |
| 308 | + | |
| 309 | + | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
| 362 | + | |
| 363 | + | |
| 364 | + | |
| 365 | + | |
| 366 | + | |
| 367 | + | |
| 368 | + | |
| 369 | + | |
| 370 | + | |
| 371 | + | |
| 372 | + | |
| 373 | + | |
| 374 | + | |
| 375 | + | |
| 376 | + | |
| 377 | + | |
| 378 | + | |
| 379 | + | |
| 380 | + | |
| 381 | + | |
| 382 | + | |
| 383 | + | |
| 384 | + | |
| 385 | + | |
| 386 | + | |
| 387 | + | |
| 388 | + | |
| 389 | + | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
| 393 | + | |
| 394 | + | |
| 395 | + | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
289 | 404 | | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1161 | 1161 | | |
1162 | 1162 | | |
1163 | 1163 | | |
| 1164 | + | |
1164 | 1165 | | |
1165 | 1166 | | |
1166 | 1167 | | |
| |||
0 commit comments