Skip to content

Commit c522b6a

Browse files
committed
Error diagnostics attribution matches real across body types and added the file/filegroup metadata scalars.
1 parent d495b9e commit c522b6a

23 files changed

Lines changed: 774 additions & 55 deletions

CLAUDE.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,12 +235,12 @@ Each entry below is a trigger: read the linked file on demand when working in th
235235
- **`PIVOT` / `UNPIVOT`** — PIVOT desugars to grouped conditional aggregation (implicit grouping = inner columns minus FOR + aggregate-arg), UNPIVOT is a NULL-skipping unfold; both attach as a postfix FROM-source wrapper on the derived-table `LateralPlan` seam → [`pivot.md`](docs/claude/pivot.md).
236236
- **UPDATE / DELETE / INSERT…SELECT / SELECT…INTO / rowversion** (`@@DBTS` / `MIN_ACTIVE_ROWVERSION`) **/ identity helpers** (`@@IDENTITY` / `SCOPE_IDENTITY` / `IDENT_CURRENT`/`_INCR`/`_SEED`) **/ `@@ROWCOUNT` / `ROWCOUNT_BIG` / OUTPUT / MERGE**[`dml.md`](docs/claude/dml.md).
237237
- **Variables, control flow (IF/WHILE/BREAK/CONTINUE/RETURN), TRY/CATCH+THROW+ERROR_*, `@@ERROR` / `@@TRANCOUNT` / `XACT_STATE`, PRINT, WAITFOR**[`control-flow.md`](docs/claude/control-flow.md).
238-
- **Error diagnostics**`SimulatedSqlException` / `SimulatedError` line number (statement-start for runtime/bind, token line for syntax, CREATE-relative for proc bodies), `Server` (= data source), schema-qualified `Procedure`; `ERROR_LINE` / `ERROR_PROCEDURE` parity; TDS ERROR/INFO token server field (`SIMULATED`) → [`errors.md`](docs/claude/errors.md).
238+
- **Error diagnostics**`SimulatedSqlException` / `SimulatedError` line number (statement-start for runtime/bind, token line for syntax, CREATE-relative for proc & trigger bodies, outer-invoking-statement for inlined UDF/TVF/view bodies, opening-quote/end-of-input for unclosed string/comment), `Server` (= data source), `Procedure` (schema-qualified for procs, unqualified for triggers); `ERROR_LINE` / `ERROR_PROCEDURE` parity; TDS ERROR/INFO token server field (`SIMULATED`) → [`errors.md`](docs/claude/errors.md).
239239
- **Cursors** (`DECLARE … CURSOR` / `OPEN` / `FETCH` / `CLOSE` / `DEALLOCATE`, STATIC / KEYSET / DYNAMIC sensitivity, scroll fetches, `@@FETCH_STATUS` / `@@CURSOR_ROWS` / `CURSOR_STATUS`, `WHERE CURRENT OF`; GLOBAL / LOCAL scope + scope-aware resolution, cursor variables (`DECLARE @c CURSOR` / `SET @c = CURSOR …` refcounted, cursor OUTPUT proc params), `FOR UPDATE OF` gating (Msg 16932), SCROLL_LOCKS cursor-scoped U locks + OPTIMISTIC conflict detection (Msg 16947/16934), TYPE_WARNING (Msg 16956)) → [`cursors.md`](docs/claude/cursors.md).
240240
- **CTE shapes / recursive-CTE error handling**[`ctes.md`](docs/claude/ctes.md).
241241
- **JSON** (JSON_VALUE / JSON_QUERY / JSON_MODIFY / JSON_OBJECT / JSON_ARRAY / JSON_OBJECTAGG / JSON_ARRAYAGG / JSON_PATH_EXISTS / ISJSON / OPENJSON) → [`json.md`](docs/claude/json.md).
242242
- **Name resolution, schema lookup, CREATE / DROP / ALTER SCHEMA TRANSFER, `OBJECT_ID`/`_NAME`/`_SCHEMA_NAME` / `SCHEMA_ID`/`_NAME` / `DB_ID`/`_NAME`, cross-DB reads**[`schemas.md`](docs/claude/schemas.md).
243-
- **System metadata surfaces** (sys.* / INFORMATION_SCHEMA.*; `OBJECT_DEFINITION` / `OBJECTPROPERTY(EX)` / `COLUMNPROPERTY` / `INDEXPROPERTY` / `STATS_DATE` / `TYPEPROPERTY` / `SERVERPROPERTY` / `COL_NAME` / `TYPE_NAME` / `PARSENAME`) → [`catalog-views.md`](docs/claude/catalog-views.md).
243+
- **System metadata surfaces** (sys.* / INFORMATION_SCHEMA.*; `OBJECT_DEFINITION` / `OBJECTPROPERTY(EX)` / `COLUMNPROPERTY` / `INDEXPROPERTY` / `STATS_DATE` / `TYPEPROPERTY` / `SERVERPROPERTY` / `COL_NAME` / `TYPE_NAME` / `PARSENAME`; file/filegroup scalars `FILE_ID`/`_IDEX`/`FILE_NAME` / `FILEGROUP_ID`/`_NAME` / `FILEGROUPPROPERTY` / `FILEPROPERTY` over the placeholder two-file model) → [`catalog-views.md`](docs/claude/catalog-views.md).
244244
- **Scalar UDFs / TVFs / views / stored procs / dynamic SQL / `@@NESTLEVEL` / `@@PROCID`**[`programmable.md`](docs/claude/programmable.md).
245245
- **`#foo` / `##foo` routing, DROP TABLE, TRUNCATE TABLE**[`temp-tables.md`](docs/claude/temp-tables.md).
246246
- **`DECLARE @t TABLE`, table-variable DML, `OUTPUT … INTO`**[`table-variables.md`](docs/claude/table-variables.md).

