Commit 8f65789
committed
PRIMARY KEY / UNIQUE on PERSISTED computed columns — lifts the broad
NotSupportedException at Simulation.Create.cs lines 1073 (ParseTableKeyConstraint pending-computed-name scan) and 1129 (ResolveKeyConstraints final validator). PERSISTED computed columns are key-eligible because they carry a real storage ordinal (HeapColumn.IsStored=true via IsPersisted) — the existing EnforceKeyConstraints + EnforceUniqueIndexes loops read them by storage-ordinal lookup like any other stored column, so no change to the enforcement path is needed. ParseTableKeyConstraint's pending-computed branch now sets found = i and breaks instead of throwing — the column's null slot in heapColumns gets filled during the computed-column materialization pass; ResolveKeyConstraints then sees the finished HeapColumn and applies the new gate. Inline form (c AS expr PERSISTED NOT NULL PRIMARY KEY) is supported by extending the computed-column branch in ParseOneColumnIntoLists to consume an optional trailing PRIMARY KEY / UNIQUE keyword after the PERSISTED-[NOT-NULL] suffix and add the constraint to pendingKeys with the column's index. Rejection paths match probe-confirmed real SQL Server 2025 behavior: PK on non-persisted at CREATE TABLE → new Msg 1711 factory ComputedColumnPkRequiresPersisted ("The computed column has to be persisted and not nullable."); PK on non-persisted at ALTER ADD → existing Msg 8111 via the non-persisted-implies-nullable shortcut (probe-confirmed real SQL Server uses the different code at ALTER vs CREATE — both observable through the simulator's existing nullable-check path without special-casing); PK on PERSISTED nullable computed at either CREATE or ALTER → existing Msg 8111 (computed columns default to nullable=true unless explicitly PERSISTED NOT NULL — divergence from real SQL Server which appears to auto-promote-to-NOT-NULL when used as PK, documented as deferred since EF Core always emits explicit nullability and so apps don't reach the path); UNIQUE on non-persisted at CREATE TABLE → NotSupportedException (real SQL Server allows; deferred because enforcement would need per-row expression evaluation in EnforceUniqueIndexes / EnforceKeyConstraints rather than storage-ordinal lookup); same NotSupportedException at ALTER ADD (new guard in Simulation.AlterTableConstraint.cs's ParseAddKeyConstraint covers UNIQUE that the existing Msg 8111 nullable check doesn't catch). Existing obsolete test KeyConstraintTests.PrimaryKey_OnComputedColumn_NotSupported rewritten + 14 new tests cover the full surface: inline + table-level + ALTER ADD shapes across PK / UNIQUE; CREATE-time + ALTER-time + INSERT-time enforcement; compound PK with regular+computed columns; Msg 1711 / Msg 8111 / Msg 2627 / Msg 1505 paths; NotSupportedException for both non-persisted UNIQUE shapes. CLAUDE.md "Not modeled" entry rewritten — the broad "PK/UNIQUE on computed column" bullet now scoped down to "UNIQUE on a non-persisted computed column", explaining the storage-ordinal-vs-expression-evaluation distinction and the orthogonal Msg 4936 (PERSISTED determinism gate) gap that remains unenforced.1 parent 7ae5038 commit 8f65789
5 files changed
Lines changed: 181 additions & 14 deletions
File tree
- SqlServerSimulator.Tests
- SqlServerSimulator
- Errors
- Simulation
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
166 | 166 | | |
167 | 167 | | |
168 | 168 | | |
169 | | - | |
| 169 | + | |
170 | 170 | | |
171 | 171 | | |
172 | 172 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
317 | 317 | | |
318 | 318 | | |
319 | 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 | + | |
320 | 403 | | |
321 | | - | |
| 404 | + | |
322 | 405 | | |
323 | | - | |
324 | | - | |
325 | | - | |
326 | | - | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
327 | 411 | | |
328 | 412 | | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
| 419 | + | |
| 420 | + | |
| 421 | + | |
| 422 | + | |
| 423 | + | |
| 424 | + | |
| 425 | + | |
| 426 | + | |
| 427 | + | |
| 428 | + | |
| 429 | + | |
| 430 | + | |
| 431 | + | |
| 432 | + | |
| 433 | + | |
| 434 | + | |
| 435 | + | |
| 436 | + | |
| 437 | + | |
| 438 | + | |
| 439 | + | |
| 440 | + | |
| 441 | + | |
| 442 | + | |
| 443 | + | |
| 444 | + | |
| 445 | + | |
| 446 | + | |
| 447 | + | |
| 448 | + | |
| 449 | + | |
| 450 | + | |
| 451 | + | |
| 452 | + | |
329 | 453 | | |
330 | 454 | | |
331 | 455 | | |
| |||
Lines changed: 9 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
396 | 396 | | |
397 | 397 | | |
398 | 398 | | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
399 | 408 | | |
400 | 409 | | |
401 | 410 | | |
| |||
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
261 | 261 | | |
262 | 262 | | |
263 | 263 | | |
| 264 | + | |
| 265 | + | |
| 266 | + | |
| 267 | + | |
| 268 | + | |
| 269 | + | |
| 270 | + | |
| 271 | + | |
264 | 272 | | |
265 | 273 | | |
266 | 274 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
545 | 545 | | |
546 | 546 | | |
547 | 547 | | |
548 | | - | |
| 548 | + | |
| 549 | + | |
549 | 550 | | |
550 | 551 | | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
551 | 562 | | |
552 | 563 | | |
553 | 564 | | |
| |||
1070 | 1081 | | |
1071 | 1082 | | |
1072 | 1083 | | |
1073 | | - | |
| 1084 | + | |
| 1085 | + | |
| 1086 | + | |
| 1087 | + | |
| 1088 | + | |
| 1089 | + | |
| 1090 | + | |
| 1091 | + | |
| 1092 | + | |
1074 | 1093 | | |
| 1094 | + | |
| 1095 | + | |
1075 | 1096 | | |
1076 | 1097 | | |
1077 | 1098 | | |
| |||
1097 | 1118 | | |
1098 | 1119 | | |
1099 | 1120 | | |
1100 | | - | |
1101 | | - | |
| 1121 | + | |
| 1122 | + | |
| 1123 | + | |
| 1124 | + | |
| 1125 | + | |
1102 | 1126 | | |
1103 | | - | |
1104 | | - | |
1105 | 1127 | | |
1106 | 1128 | | |
1107 | 1129 | | |
| |||
1125 | 1147 | | |
1126 | 1148 | | |
1127 | 1149 | | |
1128 | | - | |
1129 | | - | |
| 1150 | + | |
| 1151 | + | |
| 1152 | + | |
| 1153 | + | |
| 1154 | + | |
| 1155 | + | |
1130 | 1156 | | |
1131 | 1157 | | |
1132 | 1158 | | |
| |||
0 commit comments