You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Added multi-table-syntax UPDATE / DELETE (UPDATE alias SET ... FROM table AS alias, DELETE FROM alias FROM table AS alias) — the EF7+ ExecuteUpdate / ExecuteDelete emission shape. Single-source-only; joined-source FROM clauses raise NotSupportedException.
Copy file name to clipboardExpand all lines: CLAUDE.md
+4-3Lines changed: 4 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,7 +18,7 @@ Priority is opportunistic: each bundle picks the lowest-effort path that unlocks
18
18
19
19
Standing pattern for non-trivial SQL feature work:
20
20
21
-
1.**Probe.** Behavior questions get answered against a real SQL Server 2025 instance, not from memory or docs. Connection details for the user's reference instance live in user memory under "Real SQL Server reference instance."
21
+
1.**Probe.** Behavior questions get answered against a real SQL Server 2025 instance, not from memory or docs. Connection details for the user's reference instance live in user memory under "Real SQL Server reference instance." Probe scaffolds — both raw SqlClient probes and EF Core emission probes — live in `/tmp/<probe-name>/` console projects and get deleted after the bundle. The git workspace stays free of probe scratch; only graduated regression tests land in `*.Tests` / `*.Tests.EFCore`.
22
22
2.**Surface decisions.** Before writing code, surface 2–3 concrete design choices and recommend one each. The user is decisive at choice points.
23
23
3.**Implement + test.** Tests in `*.Tests` exercise the public API path; `*.Tests.EFCore` validates the oracle. Use `*.Tests.Internal` only for things genuinely unreachable from public SQL.
24
24
4.**Update CLAUDE.md.** Move bullets between "What's modeled" / "Not modeled" / "Quirks" as scope changes.
@@ -188,7 +188,8 @@ Per-type keyword compatibility mirrors SQL Server (verified against Kardax7 2026
188
188
-`PRIMARY KEY` / `UNIQUE`: linear scan (O(N) per insert); no B-tree backing.
189
189
190
190
### UPDATE / DELETE
191
-
-`UPDATE table SET col = expr [, col = expr]* [WHERE pred]` and `DELETE [FROM] table [WHERE pred]`. Single-table only.
191
+
-`UPDATE table SET col = expr [, col = expr]* [WHERE pred]` and `DELETE [FROM] table [WHERE pred]`.
192
+
- Multi-table-syntax form (`UPDATE alias SET alias.col = expr FROM table AS alias [WHERE pred]`, `DELETE FROM alias FROM table AS alias [WHERE pred]`) is the EF7+ `ExecuteUpdate` / `ExecuteDelete` shape. Single-source-only — additional sources or joins on the FROM clause raise `NotSupportedException`. Two-pass parsing: collect raw `(columnName, expr)` pairs without resolving ordinals, then bind to the FROM-clause table once known. SET LHS supports both bare `col = expr` and alias-qualified `[a].[col] = expr`; the alias prefix is accepted verbatim and not cross-checked against the FROM-clause's alias since the simulator's row resolvers use `name.Leaf` (the alias is moot for single-source). OUTPUT is only supported on the single-table form (EF doesn't combine OUTPUT with multi-table-syntax) — see `Simulation.Update.cs` / `Simulation.Delete.cs` for the deferred-table-binding pattern.
192
193
-**Multi-column SET evaluates RHS against the pre-update row snapshot** — verified: `UPDATE t SET a = 100, b = a + 1` over `(a=10, b=20)` produces `(a=100, b=11)` (b read pre-update a). Scalar subquery RHS sees the pre-update table state.
-`OUTPUT INTO @table_var`, `OUTPUT DELETED.*` / `INSERTED.*` star expansion. Per-column `OUTPUT INSERTED.<col>` / `OUTPUT DELETED.<col>`*is* supported (UPDATE / DELETE both); only the star-expansion form is missing. `OUTPUT INTO` (sending the projection to a table variable rather than the result set) isn't.
253
-
-Multi-table UPDATE / DELETE (`UPDATE alias SET ... FROM table AS alias`, `DELETE alias FROM ...`). EF7+ `ExecuteUpdate` / `ExecuteDelete` emit these and won't work without the bundle.
254
+
-Joined-source UPDATE / DELETE FROM clauses (`UPDATE a SET ... FROM t AS a JOIN u AS b ON ...`). The single-source alias form (`UPDATE a SET ... FROM t AS a [WHERE ...]`, `DELETE FROM a FROM t AS a [WHERE ...]`) IS supported — that's what EF7+ `ExecuteUpdate` / `ExecuteDelete` emit, verified against real SQL Server 2025. Adding sources beyond the single aliased target raises `NotSupportedException` so the gap is visible.
254
255
- MERGE source subqueries; MERGE target column refs in `ON`; `WHEN MATCHED` UPDATE/DELETE branches; `$action`. EF Core 9 emits N semicolon-separated `UPDATE … OUTPUT INSERTED.[RowVersion] WHERE [Id] = @p AND [RowVersion] = @p` statements for batched updates (verified 2026-05-07, real SQL Server 2025) — *not* MERGE WHEN MATCHED — so EF SaveChanges fidelity already works without WHEN MATCHED. WHEN MATCHED is still legitimate SQL Server surface (hand-written MERGE, future trigger model) but isn't the EF unlock the older roadmap framed it as. Triggers, when added, will reuse the same INSERTED/DELETED projection model already wired here.
255
256
- Msg 8141 (inline CHECK referencing a peer column — SQL Server rejects at CREATE TABLE; simulator allows).
256
257
- Msg 8133 (CASE where every branch is bare `NULL`; simulator returns NULL of `int`).
0 commit comments