docs/claude/backlog.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Remaining phases, roughly in value order:
3636
**Remaining frontier**: Table Designer, Activity Monitor, standard reports, and IntelliSense's background metadata harvest.
3737
Candidate follow-on legs within tool scope: Visual Studio's SQL Server Object Explorer (DacFx-driven, a different query dialect from SMO) and LINQPad.
3838
- **SMO API sweep campaign**`.vs/smo-sweep` (gitignored local harness) walks SMO's full reachable read surface against the self-hosted simulator and, identically, against the live reference, draining every `Property.Value` and `Script()`-ing every `IScriptable`; modes `sweep` / `sweep --live` / `diff` → sorted JSON reports + `reports/triage.md`; workflow = sweep both sides → triage → fix bundles → graduated `Tests.Smo` tests → re-sweep.
39-
Open items from the latest triage: (a) `DBCC SHOW_STATISTICS … WITH STATS_STREAM` (SMO `Statistic.Stream`) stays `NotSupportedException` — it wants the raw serialized statistics-histogram blob, which the simulator has no faithful source for; (b) the unmodeled runtime/OS surfaces SMO reaches as absent objects (backup history `msdb.dbo.backupset`, `sys.dm_tran_persistent_version_store_stats`, file-space/IO DMVs, `sys.dm_os_process_memory`, `master.dbo.sysprocesses`, `FILEPROPERTY`, registry/OS xps) — surfaced as `PropertyCannotBeRetrievedException` / defaults, the legitimate-gap category.
39+
Open items from the latest triage: (a) `DBCC SHOW_STATISTICS … WITH STATS_STREAM` (SMO `Statistic.Stream`) stays `NotSupportedException` — it wants the raw serialized statistics-histogram blob, which the simulator has no faithful source for; (b) the unmodeled runtime/OS surfaces SMO reaches as absent objects (backup history `msdb.dbo.backupset`, `sys.dm_tran_persistent_version_store_stats`, file-space/IO DMVs, `sys.dm_os_process_memory`, `master.dbo.sysprocesses`, registry/OS xps) — surfaced as `PropertyCannotBeRetrievedException` / defaults, the legitimate-gap category (`FILEPROPERTY` now ships — see [`catalog-views.md`](catalog-views.md)).
4040
- **Open residuals of shipped wire features** (details in [`tds-endpoint.md`](tds-endpoint.md)): cancel/attention reaction is bounded by the in-flight statement's materialization, not interruptible inside a single statement's row loop; MARS never raises Msg 8628/8651 and fully materializes each session's response under the execution gate.
4141
- **Chunked `OFFSET/FETCH` paging: per-page constant factor, complexity class matches real** (probed 2026-07-18, plans + timings): real SQL Server also redoes the work on every page — `Top(OFFSET…)` over an ordered index scan reading offset+fetch rows when an index supplies the order, or a full scan + `Sort(TOP offset+fetch)` re-sorted per page when not; no cross-query sorted-result caching exists on either side, so "sort once, serve many pages" is rejected (it would invent behavior real doesn't have).
4242
The residual is constant-factor only: the simulator materializes (and for non-index order, sorts) all n rows per page regardless of offset where real's indexed plan touches only offset+fetch (measured at 150k rows / fetch 100 / offset 140k: sim ~41 ms vs real ~13 ms indexed, ~116 ms vs ~22 ms unindexed — real's sort is also 16-way parallel).
@@ -60,9 +60,6 @@ Blocked on a larger unmodeled parent feature (shipping a function here implies t
6060
Low priority / niche — simulatable (as placeholder constants or a small model) but rarely hit, so not worth attention yet:
6161

6262
- **Legacy text/image** — TEXTPTR / TEXTVALID (the `text` / `ntext` / `image` types ship; these navigate the deprecated READTEXT / WRITETEXT / UPDATETEXT pointer path).
63-
- **Files / filegroups** — FILE_ID / FILE_IDEX / FILE_NAME / FILEGROUP_ID / FILEGROUP_NAME / FILEGROUPPROPERTY / FILEPROPERTY.
64-
No physical file model.
65-
A named-filegroup registry now ships (`Database.Filegroups`, seeded PRIMARY=1, extended by the bacpac loader's `SqlFilegroup` dispatch; surfaced by `sys.filegroups`/`sys.data_spaces` and FILEGROUP-scoped extended properties) — the scalar helpers above could read it, though a `file_id` 1 placeholder is still needed for the file-level ones.
6663
- **Certificates** — CERTENCODED / CERTPRIVATEKEY (needs a small certificate-name → bytes model, or NULL placeholders).
6764
- **Full-text properties** — FULLTEXTCATALOGPROPERTY (the `CREATE FULLTEXT CATALOG` / `INDEX` DDL already ships; this reads its metadata).
6865
- **`sql_variant` minor quirk** (cross-type family ordering and one-side-variant comparison both shipped 2026-07-19 — see [`scalars.md`](scalars.md#sql_variant-expression-semantics)): a decimal-declared inner reports BaseType `numeric` rather than real's `decimal`.
@@ -78,9 +75,6 @@ Real bugs / limitations against shipped behavior — fixes are concrete work, no
7875
- **Per-object creation-time `QUOTED_IDENTIFIER` capture not modeled** — real SQL Server stamps procedures / views / triggers / tables with the QI setting in effect at CREATE (`sys.sql_modules.uses_quoted_identifier`, `OBJECTPROPERTY(id, 'IsQuotedIdentOn')`) and executes bodies under the captured setting; the simulator re-parses bodies under the executing session's current setting.
7976
See [`grammar.md`](grammar.md).
8077
Rare legacy-pattern impact.
81-
- **Error line-number residuals** — the line-number / server / procedure threading shipped ([`errors.md`](errors.md)): runtime & bind errors report the failing statement's start line, syntax errors the offending token's line, procedure bodies a CREATE-relative line + schema-qualified `Procedure`, dynamic SQL a batch-relative line.
82-
Two residuals remain, both narrow: (1) a **tokenizer-thrown** error on a *later* line of a multi-line token (unclosed string Msg 105 / unclosed comment Msg 113) reports the prior token's line, off by the token's internal newline count — the parse frontier lags the tokenizer's internal position; (2) **scalar-UDF / TVF / trigger / view body** errors report a *body-relative* line and carry no `Procedure` name (only stored procedures thread the `BodyLineOffset` + qualified name).
83-
Both surface a sane non-zero line and correct server today; closing them is per-body-type plumbing (a `BodyLineOffset` field + child-batch wiring like `Procedure` has) plus a tokenizer-position hook for (1).
8478
- **Skip-mode deferred name resolution — DML target tables not placeholder-continued** — the skip-mode parse-continuation fix (2026-07-17) substitutes placeholder metadata for a missing *FROM-clause table* or *schema-qualified function* so an un-taken branch parses to completion and is discarded whole (killing the orphaned-`ELSE` cascade — see [`control-flow.md`](control-flow.md)).
8579
A missing **DML target table** (INSERT / UPDATE / DELETE / MERGE) still resolves inline and throws Msg 208, caught by the residual object-name swallow whose flat recovery scan can orphan a trailing `ELSE` / `END` when the throw fires before the statement's own body is consumed.
8680
Probe-confirmed real SQL Server defers these (`IF 1=0 INSERT INTO missing SELECT * FROM other; SELECT 'after'``after`; the ELSE form runs the ELSE).

docs/claude/catalog-views.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,23 @@ Empty / NULL input → NULL; out-of-range index → NULL.
410410
Treats bracket-quoting at the segment level (`'[a.b].c'` keeps the dotted segment intact when the outer quotes balance).
411411
Common use in dynamic-SQL identifier manipulation.
412412

413+
**File / filegroup metadata scalars** (`Parser/Expressions/DatabaseScalarFunctions.cs`, `FilegroupProperty.cs`, `FileProperty.cs`) — return types probe-confirmed against SQL Server 2025 (2026-07-20):
414+
415+
- **`FILE_ID('file_name')`** (`smallint`) / **`FILE_IDEX('file_name')`** (`int`) / **`FILE_NAME(file_id)`** (`sysname`): the two forms of `FILE_ID` differ only in projected result type (real: FILE_ID → smallint, FILE_IDEX → int) and resolve identically over the placeholder file model.
416+
- **`FILEGROUP_ID('filegroup_name')`** (`smallint`) / **`FILEGROUP_NAME(filegroup_id)`** (`sysname`): read `Database.Filegroups` (PRIMARY = `data_space_id` 1; user filegroups 2, 3, … in registration order — same registry `sys.filegroups` / `sys.data_spaces` enumerate).
417+
- **`FILEGROUPPROPERTY('filegroup_name', 'property')`** (`int`): `IsDefault` (1 for PRIMARY, 0 for user — the simulator has no `MODIFY FILEGROUP … DEFAULT`, so PRIMARY is always the default), `IsUserDefinedFG` (0 for PRIMARY, 1 for a registered user filegroup), `IsReadOnly` (always 0 — no read-only filegroups modeled).
418+
- **`FILEPROPERTY('file_name', 'property')`** (`int`): `IsPrimaryFile` / `IsLogFile` / `IsReadOnly` / `SpaceUsed` — full deep-dive in [`scalars.md`](scalars.md); see the `sys.database_files` self-consistency contract above.
419+
420+
Shared conventions across the family (probe-confirmed):
421+
- NULL on any NULL argument, an unknown / unregistered name or id (including `FILE_NAME` / `FILEGROUP_NAME` of 0, a negative, or an out-of-range id), and an unknown property.
422+
- Name lookups are case-insensitive and trailing-space insensitive (SQL Server's internal `=` comparison — the `FILE_ID` / `FILEGROUP_ID` / `FILEGROUPPROPERTY` argument is `TrimEnd(' ')`'d before matching, since the modeled names carry no trailing spaces).
423+
- Property names are case-insensitive and trailing-space insensitive.
424+
- All operate on the **current** database only.
425+
426+
**Placeholder file model** (the file-level divergence): there is no physical file model.
427+
Each database exposes exactly two synthetic files, mirroring `sys.database_files` / `sys.master_files`: `<db>_Data` (`file_id` 1, primary ROWS, on PRIMARY) and `<db>_Log` (`file_id` 2, LOG).
428+
So `FILE_ID(N'simulated_Data')` = 1, `FILE_NAME(1)` = `simulated_Data`, and the file-level scalars stay consistent with those views; real SQL Server's actual logical file names (e.g. master's `master` / `mastlog`) are database-install artifacts the simulator doesn't reproduce.
429+
413430
Cross-cutting notes:
414431
- **Column subset (sys.* only)**: real SQL Server's `sys.tables` / `sys.objects` / `sys.columns` have 30+ columns each; the simulator ships the load-bearing subset that EF / migration tooling and the probe queried.
415432
`SELECT *` returns fewer columns than real SQL Server — apps that depend on a specific full-column shape will surface gaps, address those as needed.

0 commit comments

Comments
 (0)