Skip to content

fix: use ToLowerInvariant/ToUpperInvariant for SQL identifiers (Turkish collation bug)#247

Merged
jeremydmiller merged 2 commits into
masterfrom
fix/turkish-collation-tolowerinvariant
Apr 9, 2026
Merged

fix: use ToLowerInvariant/ToUpperInvariant for SQL identifiers (Turkish collation bug)#247
jeremydmiller merged 2 commits into
masterfrom
fix/turkish-collation-tolowerinvariant

Conversation

@jeremydmiller

Copy link
Copy Markdown
Member

Summary

Files changed:

File Change
`Weasel.Postgresql/Tables/TableColumn.cs` Column name + type normalization
`Weasel.SqlServer/Tables/TableColumn.cs` Column name + type normalization
`Weasel.Postgresql/PostgresqlProvider.cs` `ConvertSynonyms` type matching
`Weasel.SqlServer/SqlServerProvider.cs` `ConvertSynonyms` + `ReadAction` (cascade actions)
`Weasel.Postgresql/Tables/IndexDefinition.cs` DDL keyword parsing
`Weasel.Postgresql/Extension.cs` Extension name normalization
`Weasel.Core/Migrator.cs` Template file name lookup
`Weasel.SqlServer/Tables/Table.cs` SQL variable name from GUID

Test plan

  • Added `column_name_normalization_is_culture_invariant` unit test in both `Weasel.Postgresql.Tests` and `Weasel.SqlServer.Tests` — sets `CultureInfo.CurrentCulture = new CultureInfo("tr-TR")` and asserts `INFORMATION_SCHEMA` normalizes to `information_schema` (not `ınformation_schema`)
  • All 6 test runs pass (3 .NET versions × 2 providers) without requiring a database connection
  • Full solution builds with 0 errors

🤖 Generated with Claude Code

jeremydmiller and others added 2 commits April 9, 2026 14:49
When a table's primary key is dropped and recreated via ALTER TABLE ...
DROP CONSTRAINT ... CASCADE, PostgreSQL also drops foreign keys from
other tables that reference the PK. Previously these referencing FKs
were not recreated, leaving the schema in an inconsistent state.

The fix:
- In TableDelta.PostProcess(), scan all other table deltas for FKs
  that reference this table when the PK is being changed
- Store those referencing FKs in a new ReferencingForeignKeys list
- In writePrimaryKeyChanges(), after recreating the PK, emit
  ALTER TABLE ... ADD CONSTRAINT for each referencing FK

Closes #45

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…QL identifiers

In Turkish locale (tr-TR), String.ToLower() converts 'I' to dotless 'ı' (U+0131)
instead of 'i', corrupting SQL identifiers (e.g. INFORMATION_SCHEMA →
ınformation_schema). Replace all .ToLower()/.ToUpper() calls that operate on SQL
identifiers, schema names, column names, type names, and keywords with
.ToLowerInvariant()/.ToUpperInvariant(). Adds unit tests that set
CultureInfo.CurrentCulture = tr-TR to verify correct normalization.

Upstream fix for JasperFx/wolverine#2472 (companion PR to JasperFx/wolverine#2480).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jeremydmiller jeremydmiller merged commit 796270c into master Apr 9, 2026
21 checks passed
@jeremydmiller jeremydmiller deleted the fix/turkish-collation-tolowerinvariant branch April 9, 2026 21:15
jeremydmiller added a commit that referenced this pull request May 13, 2026
Refreshes the AOT-cleanup PR forward to the foundation alphas that just
shipped from #247 / #250 (the IsAotCompatible=true flip
and the CommandLine reflective surface annotation pass). Adopting these
gives Weasel.Core / Weasel.* the precise [RequiresUnreferencedCode] /
[RequiresDynamicCode] annotations on JasperFx.CommandLine entry points
in time for the 9.0.0-alpha.3 cut.

Carries the existing weasel#265 + weasel#266 fixes from the original
alpha.8 bump branch:

  - AssertCommand override carries [UnconditionalSuppressMessage("AOT",
    "IL3050")] for the dev-time Spectre.Console exception writer (#265)
  - CommandBuilderBase.AddParameters(object) carries
    [RequiresUnreferencedCode] for the runtime reflection it does (#266)

Local Weasel.Core build clean against alpha.11 / alpha.4. The next
Publish Nugets workflow run cuts Weasel.* 9.0.0-alpha.3 (Directory.Build.props
is already at that version line).
jeremydmiller added a commit that referenced this pull request May 13, 2026
)

Refreshes the AOT-cleanup PR forward to the foundation alphas that just
shipped from #247 / #250 (the IsAotCompatible=true flip
and the CommandLine reflective surface annotation pass). Adopting these
gives Weasel.Core / Weasel.* the precise [RequiresUnreferencedCode] /
[RequiresDynamicCode] annotations on JasperFx.CommandLine entry points
in time for the 9.0.0-alpha.3 cut.

Carries the existing weasel#265 + weasel#266 fixes from the original
alpha.8 bump branch:

  - AssertCommand override carries [UnconditionalSuppressMessage("AOT",
    "IL3050")] for the dev-time Spectre.Console exception writer (#265)
  - CommandBuilderBase.AddParameters(object) carries
    [RequiresUnreferencedCode] for the runtime reflection it does (#266)

Local Weasel.Core build clean against alpha.11 / alpha.4. The next
Publish Nugets workflow run cuts Weasel.* 9.0.0-alpha.3 (Directory.Build.props
is already at that version line).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant