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
Copy file name to clipboardExpand all lines: docs/claude/backlog.md
+1-3Lines changed: 1 addition & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -68,9 +68,7 @@ Low priority / niche — simulatable (as placeholder constants or a small model)
68
68
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.
69
69
-**Certificates** — CERTENCODED / CERTPRIVATEKEY (needs a small certificate-name → bytes model, or NULL placeholders).
70
70
-**Full-text properties** — FULLTEXTCATALOGPROPERTY (the `CREATE FULLTEXT CATALOG` / `INDEX` DDL already ships; this reads its metadata).
71
-
-**`sql_variant` mixed-inner-family ordering** — `ORDER BY` / `GROUP BY` over a variant column with *mixed inner base-type families* (int + nvarchar in one column) isn't modeled: real orders by a datatype-family rank, while the inner `CompareTo` rejects the cross-type pair (surfaces as `InvalidOperationException` from the sort).
72
-
Same-inner-family ordering, mixed-inner `DISTINCT`, and the single-scalar / comparison / `CAST` flows all work — see [`scalars.md`](scalars.md#sql_variant-expression-semantics), [`catalog-views.md`](catalog-views.md#the-sql_variant-type).
73
-
Related open quirk: a decimal-declared sequence/column's inner reports BaseType `numeric` rather than real's `decimal` — the single-decimal-family divergence.
71
+
-**`sql_variant` minor quirks** (cross-type family ordering 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` (the single-decimal-family naming divergence); a mixed variant-vs-base-typed comparison unwraps and promotes where real converts the base side up to variant and applies the family rules (a string variant never matches a numeric literal on real — unprobed, retained).
74
72
Deliberate exclusion, don't re-pitch: `msdb.dbo.syspolicy_configuration.current_value` stays `nvarchar` — it's a *view-body* projection (not a resource column) mixing `int` rows with a `binary` GUID row, every consumer reads a single named row and CASTs it, so a variant migration there would only touch the view SQL text for no observable gain.
75
73
-**FILESTREAM** — GET_FILESTREAM_TRANSACTION_CONTEXT (needs a FILESTREAM storage binding; NULL is a faithful "no FILESTREAM context" placeholder).
Copy file name to clipboardExpand all lines: docs/claude/catalog-views.md
+4-7Lines changed: 4 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -143,18 +143,15 @@ Contracts:
143
143
This is what lets the DSC catalog view — which re-encodes each generator row through `RowEncoder` — carry variant cells.
144
144
-**Coercion** — `CAST(x AS sql_variant)` wraps (`CoerceTo` a variant target); `CAST(variant AS <concrete>)` unwraps the inner and re-coerces.
145
145
`ISNULL(variant, x)` / `COALESCE(variant, …)` stay `sql_variant` (ISNULL fixes to the first arg's type; `Promote(variant, X) → variant`).
146
-
-**Comparison** — a variant operand unwraps to its inner value before the promote-and-compare (`CompareValuesPromoted`), so `value = 0` unwraps a variant int/bit and compares numerically.
147
-
Identity (Equals / GetHashCode for GROUP BY / DISTINCT) is strict on the inner value, so mixed-inner values are all distinct.
148
-
**Residual:**`ORDER BY` / `GROUP BY` over a variant column with *mixed inner base-type families* (int and nvarchar in one column) isn't modeled — SQL Server orders by a documented datatype-family rank, but the inner `CompareTo` rejects the cross-type pair (surfaces as an `InvalidOperationException` from the sort).
149
-
Same-inner-family ordering works; the built-ins realistically feed single-scalar / comparison / `CAST` flows that are unaffected.
146
+
-**Comparison** — a variant operand against a base-typed one unwraps to its inner value before the promote-and-compare (`CompareValuesPromoted`), so `value = 0` unwraps a variant int/bit and compares numerically; a both-variant pair follows the datatype-family rules.
147
+
Identity and ordering (Equals / GetHashCode / CompareTo for GROUP BY / DISTINCT / ORDER BY) follow SQL Server's two-level family comparison — family rank, then value within the family, with cross-type equal values collapsing into one bucket (`Storage/SqlVariantOrdering.cs`; probed rules in [`scalars.md`](scalars.md#sql_variant-expression-semantics)).
150
148
-**Arithmetic / concatenation** — probe-confirmed against SQL Server 2025: `variant + non-variant` raises **Msg 257** (`Implicit conversion from data type sql_variant to <target> is not allowed. Use the CONVERT function to run this query.`); `variant + variant` and `string + variant` raise **Msg 402** (`… incompatible in the <op> operator`).
151
149
`SqlType.PromoteForArithmetic` is the single source; a runtime guard in `IntegerArithmetic` routes through it so `Run`-time and projection-schema errors agree.
152
-
-**TDS wire** — a `sql_variant` result column emits COLMETADATA type `0x62` (SSVARIANTTYPE) and the MS-TDS 2.2.5.5.3 per-value body (see [`tds-endpoint.md`](tds-endpoint.md)).
153
-
RPC `sql_variant`*parameters* remain rejected.
150
+
-**TDS wire** — a `sql_variant` result column emits COLMETADATA type `0x62` (SSVARIANTTYPE) and the MS-TDS 2.2.5.5.3 per-value body; RPC `sql_variant` parameters ship in both directions, TVP variant columns included (see [`tds-endpoint.md`](tds-endpoint.md)).
154
151
155
152
**Consumers surfacing true `sql_variant`:** the `SERVERPROPERTY` / `SESSIONPROPERTY` / `CONNECTIONPROPERTY` / `COLLATIONPROPERTY` / `LOGINPROPERTY` / `SESSION_CONTEXT` / `SQL_VARIANT_PROPERTY` / `DATABASEPROPERTYEX` / `OBJECTPROPERTYEX` scalar family (see [`scalars.md`](scalars.md)), `sys.configurations`.`value*`, `sys.database_scoped_configurations`.`value*`, `sys.sequences` (`start_value` / `increment` / `minimum_value` / `maximum_value` / `current_value` / `last_used_value`, inner = the sequence's declared type), `sys.identity_columns` (`seed_value` / `increment_value` / `last_value`, inner = the identity column's declared type), `sys.parameters.default_value` (always a NULL variant), `sys.partition_range_values.value` (always empty), and the `sys.symmetric_keys` / `sys.asymmetric_keys` sql_variant columns (`key_thumbprint` / `cryptographic_provider_algid`, always empty).
156
153
No inner-type substitution remains.
157
-
The one **semantic residual** is `ORDER BY` / `GROUP BY` over a variant column with *mixed inner base-type families* (see [`scalars.md`](scalars.md#sql_variant-expression-semantics)); a decimal-declared sequence's inner reports BaseType `numeric` rather than real's `decimal` (the single-decimal-family quirk).
154
+
Remaining quirk: a decimal-declared sequence's inner reports BaseType `numeric` rather than real's `decimal` (the single-decimal-family naming divergence).
158
155
-**`sys.filegroups`** is the row-filegroup subset of `sys.data_spaces` (same `Database.Filegroups` enumeration via `EnumerateFilegroupRows` — PRIMARY plus any bacpac-registered filegroup like WWI's `[USERDATA]`) plus `filegroup_guid uniqueidentifier` (NULL), `log_filegroup_id int` (NULL), `is_read_only` / `is_autogrow_all_files bit` (0).
159
156
SMO's CREATE-scripting index/full-text queries read it; DacFx's bacpac export re-emits a standalone `SqlFilegroup` element per non-PRIMARY row.
160
157
-**`sys.periods`** projects one row per table carrying a `PERIOD FOR SYSTEM_TIME` declaration (`HeapTable.PeriodColumns`), **history siblings excluded** (they hold no period of their own even though the simulator copies `PeriodColumns` onto them for the `FOR SYSTEM_TIME` query machinery).
Copy file name to clipboardExpand all lines: docs/claude/scalars.md
+9-2Lines changed: 9 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -508,11 +508,18 @@ Probe-confirmed against SQL Server 2025 (2026-07-16):
508
508
-**`ISNULL` / `COALESCE` / `CASE`** keep the `sql_variant` result type (variant has highest data-type precedence in `SqlType.Promote`) and preserve each value's inner type — `ISNULL(SESSIONPROPERTY('ANSI_NULLS'), 0)` stays `sql_variant`.
509
509
-**`UNION [ALL]`** keeps each row's own inner base type — no schema unification/promotion (a variant column can be `int` on one row, `nvarchar` on the next).
510
510
-**Comparison** against a non-variant (`WHERE int_col = SESSION_CONTEXT(N'k')`) unwraps the variant to its inner value.
Residual: real converts the base-typed side of a mixed pair *up* to `sql_variant` (highest precedence) and applies the family rules — so a string variant never matches a numeric literal on real, while the unwrap path converts and can match; unprobed, retained.
511
513
-**`SELECT … INTO`** from a variant-producing built-in creates a `sql_variant` column (probe-confirmed).
512
514
-**Arithmetic** rejects: `variant + non-variant` → **Msg 257** (`Implicit conversion from data type sql_variant to <target> is not allowed. Use the CONVERT function to run this query.`); `variant + variant` and `string + variant` → **Msg 402** (`… incompatible in the add operator`).
513
515
`PromoteForArithmetic` is the single source; a runtime guard in `IntegerArithmetic` routes through it so `Run`-time and projection-schema errors agree.
514
-
-**Residual**: `ORDER BY` / `GROUP BY` over a variant column with *mixed inner base-type families* (e.g. `int` and `nvarchar` in the same column) isn't modeled — real orders by a documented type-family rank, the simulator's inner `CompareTo` rejects the cross-type pair (surfaces as an `InvalidOperationException` from the sort).
515
-
Same-inner-family ordering and mixed-inner `DISTINCT` (equality unwraps per value) both work; single-scalar / `ISNULL` / comparison / `CAST` flows the built-ins realistically feed are unaffected.
516
+
-**Cross-type ordering / grouping** (`Storage/SqlVariantOrdering.cs`, probe-confirmed 2026-07-19): comparison is two-level — datatype-family rank first, then value within the family.
517
+
Six families, lowest to highest: **1 `uniqueidentifier`; 2 binary** (`binary`/`varbinary`, byte-lexicographic); **3 character** (`char`/`varchar`/`nchar`/`nvarchar` — Unicode and non-Unicode are ONE family); **4 exact numeric** (`bit`, integer types, `decimal`, `money`/`smallmoney`, compared as decimal); **5 approximate** (`real`/`float` — above *every* exact value regardless of magnitude); **6 date/time** (compared as an instant: `time` anchored to 1900-01-01, `datetimeoffset` by UTC instant).
518
+
Cross-family comparison is value-blind (`float 0.5 > bigint 1000000`); within a family, cross-type values compare by value and equal values are truly equal — `int 5` / `bigint 5` / `decimal 5.00` are one GROUP BY / DISTINCT bucket whose representative is the first value encountered (matching real's plan-order representative), and their ORDER BY tie order is undefined on real (plan-dependent), so tests must not pin it.
519
+
NULL sorts lowest.
520
+
`MIN`/`MAX` pick the family-hierarchy extremes.
521
+
Same-collation character pairs compare under that collation; cross-collation pairs compare by code point **without** a Msg 468 conflict (probed) — the character family hashes by rank alone since no single hash agrees with both regimes.
522
+
The `SqlValue` variant arms (`CompareTo` / `Equals` / `GetHashCode`) implement the rules, so ORDER BY, GROUP BY, DISTINCT, MIN/MAX, and hash joins all inherit them via `SqlValueKey`.
516
523
517
524
## Built-in TVF: `STRING_SPLIT`
518
525
`STRING_SPLIT(input, separator [, enable_ordinal])` dispatches in `ParseSingleFromSource` alongside `OPENJSON` — case-insensitive name match before generic name resolution.
0 commit comments