Skip to content

Commit 6418af1

Browse files
committed
Removed the speculatively-added UNICODE_CODEPOINT collation.
1 parent ef9fb65 commit 6418af1

4 files changed

Lines changed: 3 additions & 26 deletions

File tree

SqlServerSimulator.Tests/CollationDeclaredColumnTests.cs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,6 @@ public void InList_CrossCollation_RaisesMsg468()
332332
[DataRow("Turkish_CI_AS")]
333333
[DataRow("Latin1_General_CI_AS_KS_WS")]
334334
[DataRow("SQL_Latin1_General_CP437_CS_AS")]
335-
[DataRow("UNICODE_CODEPOINT")]
336335
public void NewCollation_AcceptedAndRoundTripsThroughSysColumns(string collationName)
337336
{
338337
var sim = new Simulation();
@@ -453,7 +452,6 @@ insert t values (N'Hello')
453452
[DataRow("Latin1_General_BIN2")]
454453
[DataRow("Latin1_General_CI_AS_KS_WS")]
455454
[DataRow("SQL_Latin1_General_CP437_CS_AS")]
456-
[DataRow("UNICODE_CODEPOINT")]
457455
[DataRow("Japanese_XJIS_140_CI_AS")]
458456
[DataRow("Chinese_PRC_CI_AS")]
459457
[DataRow("Turkish_CI_AS")]
@@ -485,7 +483,6 @@ insert t values (N'banana'), (N'apple'), (N'cherry')
485483
[DataRow("Latin1_General_BIN2", 3)]
486484
[DataRow("Latin1_General_CI_AS_KS_WS", 1)]
487485
[DataRow("SQL_Latin1_General_CP437_CS_AS", 3)]
488-
[DataRow("UNICODE_CODEPOINT", 3)]
489486
[DataRow("Japanese_XJIS_140_CI_AS", 1)]
490487
[DataRow("Chinese_PRC_CI_AS", 1)]
491488
[DataRow("Turkish_CI_AS", 1)]

SqlServerSimulator.Tests/CollationMetadataTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public void Column_Collate_UnrecognizedName_RaisesNotSupported()
125125

126126
[TestMethod]
127127
public void FnHelpCollations_ListsRecognized()
128-
=> AreEqual(27, new Simulation().ExecuteScalar(
128+
=> AreEqual(26, new Simulation().ExecuteScalar(
129129
"SELECT COUNT(*) FROM sys.fn_helpcollations()"));
130130

131131
[TestMethod]

SqlServerSimulator/Collation.cs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -200,22 +200,6 @@ private protected Collation()
200200
/// </summary>
201201
internal static readonly CultureCollation SqlLatin1GeneralCp437CsAs = new("SQL_Latin1_General_CP437_CS_AS", CultureInfo.InvariantCulture.Name, caseSensitive: true);
202202

203-
/// <summary>
204-
/// "UNICODE_CODEPOINT" — pure ordinal Unicode codepoint comparison.
205-
/// Semantically equivalent to <see cref="Latin1GeneralBin2"/> at the
206-
/// value level; the name appears on a handful of system columns in
207-
/// some BACPACs (notably AdventureWorks2025). Reuses the binary
208-
/// codepath via a separate metadata-only instance.
209-
/// </summary>
210-
internal static readonly UNICODE_CODEPOINT UnicodeCodepoint = new();
211-
212-
/// <summary>Metadata-only binary collation under the
213-
/// <c>UNICODE_CODEPOINT</c> name; behavior body is <see cref="BinaryCollation"/>.</summary>
214-
internal sealed class UNICODE_CODEPOINT : BinaryCollation
215-
{
216-
public override string Name => "UNICODE_CODEPOINT";
217-
}
218-
219203
/// <summary>"Korean_100_CI_AS" — Korean (Hangul) v100 sort via .NET's
220204
/// <c>ko-KR</c> <see cref="CompareInfo"/>. Same sort-tiebreaker
221205
/// divergence caveat as the other locale collations
@@ -341,7 +325,6 @@ internal sealed class Latin1_General_100_BIN2_UTF8 : BinaryCollation
341325
[Latin1GeneralBin2.Name] = "Latin1-General, binary code point comparison sort",
342326
[Latin1GeneralCiAsKsWs.Name] = "Latin1-General, case-insensitive, accent-sensitive, kanatype-sensitive, width-sensitive",
343327
[SqlLatin1GeneralCp437CsAs.Name] = "Latin1-General, case-sensitive, accent-sensitive, kanatype-insensitive, width-insensitive for Unicode Data, SQL Server Sort Order 30 on Code Page 437 for non-Unicode Data",
344-
[UnicodeCodepoint.Name] = "Unicode code point comparison sort",
345328
[JapaneseXJIS140CiAs.Name] = "Japanese-XJIS-140, case-insensitive, accent-sensitive, kanatype-insensitive, width-insensitive",
346329
[ChinesePrcCiAs.Name] = "Chinese-PRC, case-insensitive, accent-sensitive, kanatype-insensitive, width-insensitive",
347330
[TurkishCiAs.Name] = "Turkish, case-insensitive, accent-sensitive, kanatype-insensitive, width-insensitive",
@@ -379,7 +362,6 @@ internal sealed class Latin1_General_100_BIN2_UTF8 : BinaryCollation
379362
[Latin1GeneralBin2.Name] = Latin1GeneralBin2,
380363
[Latin1GeneralCiAsKsWs.Name] = Latin1GeneralCiAsKsWs,
381364
[SqlLatin1GeneralCp437CsAs.Name] = SqlLatin1GeneralCp437CsAs,
382-
[UnicodeCodepoint.Name] = UnicodeCodepoint,
383365
[JapaneseXJIS140CiAs.Name] = JapaneseXJIS140CiAs,
384366
[ChinesePrcCiAs.Name] = ChinesePrcCiAs,
385367
[TurkishCiAs.Name] = TurkishCiAs,

docs/claude/collations.md

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Chained `expr COLLATE A COLLATE B` rejects with Msg 156 at parse time (probe-con
5858

5959
## Recognized catalog
6060

61-
27 entries today. Resolution at parse / load time consults the case-insensitive `Collation.ByName` map; names outside the set raise `NotSupportedException` in direct SQL and surface on `BacpacImportResult.Warnings` for BACPAC loads (graceful degradation).
61+
26 entries today. Resolution at parse / load time consults the case-insensitive `Collation.ByName` map; names outside the set raise `NotSupportedException` in direct SQL and surface on `BacpacImportResult.Warnings` for BACPAC loads (graceful degradation).
6262

6363
### Latin1 / SQL_Latin1
6464

@@ -75,7 +75,6 @@ Chained `expr COLLATE A COLLATE B` rejects with Msg 156 at parse time (probe-con
7575
| `Latin1_General_100_CI_AS_SC_UTF8` | Invariant culture CI (same body as `_100_CI_AS`) | UTF-8 is a storage encoding only at the simulator's UTF-16 value layer; `_SC` (supplementary characters) is handled natively by `CompareInfo`. |
7676
| `Latin1_General_100_CS_AS_SC_UTF8` | Invariant culture CS | Same body as `Latin1_General_CS_AS`. |
7777
| `Latin1_General_100_BIN2_UTF8` | `StringComparer.Ordinal` (`BinaryCollation` body) | Pure codepoint binary; UTF-8 storage doesn't alter compare semantics. |
78-
| `UNICODE_CODEPOINT` | `StringComparer.Ordinal` (`BinaryCollation` body) | Semantically equivalent to BIN2 at the value level; appears in AdventureWorks2025. |
7978

8079
### CJK locales
8180

@@ -124,7 +123,7 @@ The two bodies diverge for any string containing characters whose CP1252 byte li
124123

125124
The dispatch hangs off `Collation.ForVarcharStorage()` (a virtual returning `this` by default; the BIN / BIN2 singletons override to point at the `Cp1252BinaryCollation` sibling). `VarcharSqlType.WithCollation` and `CharSqlType.WithCollation` call it at column-pin time; `NVarcharSqlType` / `NCharSqlType` don't substitute. Both bodies share the same `Name` so catalog views report one collation name and `Collation.Resolve` treats them as the same collation for cross-operand coercibility.
126125

127-
`Latin1_General_100_BIN2_UTF8` keeps the codepoint-order body — UTF-8 byte order equals codepoint order (UTF-8 invariant), so the substitution isn't needed even though it's a varchar collation. `UNICODE_CODEPOINT` is Unicode-only (the simulator doesn't reject it on varchar at parse time — a low-priority gap).
126+
`Latin1_General_100_BIN2_UTF8` keeps the codepoint-order body — UTF-8 byte order equals codepoint order (UTF-8 invariant), so the substitution isn't needed even though it's a varchar collation.
128127

129128
### Microsoft-docs-vs-real-behavior gap: BIN2 is code *unit*, not code point
130129

@@ -151,7 +150,6 @@ The pre-2005 `_BIN` (not `_BIN2`) variant has a different, real quirk: at positi
151150
- **Set ops (UNION / UNION ALL / INTERSECT / EXCEPT) don't apply collation-conflict checks at the column-pair level yet.** Probe showed UNION raises Msg 468, UNION ALL raises Msg 457 across cross-collation columns; the simulator's set-op type-promotion path doesn't call `Collation.Resolve`. Cross-collation set-op columns currently fall through to the legacy type-precedence resolution.
152151
- **`text` / `ntext` columns can't be declared with an explicit COLLATE in the simulator.** Real SQL Server allows it; the simulator's single-instance modeling collapses all text/ntext to the default. Low impact (text/ntext deprecated since SQL Server 2005).
153152
- **Sysname's collation is always `Collation.Default`** at `Implicit` rank — real SQL Server's sysname inherits the server's catalog collation which can differ from the user database's collation; the simulator's single-instance modeling collapses them.
154-
- **`UNICODE_CODEPOINT` is over-permitted.** Real SQL Server 2025 rejects `COLLATE UNICODE_CODEPOINT` with `Invalid collation 'UNICODE_CODEPOINT'.` — it's an internal-only collation that surfaces on XML-index storage columns in `sys.columns.collation_name` (probed against `AdventureWorks2025.sys.xml_index_nodes_*`) but isn't on `sys.fn_helpcollations()` and can't be applied in a `COLLATE` clause. The simulator accepts it everywhere via the same `Recognized` whitelist that drives BACPAC catalog round-trip. Splitting "loader-recognized" from "COLLATE-acceptable" requires a separate dispatch flag; deferred because real exposure is narrow (someone manually typing `COLLATE UNICODE_CODEPOINT` in user SQL).
155153
- **`Latin1_General_100_BIN2_UTF8` and the other `*_UTF8` collations are storage-misencoded.** Real SQL Server stores values as UTF-8 bytes (`` U+20AC → 3 bytes `E2 82 AC`, `NBSP` U+00A0 → 2 bytes `C2 A0`, 😀 U+1F600 → 4 bytes `F0 9F 98 80`). The simulator collapses all varchar storage to CP1252 regardless of collation, so `DATALENGTH`, `LEN` (under `_SC_UTF8`), and storage-size budgeting diverge for non-ASCII inputs. Sort happens to match for most cases because UTF-8 byte order == UTF-16 codepoint order == `StringComparer.Ordinal` (the simulator's value layer). Fixing this requires per-collation storage encoder dispatch in `VarcharSqlType.Encode/Decode`; deferred as a significant refactor.
156154
- **`_SC_` (supplementary-character-aware) semantics aren't modeled.** Probe showed three observable effects on SQL Server 2025 the simulator doesn't replicate:
157155
- `LEN(N'😀')` returns 2 under non-`_SC_` collations, 1 under `_SC_`. The simulator always returns code-unit count (2 in this case).

0 commit comments

Comments
 (0)