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
Cross-category integer ↔ string Promote: returns the integer's specific subtype (tinyint+'3' → tinyint, bigint+'3' → bigint), with the string parsing through the integer's CAST path; bit + string raises Msg 402 (+/-/%) or Msg 8117 (*/) per SQL Server 2025. Coalesce now caches its Promote result type, BuildSynthesizedSqlRow runs Run-then-GetSqlType so mixed-type CASE / Coalesce in FROM-less SELECTs land at the joint type, and FromSqlInterpolated covers the EF Core integration end-to-end.
Cross-category integer ↔ string promotion lands the integer's specific subtype (`tinyint + '3'` stays tinyint, `bigint + '3'` stays bigint — probe-confirmed against SQL Server 2025, 2026-05-08). The string side parses through the integer's existing CAST path at runtime — empty / whitespace-only → 0, `+`/`-` sign prefixes accepted, leading/trailing whitespace trimmed. **Decimal-shaped strings (`'5.5'`, `'5.0'`) raise Msg 245** rather than routing through decimal — SQL Server's int-target string parse rejects any non-integer literal. Hex notation (`'0x05'`) likewise rejected; the `0x` literal form is a different parse path.
190
+
191
+
`PromoteFromInteger`'s `String => a` arm and `PromoteFromString`'s `Integer => b` arm are the static rule; `IntegerArithmetic` in `TwoSidedExpression` normalizes the string operand by `CoerceTo(integerType)` before dispatching to `PureIntegerArithmetic`. The bit asymmetry: `bit ↔ string`**comparison** works through string→bit CAST (with `'true'` / `'false'` / empty all accepted), but `bit + str` (and other bit-arithmetic with strings) is rejected — `+` / `-` / `%` raise **Msg 402** (`"The data types bit and varchar are incompatible in the {add|subtract|modulo} operator."`); `*` / `/` raise **Msg 8117** with the LEFT operand's type only (`"Operand data type bit is invalid for {multiply|divide} operator."`). The asymmetry mirrors SQL Server's same bit-arithmetic restriction with another bit, which is also rejected.
192
+
193
+
WHERE on a varchar column compared against an int (or vice versa) halts the whole query on the first unparseable row — the failure isn't isolated as per-row UNKNOWN. SQL Server's lazy-IN quirk (where an unparseable value in an IN list is suppressed when any other value matches) isn't modeled — strict semantics: any conversion error in an IN-list propagates immediately.
194
+
195
+
`BuildSynthesizedSqlRow` (the FROM-less SELECT path) runs each expression first to surface runtime-only errors with their operator-name wording, then calls `GetSqlType` to populate the projection schema and bridges any runtime/schema type mismatch via `CoerceTo` — required for mixed-type CASE / Coalesce expressions (`case when 1=0 then 5 else '99' end` lands as int 99 even without a FROM clause).
196
+
188
197
### Decimal arithmetic precision / scale
189
198
SQL Server has per-operator scale rules for decimal that differ from the joint-envelope rule used for comparison / COALESCE / set-op type unification (probe-confirmed against SQL Server 2025, 2026-05-08):
-`OUTPUT INTO @table_var`, `OUTPUT DELETED.*` / `INSERTED.*` star expansion. Per-column `OUTPUT INSERTED.<col>` / `OUTPUT DELETED.<col>`*is* supported (UPDATE / DELETE both); only the star-expansion form is missing. `OUTPUT INTO` (sending the projection to a table variable rather than the result set) isn't.
306
314
- Joined-source UPDATE / DELETE FROM clauses (`UPDATE a SET ... FROM t AS a JOIN u AS b ON ...`). The single-source alias form (`UPDATE a SET ... FROM t AS a [WHERE ...]`, `DELETE FROM a FROM t AS a [WHERE ...]`) IS supported — that's what EF7+ `ExecuteUpdate` / `ExecuteDelete` emit, verified against real SQL Server 2025. Adding sources beyond the single aliased target raises `NotSupportedException` so the gap is visible.
0 commit comments