Commit 2c3a8af
committed
Locking phase 0 — schema-stability locks (Sch-S / Sch-M) on every schema-bound object, plus the per-connection plumbing (SPID /
@@LOCK_TIMEOUT / currently-executing-thread) the data-lock phases will build on. New LockResource primitive (one per SchemaObject via the inherited SchemaLock field) provides reader/writer locking with re-entrant per-owner counting, Monitor.Wait-based cross-thread blocking, and same-thread-deadlock detection: when a conflicting holder's CurrentExecutingThreadId matches the caller's managed thread, the wait short-circuits to Msg 1205 since the holder can't release until the caller does. Cross-thread waiter-graph cycle detection isn't part of phase 0 — Sch-S / Sch-M's per-statement scope means cycles can't form here; they emerge with data X locks held across transactions (phase 1a). Errors/SimulatedSqlException.ConcurrencyErrors.cs ships verbatim-from-probe Msg 1222 (Lock request time out period exceeded.) at Class 16 State 56 (schema-lock path) and Msg 1205 (Transaction (Process ID <N>) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.) at Class 13 State 45 with the victim's SPID embedded. SimulatedDbConnection gains Spid (allocated via Simulation.AllocateSpid(), first user = 51 per SQL Server convention), LockTimeoutMillis (default -1 / wait forever — probe-confirmed against SQL Server 2025), and CurrentExecutingThreadId (set/cleared in DispatchOneStatement's try/finally with save+restore for nested proc / trigger / UDF / MS-TVF body dispatches). BatchContext.StatementSchemaLocks is the per-statement list of (LockResource, LockMode) tuples; AcquireStatementLock appends, ReleaseStatementSchemaLocks walks in reverse and the dispatcher fires it in a finally so locks unwind on success / error / TRY-caught alike. Sch-S acquired by every successful BatchContext.TryResolve* path (table / view / function / procedure / table-type / sequence); temp tables / table variables / trigger INSERTED / DELETED pseudo-tables bypass (per-session or per-batch, no cross-connection contention). Sch-M acquired by every DDL site: DropOne{Table,View,Function,Procedure,Type,Sequence,Trigger} between TryGetValue and TryRemove, TRUNCATE TABLE after the lookup, and TryParseAlterTable once at dispatcher entry so every sub-parser (ADD / DROP / ALTER COLUMN / ADD CONSTRAINT / DROP CONSTRAINT / CHECK / NOCHECK / SET SYSTEM_VERSIONING) runs under exclusive schema modification (the sub-parsers' own TryResolveTable adds re-entrant Sch-S holds, harmless under same-owner Sch-M reentry). SET LOCK_TIMEOUT N promoted from parse-and-discard → drives connection.LockTimeoutMillis; the negative-literal form (SET LOCK_TIMEOUT -1) still falls through Msg 102 since the tokenizer splits - from 1 and the simulator's SET path uses a single-token check rather than Expression.Parse — the default is already -1 so this rarely matters in practice. 13 new internal LockResourceTests cover the primitive directly (acquire / release / re-entrance, Sch-S × Sch-S compatible, Sch-M-blocks-everything, timeout zero / positive / cross-thread grant-after-release, same-thread immediate Msg 1205, SPID allocation, SET LOCK_TIMEOUT propagation) plus 5 user-facing LockingTests (single-connection SET acceptance for positive / zero, two-connection sequential DDL/DML, two-thread concurrent inserts into separate tables, two-thread DROP race on the same table — exactly-one Msg 3701). New docs/claude/locking.md covers acquisition sites, same-thread-deadlock model, and the phase-0 gaps list (data locks / hint behavior / isolation levels / MVCC are phases 1a–3; ALTER PROCEDURE / TRIGGER / SEQUENCE / SCHEMA TRANSFER Sch-M wiring deferred; Heap.Insert thread-safety relies on phase 1a's S/X serialization; @@LOCK_TIMEOUT scalar not yet wired). CLAUDE.md "Not modeled" rewritten to scope the locking gap to phases 1a+, session-state listing on SimulatedDbConnection expanded with the three new fields, Feature reference gains the locking.md trigger.1 parent 68a0535 commit 2c3a8af
14 files changed
Lines changed: 1052 additions & 29 deletions
File tree
- SqlServerSimulator.Tests.Internal
- SqlServerSimulator.Tests
- SqlServerSimulator
- Errors
- Parser
- Simulation
- docs/claude
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
62 | 62 | | |
63 | 63 | | |
64 | 64 | | |
65 | | - | |
| 65 | + | |
66 | 66 | | |
67 | 67 | | |
68 | 68 | | |
| |||
114 | 114 | | |
115 | 115 | | |
116 | 116 | | |
117 | | - | |
| 117 | + | |
118 | 118 | | |
119 | 119 | | |
120 | 120 | | |
| |||
154 | 154 | | |
155 | 155 | | |
156 | 156 | | |
| 157 | + | |
157 | 158 | | |
158 | 159 | | |
159 | 160 | | |
160 | 161 | | |
161 | | - | |
| 162 | + | |
162 | 163 | | |
163 | 164 | | |
164 | 165 | | |
| |||
0 commit comments