Commit b35d76e
fix(sql): pin culture-sensitive ToString to InvariantCulture in parameter encoding
Two latent bugs that surfaced today on a Mac with ar-SA culture (UmAlQura
/ Hijri calendar) running CosmoMailAdmin against a prod Postgres:
1. PgMessage.cs line 411: SqlValueKind.Date encoded via
`DateValue.ToString("yyyy-MM-dd HH:mm:ss.ffffff")` without an explicit
culture. The format string only specifies *fields*; the *calendar*
comes from CurrentThread.CurrentCulture. Under ar-SA, year 2026
formats as Hijri 1447, so a row inserted today gets stored with
`created_at = 1447-11-10`, ~579 years in the past. Real example:
the chalyar.com mail user created via the wizard on 2026-04-27 has
`created_at = 1447-11-10 00:32:09 UTC`.
2. SqlValue.cs AsString() / ToString() called .ToString() on numeric
values (Int8..Int64, Float, Double, Decimal) without a culture.
Under de-DE/fr-FR/etc., decimal separators flip to ',' which Postgres
rejects as malformed numeric. Hadn't bitten in production because the
deployed servers are Linux with en-US default, but any local-Mac
admin or German-locale CI run would hit it.
Fix: pass `CultureInfo.InvariantCulture` everywhere a numeric or custom
date format is rendered for SQL parameter encoding. The DateTime "O" /
"o" specifier is documented as culture-independent + Gregorian-fixed,
so existing AsString uses of "O" stay as-is.
Tests pin the behavior under deliberately wrong cultures:
- AsString_Date_UsesGregorianRegardlessOfCulture (ar-SA)
- AsString_Decimal_UsesPeriodSeparatorRegardlessOfCulture (de-DE)
- AsString_Double_UsesPeriodSeparatorRegardlessOfCulture (de-DE)
- AsString_Int64_StableAcrossCultures (ar-SA)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>1 parent 2d90d3e commit b35d76e
3 files changed
Lines changed: 90 additions & 15 deletions
File tree
- src
- CosmoSQLClient.Core
- CosmoSQLClient.Postgres/Proto
- tests/CosmoSQLClient.Core.Tests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
1 | 3 | | |
2 | 4 | | |
3 | 5 | | |
| |||
132 | 134 | | |
133 | 135 | | |
134 | 136 | | |
135 | | - | |
136 | | - | |
137 | | - | |
138 | | - | |
139 | | - | |
140 | | - | |
141 | | - | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
142 | 149 | | |
143 | 150 | | |
144 | 151 | | |
| |||
236 | 243 | | |
237 | 244 | | |
238 | 245 | | |
239 | | - | |
240 | | - | |
241 | | - | |
242 | | - | |
243 | | - | |
244 | | - | |
245 | | - | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
| 251 | + | |
| 252 | + | |
246 | 253 | | |
247 | 254 | | |
248 | 255 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | 1 | | |
| 2 | + | |
2 | 3 | | |
3 | 4 | | |
4 | 5 | | |
| |||
408 | 409 | | |
409 | 410 | | |
410 | 411 | | |
411 | | - | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
| 418 | + | |
412 | 419 | | |
413 | 420 | | |
414 | 421 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
| 124 | + | |
| 125 | + | |
| 126 | + | |
| 127 | + | |
| 128 | + | |
| 129 | + | |
| 130 | + | |
| 131 | + | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
99 | 160 | | |
0 commit comments