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
geography / geometry data types + spatial indexes — eighth and final bacpac prerequisite bundle, skip-with-diagnostic stance. Spatial columns + geography::Parse(wkt) / geometry::STGeomFromText(wkt, srid) / geometry::Point(x, y, srid) construction + CREATE SPATIAL INDEX (with USING <scheme> / BOUNDING_BOX / GRIDS / CELLS_PER_OBJECT) + sys.spatial_indexes / sys.spatial_index_tessellations / sys.spatial_reference_systems ship. OGC + Microsoft-extension instance methods (.STDistance / .STAsText / .STIntersects / etc.) parse cleanly so CREATE VIEW / CREATE PROCEDURE bodies that reference them store verbatim, then raise NotSupportedException at execute — except .ToString() which returns the stored WKT (the only spatial method whose result is recoverable from the degraded in-memory representation). AW's sole spatial column (Person.Address.SpatialLocation, geography) round-trips end-to-end as a first-class spatial-typed column rather than the originally-recommended varbinary(MAX) degradation. All eight bacpac prerequisites now complete.
**Storage**: new `GeographySqlType` + `GeometrySqlType` singletons in `Storage/SpatialType.cs`, both inheriting `SpatialSqlType : SqlType(SqlTypeCategory.String)`. SystemTypeId=240 (CLR-UDT family, shared with hierarchyid via the new arm in `SqlType.SystemTypeId`), UserTypeId=130 (geography) / 129 (geometry) via new arms in `SqlType.UserTypeId`. IsLob=true (routes column declaration through the off-row LOB chain, matching real-server max_length=-1 reporting). Payload encoding: raw UTF-16 LE of the constructed WKT string — the simulator's degraded-mode form. `SqlValue.FromGeography` / `FromGeometry` factories + the corresponding branches in `SqlValue.FromString`. The pre-existing `BuiltInResources.SystypesRowData` rows 33-34 (geography + geometry) already carried the system_type_id / user_type_id pair; the bundle wired them into `ResolveSimpleKeyword`'s 8-char / 9-char arms so `CREATE TABLE (g geography)` actually accepts them, and added the `SpatialSqlType => (-1, 0, 0)` arm to `GetSysColumnMetadata` so `sys.columns` reports the type identity. The byte form on disk is **not** SQL Server's documented binary CLR-UDT representation — same simulator-specific deferral as `hierarchyid`, to be replaced when the BACPAC loader bundle implements wire-format encoding (the prerequisite doc's order-of-operations item 2 calls this out explicitly).
**Method-call surface** (`Parser/Expressions/SpatialMethodCall.cs`, ~270 lines): broad closed accept-list (~70 names) covering every OGC predicate / accessor / constructor exposed on both geography and geometry, plus the common Microsoft extensions (`Lat` / `Long` / `MakeValid` / `Reduce` / `Filter` / `BufferWithTolerance` / `BufferWithCurves` / `EnvelopeAngle` / `STSrid` / `STNumGeometries` / `STX` / `STY` / `STZ` / `STM` / `HasZ` / `HasM` / `InstanceOf` / etc.). `IsKnownMethodName` is checked at parse in `Expression.cs`'s dotted-name dispatch loop, immediately after the `XmlMethodCall.IsKnownMethodName` check; on a positive match (followed by `(`) the parse dispatches as `SpatialMethodCall` rather than falling through to multipart-Reference. `Run` raises `NotSupportedException` with `"Spatial instance method '.NAME()' is not modeled."` except `.ToString()` which returns the stored WKT as `nvarchar(MAX)`. Static result-type inference applies the right SqlType per method (`.STDistance` / `.STArea` / `.STLength` / `.Lat` / `.Long` → `float`; `.STContains` / `.STIntersects` / `.STIsValid` / `.HasZ` / `.HasM` → `bit`; `.STAsText` / `.STGeometryType` / `.ToString` / `.AsGml` / `.AsTextZM` → `nvarchar(MAX)`; `.STAsBinary` / `.AsBinaryZM` → `varbinary(MAX)`; `.STSrid` / `.STDimension` / `.STNumGeometries` / etc. → `int`; constructor-style methods → same `SpatialSqlType` as the receiver) so projection-schema resolution works at the parser level even though `Run` never succeeds.
**Static-call surface** (`Parser/Expressions/SpatialStaticCall.cs`): `geography::` and `geometry::` type-scope dispatched alongside `hierarchyid::` in `Expression.cs`'s `::` operator handling — the existing single-arm `hierarchyid`-only check generalizes to a 3-way switch over the LHS Reference's leaf name. `Parse(wkt)` / `STGeomFromText(wkt, srid)` accept a single WKT-string argument (the SRID is parsed-and-discarded — the simulator doesn't track per-value SRID). `Point(x, y, srid)` accepts numeric coordinates and synthesizes a `POINT (x y)` WKT. Every other static method raises `NotSupportedException` at `Run`.
**ToString collision resolution**: the `.ToString()` name collides with hierarchyid's `.ToString()` (which dispatches via the existing `HierarchyIdMethodCall` path; both classes' `IsKnownMethodName` claim it). Since the dispatch in `Expression.cs` checks Hierarchy before Spatial, a naive integration would route `geography_col.ToString()` through `HierarchyIdMethodCall.Run`, which would raise Msg 6522 with `"receiver is geography, not hierarchyid"`. Fix: `HierarchyIdMethodCall.Run` now detects a `SpatialSqlType` receiver at runtime and returns the WKT through the spatial path (`SqlValue.FromNVarchar(receiver.AsString)` for non-NULL, `SqlValue.Null(NVarcharSqlType.MaxForm)` for NULL). This avoids touching the dispatch-order in `Expression.cs` — the hierarchyid `.ToString()` tests stay green, the spatial `.ToString()` path now works end-to-end.
**Spatial index parser** (`Simulation/Simulation.Spatial.cs`): `CREATE SPATIAL INDEX name ON table(col) [USING <i>scheme</i>] [WITH (BOUNDING_BOX = (xmin, ymin, xmax, ymax) | GRIDS = (level [, …]) | CELLS_PER_OBJECT = n | <i>any other index option</i>)]`. Cursor on entry is the `SPATIAL` contextual keyword; the parser walks INDEX → name → ON → object → `(col)` → optional USING → optional WITH. Default `tessellation_scheme` when no USING clause is given: `GEOMETRY_AUTO_GRID` (geometry-typed col) / `GEOGRAPHY_AUTO_GRID` (geography-typed col), matching probed real-server behavior. GRIDS level arguments accept either numeric codes (1/2/3) or named levels (LOW / MEDIUM / HIGH) — both forms surface as 1/2/3 in `sys.spatial_index_tessellations.level_*_grid`. Unknown options inside WITH (FILLFACTOR / PAD_INDEX / IGNORE_DUP_KEY / ONLINE / etc.) skip via balanced-paren consumption until the next top-level `,` or `)`. Non-spatial column → `NotSupportedException`; duplicate index name → Msg 2714. New `SpatialIndex` storage class + `SpatialIndexKind` enum on `HeapTable.SpatialIndexes`; new `Spatial` entry in `ContextualKeyword` enum + dispatch arm in `TryParseCreate`.
**Catalog views** in `BuiltInResources.cs`:
- `sys.spatial_indexes` (23-col, probe-confirmed against SQL Server 2025 on 2026-05-15): object_id / name / index_id / type (=4) / type_desc (='SPATIAL') / is_unique (=false) / data_space_id (=1) / ignore_dup_key / is_primary_key / is_unique_constraint / fill_factor / is_padded / is_disabled / is_hypothetical / is_ignored_in_optimization / allow_row_locks (=true) / allow_page_locks (=true) / spatial_index_type (3 for geometry / 4 for geography) / spatial_index_type_desc ('GEOMETRY' / 'GEOGRAPHY') / tessellation_scheme / has_filter / filter_definition / auto_created.
- `sys.spatial_index_tessellations` (16-col, probe-confirmed): object_id / index_id / tessellation_scheme / bounding_box_xmin/ymin/xmax/ymax / level_1_grid + level_1_grid_desc / ... / level_4_grid + level_4_grid_desc / cells_per_object. Unspecified GRIDS levels surface as NULL; level_*_grid_desc translates the 1/2/3 codes to 'LOW' / 'MEDIUM' / 'HIGH'.
- `sys.spatial_reference_systems` (6-col): empty by default (real SQL Server pre-seeds ~390 EPSG/ESRI SRID rows; the simulator surfaces the column shape but skips the WKT-laden seed payload).
23 new tests in `SpatialTypeTests.cs` cover: column round-trip for both geography and geometry; NULL handling; `sys.types` reports user_type_id=130 / 129 for geography / geometry sharing system_type_id=240; `sys.columns` reports spatial type identity + max_length=-1; geography::Parse from nvarchar literal; geometry::Point synthesizes a WKT from coordinates; `.ToString()` returns stored WKT; `.STDistance` / `.STAsText` / `.STIntersects` raise NotSupportedException at execute; CREATE VIEW with spatial method succeeds at CREATE and fails at execute (verifies the late-binding stance); CREATE SPATIAL INDEX populates sys.spatial_indexes (geometry with explicit bounding-box; geography with default GEOGRAPHY_AUTO_GRID); BOUNDING_BOX round-trips through sys.spatial_index_tessellations; GRIDS with LOW / HIGH level names parse to 1 / 3 codes + CELLS_PER_OBJECT; duplicate index name → Msg 2714; sys.spatial_reference_systems empty + column-shape reachable; CAST geography → nvarchar(MAX) round-trip. Total: 4185 main (+23 new) / 227 internal / 328 EFCore / 58 analyzers — all green Debug + Release.
`docs/claude/bacpac-prerequisites.md` flips the geography/geometry checklist item to [x] with the full implementation walkthrough; the order-of-operations sequence absorbs the merged item and marks **all prerequisites complete**, updates the loader-baseline item to reflect that xml / spatial now ship first-class (no longer need varbinary(MAX) degradation at the loader), and updates the Status section to flag the loader-baseline as the next bundle. `CLAUDE.md` adds a new Feature-reference index entry for the spatial surface (`GeographySqlType` / `GeometrySqlType` / `SpatialMethodCall` / `SpatialStaticCall` / `SpatialIndex` / `Simulation.Spatial.cs` / catalog views), rewrites the BACPAC working-document trigger line to drop the no-longer-pending spatial prerequisite + note all eight bundles complete, and rewrites the `Not modeled` `geography` / `geometry` bullet to reflect the shipped surface (skip-with-diagnostic stance with `.ToString()` returning WKT, static constructors working, OGC methods parsing+throwing).
**Deferred** (real feature work after the loader baseline ships): WKT/WKB parsing for validation (any string is currently accepted as a "WKT" payload); OGC method evaluation pipeline (`.STDistance` / `.STIntersects` / `.STArea` / `.STBuffer` / `.STContains` / `.STIntersection` / `.STUnion` / `.STDifference` / etc. — all the geometric predicates and constructors); SRID tracking + transformation; spatial-index query-planner integration (the index parses cleanly but never accelerates anything); the `sys.spatial_reference_systems` seed data (~390 EPSG/ESRI rows); `ALTER SPATIAL INDEX` (REORGANIZE / REBUILD); and the documented byte-identical CAST encoding for cross-engine binary transfer.
Copy file name to clipboardExpand all lines: CLAUDE.md
+3-2Lines changed: 3 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -162,8 +162,9 @@ Per-feature deep-dives live under `docs/claude/`. Each entry below is a trigger:
162
162
-**Touching `GRANT` / `REVOKE` / `DENY` parsing (including `WITH GRANT OPTION`, `REVOKE GRANT OPTION FOR`, `CASCADE`, `ON OBJECT::name` / `SCHEMA::name` / `DATABASE::name` / `TYPE::name`), the principal DDL surface (`CREATE USER`, `CREATE ROLE`, `ALTER ROLE … {ADD | DROP} MEMBER`, `DROP USER`, `DROP ROLE`), the `DatabasePrincipal` / `DatabasePermission` classes + `Database.Principals` / `Database.Permissions` / `Database.RoleMembers`, the pre-seeded fixed principals (public=0 / dbo=1 / guest=2 / INFORMATION_SCHEMA=3 / sys=4), the `sys.database_principals` / `sys.database_permissions` / `sys.database_role_members` catalog views, the Msg 15151 unknown-principal verbatim wording, or the Msg 15023 duplicate-principal-name verbatim wording** → [`docs/claude/bacpac-prerequisites.md`](docs/claude/bacpac-prerequisites.md) (the "Permission statements" section carries the implementation detail).
163
163
-**Touching `CREATE FULLTEXT CATALOG` / `CREATE FULLTEXT INDEX` / `DROP FULLTEXT CATALOG` / `DROP FULLTEXT INDEX`, the `FullTextCatalog` / `FullTextIndex` / `FullTextIndexColumn` storage, `Database.FullTextCatalogs` dict + `AllocateFullTextCatalogId`, the per-table `HeapTable.FullTextIndex` slot, the `Simulation.FullText.cs` partial, the `Fulltext` contextual keyword routing in CREATE/DROP, the `sys.fulltext_catalogs` / `sys.fulltext_indexes` / `sys.fulltext_index_columns` catalog views, or the `NotSupportedException` rejection for CONTAINS / FREETEXT / CONTAINSTABLE / FREETEXTTABLE / SEMANTIC* in `BooleanExpression.ParseAtom` + `Selection.ParseSingleFromSource`** → [`docs/claude/bacpac-prerequisites.md`](docs/claude/bacpac-prerequisites.md) (the "Full-text catalog + index" section carries the implementation detail).
164
164
- **Touching `XmlSqlType` (singleton in `Storage/XmlType.cs`, SystemTypeId=241, IsLob=true), `XmlSchemaCollection` storage class + `Schema.XmlSchemaCollections` dict + `Database.AllocateXmlCollectionId` (seeds at 65536 per probe), `HeapColumn.XmlSchemaCollection` per-column binding, the `xml`-recognizing arms of `SqlType.ResolveSimpleKeyword` / `Precedence` / `SystemTypeId`, the `xml(name)` / `xml(CONTENT name)` / `xml(DOCUMENT name)` column-type parsing in `ParseOneColumnIntoLists` (via `PeekIsXmlSchemaArgument` / `ParseXmlSchemaCollectionArgument`), `Simulation.Xml.cs` partial (CREATE XML SCHEMA COLLECTION / DROP XML SCHEMA COLLECTION / CREATE [PRIMARY] XML INDEX / FOR PATH|VALUE|PROPERTY secondary form), the `Xml` contextual keyword + `Keyword.Primary` dispatch in `TryParseCreate`, `XmlIndex` / `XmlSecondaryIndexType` storage on `HeapTable.XmlIndexes`, the `XmlMethodCall` expression in `Parser/Expressions/XmlMethodCall.cs` (closed accept-list of `value` / `nodes` / `query` / `exist` / `modify`, parses cleanly, throws `NotSupportedException` at `Run`), or the `sys.xml_schema_collections` / `sys.xml_indexes` catalog views** → [`docs/claude/bacpac-prerequisites.md`](docs/claude/bacpac-prerequisites.md) (the "`xml` data type + XML schema collections + XML methods + XML indexes" section carries the implementation detail).
165
+
- **Touching `GeographySqlType` / `GeometrySqlType` (singletons in `Storage/SpatialType.cs`, both inherit `SpatialSqlType : SqlType(SqlTypeCategory.String)`, SystemTypeId=240, UserTypeId=130/129, IsLob=true), `SqlValue.FromGeography` / `FromGeometry` factories + the spatial branches in `FromString`, the `geography` / `geometry`-recognizing arms of `SqlType.ResolveSimpleKeyword` / `Precedence` / `SystemTypeId` / `UserTypeId`, the `SpatialMethodCall` expression in `Parser/Expressions/SpatialMethodCall.cs` (broad ~70-name accept-list of OGC + Microsoft-extension methods; parses cleanly + throws `NotSupportedException` at `Run` except `.ToString()` returns the stored WKT), the `SpatialStaticCall` expression in `Parser/Expressions/SpatialStaticCall.cs` (`geography::Parse(wkt)` / `geography::STGeomFromText(wkt, srid)` / `geometry::Point(x, y, srid)` work; other static methods throw), the `::` dispatch for `geography`/`geometry` in `Expression.cs` alongside `hierarchyid::`, the `.ToString()` polymorphic delegation in `HierarchyIdMethodCall.Run` (spatial receivers return WKT through the spatial path), the `SpatialIndex` storage class + `SpatialIndexKind` enum on `HeapTable.SpatialIndexes`, the `Simulation.Spatial.cs` partial (CREATE SPATIAL INDEX with USING / BOUNDING_BOX / GRIDS / CELLS_PER_OBJECT parsing + default tessellation_scheme), the `Spatial` contextual keyword routing in `TryParseCreate`, or the `sys.spatial_indexes` (23-col probe-confirmed) / `sys.spatial_index_tessellations` (16-col probe-confirmed) / `sys.spatial_reference_systems` (6-col, empty seed) catalog views** → [`docs/claude/bacpac-prerequisites.md`](docs/claude/bacpac-prerequisites.md) (the "`geography` / `geometry` data types" section carries the implementation detail).
165
166
-**Adding a new top-level statement parser or changing the dispatch loop's statement-separator rules** → [`docs/claude/grammar.md`](docs/claude/grammar.md) + [`docs/claude/control-flow.md`](docs/claude/control-flow.md).
166
-
- **Working on BACPAC import support (the eventual `Simulation.FromBacpac` / `FromBacPac` entry point), or knocking off the sole remaining prerequisite feature (`geography`/`geometry` spatial types)** → [`docs/claude/bacpac-prerequisites.md`](docs/claude/bacpac-prerequisites.md). Working document with a feature checklist + the BCP wire-format type matrix; serves as the running scoping doc until the loader baseline lands. Shipped prerequisites: UDDTs / alias types, `sp_addextendedproperty` + `sys.extended_properties`, ALTER DATABASE options accept-list, hierarchyid AW-minimum-viable surface, DDL trigger `ON DATABASE`, GRANT/REVOKE/DENY + CREATE USER/CREATE ROLE/ALTER ROLE/DROP USER/DROP ROLE + `sys.database_principals` / `sys.database_permissions` / `sys.database_role_members`, full-text catalog + index (DDL + `sys.fulltext_*` catalog views ship, CONTAINS / FREETEXT / CONTAINSTABLE / FREETEXTTABLE / SEMANTIC* raise `NotSupportedException`), `xml` data type + xml(schema_collection) bindings + CREATE [PRIMARY] XML INDEX + `sys.xml_schema_collections` / `sys.xml_indexes` (xml-typed columns round-trip raw UTF-16 text identical to nvarchar(MAX) storage; XPath/XQuery methods `.value()` / `.nodes()` / `.query()` / `.exist()` / `.modify()` raise `NotSupportedException` at execute).
167
+
- **Working on BACPAC import support (the eventual `Simulation.FromBacpac` / `FromBacPac` entry point)** → [`docs/claude/bacpac-prerequisites.md`](docs/claude/bacpac-prerequisites.md). Working document with a feature checklist + the BCP wire-format type matrix; serves as the running scoping doc until the loader baseline lands. **All eight prerequisites complete** (shipped 2026-05-14 through 2026-05-15): UDDTs / alias types, `sp_addextendedproperty` + `sys.extended_properties`, ALTER DATABASE options accept-list, hierarchyid AW-minimum-viable surface, DDL trigger `ON DATABASE`, GRANT/REVOKE/DENY + CREATE USER/CREATE ROLE/ALTER ROLE/DROP USER/DROP ROLE + `sys.database_principals` / `sys.database_permissions` / `sys.database_role_members`, full-text catalog + index (DDL + `sys.fulltext_*` catalog views ship, CONTAINS / FREETEXT / CONTAINSTABLE / FREETEXTTABLE / SEMANTIC* raise `NotSupportedException`), `xml` data type + xml(schema_collection) bindings + CREATE [PRIMARY] XML INDEX + `sys.xml_schema_collections` / `sys.xml_indexes`, and `geography` / `geometry` data types + CREATE SPATIAL INDEX + `sys.spatial_indexes` / `sys.spatial_index_tessellations` / `sys.spatial_reference_systems` (spatial columns round-trip the constructed WKT through raw UTF-16 storage; OGC methods `.STDistance` / `.STAsText` / `.STIntersects` / etc. parse cleanly + throw `NotSupportedException` at execute except `.ToString()` returns the stored WKT; static constructors `geography::Parse` / `geography::STGeomFromText` / `geometry::Point` construct values).
167
168
168
169
## Not modeled
169
170
@@ -192,7 +193,7 @@ Per-feature deep-dives live under `docs/claude/`. Each entry below is a trigger:
- **Public `InfoMessage` event** — `SimulatedDbConnection.InfoMessage` ships as an `internal` event (with `internal SimulatedInfoMessageEventArgs` carrying `Message`, `LineNumber`, `Source`) and a `BatchContext`-side buffer that coalesces multiple `PRINT`s per command into one firing (joined with `\n`, line number = first contributing `PRINT`'s line). The internal surface is exercised through `SqlServerSimulator.Tests.Internal/PrintInfoMessageTests.cs`. Going *public* — exposing the event on the `SimulatedDbConnection` consumer surface for application use — is deferred pending the public-API shape decision (mirror SqlClient's `SqlInfoMessageEventArgs` exactly? trim to a minimal shape? add a `DbConnection`-compatible extension method instead of a typed event?). Subquery-in-operand still silently evaluates instead of raising Msg 1046 ("Subqueries are not allowed in this context"); non-string-value formatting routes through `SqlValue.CoerceTo(varchar(8000))` rather than SQL Server's PRINT-specific style 0 conventions (datetime → ISO instead of `"May 14 2026 12:00AM"`; money → `F4` instead of 2-decimal). The 8000-byte ANSI / 4000-character Unicode PRINT truncation isn't enforced — long strings pass through verbatim.
194
195
-**`ALTER TABLE` modeled shapes**: `SET (SYSTEM_VERSIONING = OFF)`, `[WITH CHECK|NOCHECK] ADD CONSTRAINT … (PK | UNIQUE | FK | CHECK | DEFAULT)`, `DROP CONSTRAINT [IF EXISTS] name [, …]`, trust toggling via `(CHECK|NOCHECK) CONSTRAINT (ALL | name)`, `ADD [COLUMN] col TYPE [, …]` (multi-column, inline DEFAULT/IDENTITY/CHECK/FK/computed), `DROP COLUMN [IF EXISTS] col [, …]`, `ALTER COLUMN col TYPE [NULL|NOT NULL]` (single-column, type widening/narrowing, nullability flip). See [`docs/claude/alter-table.md`](docs/claude/alter-table.md). Out of scope: DROP PERIOD FOR SYSTEM_TIME, REBUILD, SWITCH PARTITION, SET-versioning-on, `ALTER COLUMN col ADD/DROP {PERSISTED|MASKED|ROWGUIDCOL|SPARSE}`, identity-column type change to non-integer, multi-constraint ADD (`ADD CONSTRAINT pk1 PK (a), CONSTRAINT fk1 FK …`) — all raise `NotSupportedException`.
195
-
-`geography`, `geometry` — `hierarchyid` ships the AW-minimum-viable surface (Parse / GetRoot / GetLevel / GetAncestor / GetDescendant / IsDescendantOf / ToString / comparison / `ORDER BY`); see [`docs/claude/bacpac-prerequisites.md`](docs/claude/bacpac-prerequisites.md) for the methods + the deferred byte-identical CAST encoding (currently simulator-native, to be replaced when the BACPAC loader bundle starts).
196
+
-`hierarchyid` ships the AW-minimum-viable surface (Parse / GetRoot / GetLevel / GetAncestor / GetDescendant / IsDescendantOf / ToString / comparison / `ORDER BY`); `geography` and `geometry` ship skip-with-diagnostic — WKT round-trip + static constructors + `.ToString()` work, every other OGC/MS-extension method parses cleanly + throws `NotSupportedException` at execute. See [`docs/claude/bacpac-prerequisites.md`](docs/claude/bacpac-prerequisites.md) for the method list + the deferred byte-identical CAST encoding (currently simulator-native for all three, to be replaced when the BACPAC loader bundle starts).
196
197
-**Query hints** — `WITH (hint, …)` on FROM/JOIN-RHS/INSERT/UPDATE/DELETE/MERGE targets and `OPTION (…)` ship; closed accept-lists raise `Msg 321` (unknown table hint) / `Msg 102` (unknown OPTION hint) verbatim; `Msg 1047`/`1065`/`1069`/`307`/`308` enforced; legacy bare-paren form FROM/JOIN-RHS only. `MAXRECURSION N` retains runtime effect; every other recognized hint parse-and-discards. Remaining gaps: FROM-source `(unknown)` without alias falls through to Msg 102 (real SQL Server raises Msg 207/321); `FORCESEEK(name(cols))` nested-form name validation isn't run. See [`docs/claude/query-hints.md`](docs/claude/query-hints.md).
197
198
198
199
## Quirks (modeled, not byte-identical to SQL Server)
0 commit comments