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
Copy file name to clipboardExpand all lines: CLAUDE.md
+5Lines changed: 5 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -127,6 +127,9 @@ Three entry points share one per-connection undo log: implicit (statement-level
127
127
-`INSERT ... OUTPUT INSERTED.<col>` (single-row).
128
128
-`MERGE INTO target USING <source> ON … WHEN [NOT] MATCHED [BY TARGET|SOURCE] [AND …] THEN UPDATE|DELETE|INSERT … [OUTPUT $action, …]` — source = VALUES / SELECT / set-op / bare-table; multiple per-family AND-conditioned clauses; trailing `;` required. Msg 5324 / 8672 / 10713 / 10714 enforced. Triggers fire one INSERT → UPDATE → DELETE pass with combined affected rows. See [`docs/claude/dml.md`](docs/claude/dml.md).
129
129
130
+
### Cursors
131
+
Session-scoped T-SQL cursors: `DECLARE <name> [INSENSITIVE][SCROLL] CURSOR [LOCAL|GLOBAL][FORWARD_ONLY|SCROLL][STATIC|KEYSET|DYNAMIC|FAST_FORWARD][READ_ONLY|…] FOR <select> [FOR {READ ONLY|UPDATE [OF cols]}]`, `OPEN`, `FETCH NEXT|PRIOR|FIRST|LAST|ABSOLUTE n|RELATIVE n [FROM] <cursor> [INTO @v,…]`, `CLOSE`, `DEALLOCATE`, plus `@@FETCH_STATUS` / `@@CURSOR_ROWS` / `CURSOR_STATUS` and positioned `WHERE CURRENT OF` UPDATE/DELETE. Effective sensitivity resolves at DECLARE: non-updatable query (not a single base table with a PK/UNIQUE) → STATIC; STATIC frozen-snapshot, KEYSET frozen-membership with live value re-reads (deleted member → `@@FETCH_STATUS=-2`), DYNAMIC fully live (skips deletes, sees inserts, `@@CURSOR_ROWS=-1`). Position tracked by the logical unique key (not a RID — UPDATE relocates rows). Errors Msg 16905/16915/16916/16917/16924/16925/16929/16931 probe-confirmed verbatim. Cursor variables (`DECLARE @c CURSOR`) raise `NotSupportedException`. See [`docs/claude/cursors.md`](docs/claude/cursors.md).
132
+
130
133
### EF Core adapter coverage
131
134
`UseSqlServerSimulator(...)` covers seven SqlParameter-downcast pairs: `DateOnly→date`, `DateTime→date`, `DateTime→smalldatetime`, `TimeOnly→time(N)`, `TimeSpan→time(N)`, `decimal→money`, `decimal→smallmoney`. Without the adapter those mappings throw at SaveChanges. MAX-string family flows through plain `UseSqlServer`.
132
135
@@ -146,6 +149,7 @@ Per-feature deep-dives live under `docs/claude/`. Each entry below is a trigger:
146
149
-**`Selection`, aggregates, window functions, set ops, CASE, OFFSET/FETCH** → [`query.md`](docs/claude/query.md).
@@ -225,3 +229,4 @@ Per-feature deep-dives live under `docs/claude/`. Each entry below is a trigger:
225
229
-**`STRING_SPLIT(..., ..., cast(@v as int))` — wrapped variable accepted**: the simulator's `enable_ordinal` const-only gate rejects bare `@v` (Msg 8748, matching real) but a Cast / Parenthesized wrapper around the variable slips past the gate. Real SQL Server rejects all variable-bearing shapes regardless of wrapping. No real-world emission hits this — the const-only restriction means `@v` ergonomics are weak in any form.
226
230
-**`OPENJSON``WITH ... AS JSON`** on `nvarchar(max)` raises `NotSupportedException` even though real SQL Server accepts the column form there (sub-tree extraction not modeled). Non-`nvarchar(max)` columns with `AS JSON` raise **Msg 13618**, matching real.
227
231
-**`FOR SYSTEM_TIME` qualified-name format**: real SQL Server pads temp-table names in Msg 13544 with their internal allocation suffix (`#x____...___…000000000148`); the simulator emits the bare `tempdb.dbo.#x` form. Same Msg number / framing, less verbose name.
232
+
-**Cursor edges**: cursors over a **JOIN / derived table / view** are forced to STATIC (read-only snapshot, `@@CURSOR_ROWS`=count); real SQL Server makes them DYNAMIC (`@@CURSOR_ROWS`=-1, sees mid-loop changes, `WHERE CURRENT OF` works) — the simulator only takes the updatable KEYSET/DYNAMIC path for a *direct single base table with a PK/UNIQUE* (set-op/UNION cursors are forced STATIC on the real server too, so those match). `@@CURSOR_ROWS` is `-1` throughout for DYNAMIC (real may report a transient positive count pre-fetch); a keyset `-2` (deleted-member) fetch leaves the `INTO` variables unchanged rather than zeroing/NULLing them; `FETCH` without `INTO` omits the trailing `ROWSTAT` column. See [`docs/claude/cursors.md`](docs/claude/cursors.md).
0 commit comments