Commit 71ed92f
committed
INSTEAD OF triggers (heap tables + views, all three actions): the existing CREATE TRIGGER … INSTEAD OF parse path (which raised NotSupportedException) wires through to a new dispatch surface that replaces the firing DML's heap-write phase. Trigger model refactored from
HeapTable ParentTable to a polymorphic object Parent (HeapTable or View) with a ParentObjectId accessor for sys.triggers / sys.objects shaping; Schema.Triggers, BuiltInResources's two trigger-emitting catalog passes, DISABLE/ENABLE TRIGGER, and DROP TRIGGER routing all adapted to the new shape. Pseudo-table materialization generalized to take HeapColumn[] directly so view parents use View.OutputColumns for INSERTED / DELETED. New InvokeTrigger surface: TryFireInsteadOfTrigger (single-trigger dispatch returning whether one fired), HasInsteadOfTrigger (presence predicate excluding in-flight triggers via Connection.FiringTriggerIds so a body's nested same-target DML reaches the heap rather than no-op'ing — probe-confirmed), shared RunTriggerBodies helper extracted from FireTriggers so AFTER + INSTEAD OF reuse the body-execution / recursion-guard / SCOPE_IDENTITY-restore plumbing. CREATE TRIGGER now accepts heap-table OR view parents for INSTEAD OF; AFTER on view raises Msg 8197 (probe-confirmed wording); a second INSTEAD OF whose Actions overlap raises Msg 2111 with table / view parent-kind wording (probe-confirmed verbatim). DML hooks (Insert / Update / Delete / Merge) detect per-target / per-action INSTEAD OF and bifurcate: INSERT through view routes to a new ProcessInsteadOfInsertOnView (works for non-updatable views — the primary use case); INSERT through table threads insteadOfActive through ProcessHeapInsert that skips identity allocation (typed-default 0 for int family — probe-confirmed), CHECK / NOT NULL / key validation, heap write, and AFTER-trigger fire; UPDATE / DELETE thread per-target detection through CommitUpdate / CommitDelete with new ProjectThroughView helper that maps base-table rows to view-column shape via BaseColumnOrdinals (derived slots → typed NULL); MERGE per-action routing in CommitMerge (independent per pending list, so mixed INSERT-via-trigger + UPDATE-via-heap MERGEs work; ApplyInsert threaded with insteadOfInsert flag to suppress identity allocation in the pending phase). DROP TABLE / DROP VIEW cascade-drop attached triggers via new CascadeDropTriggers helper. Deferred (raises NotSupportedException, documented): INSTEAD OF UPDATE / DELETE on non-updatable views — requires executing the view selection to enumerate would-be-affected rows, which loses heap-row identity. 21 new InsteadOfTriggerTests cover all three action kinds on tables, INSTEAD OF on updatable + non-updatable views, Msg 2111 enforcement, AFTER-on-view rejection, direct-recursion with body-side nested INSERT reaching the heap, DEFAULT-and-computed-column evaluation for INSERTED, mixed-action MERGE routing, DROP cascade, sys.triggers.is_instead_of_trigger surfacing. CLAUDE.md and docs/claude/triggers.md updated; the prior "INSTEAD OF triggers — NotSupportedException" gap entry replaced with the narrower non-updatable-view UPDATE/DELETE follow-up.1 parent 62f9c08 commit 71ed92f
15 files changed
Lines changed: 1315 additions & 272 deletions
File tree
- SqlServerSimulator.Tests
- SqlServerSimulator
- Errors
- Simulation
- docs/claude
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
175 | 175 | | |
176 | 176 | | |
177 | 177 | | |
178 | | - | |
| 178 | + | |
179 | 179 | | |
180 | 180 | | |
181 | 181 | | |
| |||
0 commit comments