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
Fixed some allocation hotspots: resolver local functions passed as their own selfRecursive argument allocated a delegate per column resolution per row (replaced by cached self-referencing lambdas with a mutable-capture tuple slot and one hoisted RuntimeContext per loop) and join probe keys allocated per row (scratch-buffer SqlValueKey, cloned only on build-side first-occurrence insert).
`Selection.cs` + `Selection.Execution.cs` are a partial-class pair. `Parse → Selection`, `Execute → SimulatedSqlResultSet`. Correlated subqueries re-run the same plan per outer row via `outerResolver: Func<MultiPartName, SqlValue>?` (execute) and `outerTypeResolver: Func<MultiPartName, SqlType>?` (parse). Both walk arbitrary nesting depth via `ParserContext.OuterTypeResolver` + the runtime arg. **Derived tables in FROM are always deferred** (`FromSource.LateralPlan` is re-executed per outer row), matching SQL Server's "any FROM derived table can correlate" rule — required because outer references in WHERE/ON resolve through `Run`, not `GetSqlType`.
50
50
51
51
### Multi-source rows
52
-
`FromSource[]`; rows during enumeration are `byte[]?[]`, one slot per source, null = NULL-filled outer-join side (LEFT/RIGHT/FULL/OUTER APPLY). Column resolution is qualifier-aware via `FindSourceColumn` / `ResolveAcrossTuple`; ambiguous unqualified name → Msg 209. Per-row resolution goes through a per-enumeration `SourceColumnMemo` (name → (source, column), keyed by the name's string reference identity — execution-scoped per the plan-cache shared-plan contract); un-memoized re-resolution was the single largest CPU cost of scan-bound joins/aggregates.
52
+
`FromSource[]`; rows during enumeration are `byte[]?[]`, one slot per source, null = NULL-filled outer-join side (LEFT/RIGHT/FULL/OUTER APPLY). Column resolution is qualifier-aware via `FindSourceColumn` / `ResolveAcrossTuple`; ambiguous unqualified name → Msg 209. Per-row resolution goes through a per-enumeration `SourceColumnMemo` (name → (source, column), keyed by the name's string reference identity — execution-scoped per the plan-cache shared-plan contract); un-memoized re-resolution was the single largest CPU cost of scan-bound joins/aggregates.**Per-row resolver loops use the hoisted-scaffolding pattern**: one mutable-capture tuple slot + one cached *self-referencing lambda* (never a local function passed as its own `selfRecursive` argument — that allocates a delegate per column resolution per row, 41% of all bytes in the allocation profile) + one `RuntimeContext` per loop; follow it when adding executor loops.
53
53
54
54
### `MultiPartName`
55
55
Readonly struct, up to 4 inline slots (SQL Server's grammar limit). API: `Leaf`, `ImmediateQualifier` (null when unqualified — pair with `Collation.Baseline.Equals(name.ImmediateQualifier, "INSERTED")`, the equality folds null into `false`), `Count`, `ToString()`. 5th segment → Msg 4104.
0 commit comments