Skip to content

Commit 8b9cf53

Browse files
committed
fixup! ObjectListFilter filter values to target type coercion (#589)
1 parent 9808e55 commit 8b9cf53

2 files changed

Lines changed: 44 additions & 26 deletions

File tree

src/FSharp.Data.GraphQL.Server.Middleware/ObjectListFilterModule.fs

Lines changed: 41 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -200,31 +200,49 @@ module ObjectListFilter =
200200
match comparer with
201201
| null -> ValueNone
202202
| :? StringComparer as sc ->
203-
let mutable isOrdinalIgnoreCase = false
204-
205-
if StringComparer.IsWellKnownOrdinalComparer (sc, &isOrdinalIgnoreCase) then
206-
if isOrdinalIgnoreCase then
207-
ValueSome StringComparison.OrdinalIgnoreCase
208-
else
209-
ValueSome StringComparison.Ordinal
203+
// Fast path: match well-known singletons by reference first.
204+
// This is required because on Linux/Ubuntu CultureInfo.CurrentCulture and
205+
// CultureInfo.InvariantCulture share the same CompareInfo, making them
206+
// indistinguishable via IsWellKnownCultureAwareComparer alone.
207+
if obj.ReferenceEquals (sc, StringComparer.OrdinalIgnoreCase) then
208+
ValueSome StringComparison.OrdinalIgnoreCase
209+
elif obj.ReferenceEquals (sc, StringComparer.InvariantCultureIgnoreCase) then
210+
ValueSome StringComparison.InvariantCultureIgnoreCase
211+
elif obj.ReferenceEquals (sc, StringComparer.CurrentCultureIgnoreCase) then
212+
ValueSome StringComparison.CurrentCultureIgnoreCase
213+
elif obj.ReferenceEquals (sc, StringComparer.Ordinal) then
214+
ValueSome StringComparison.Ordinal
215+
elif obj.ReferenceEquals (sc, StringComparer.InvariantCulture) then
216+
ValueSome StringComparison.InvariantCulture
217+
elif obj.ReferenceEquals (sc, StringComparer.CurrentCulture) then
218+
ValueSome StringComparison.CurrentCulture
210219
else
211-
let mutable compareInfo = Unchecked.defaultof<Globalization.CompareInfo>
212-
let mutable compareOptions = Globalization.CompareOptions.None
213-
214-
if StringComparer.IsWellKnownCultureAwareComparer (sc, &compareInfo, &compareOptions) then
215-
let isInvariantCulture = compareInfo.Equals Globalization.CultureInfo.InvariantCulture.CompareInfo
216-
let isCurrentCulture = compareInfo.Equals Globalization.CultureInfo.CurrentCulture.CompareInfo
217-
218-
match compareOptions with
219-
| Globalization.CompareOptions.None when isInvariantCulture -> ValueSome StringComparison.InvariantCulture
220-
| Globalization.CompareOptions.IgnoreCase when isInvariantCulture ->
221-
ValueSome StringComparison.InvariantCultureIgnoreCase
222-
| Globalization.CompareOptions.None when isCurrentCulture -> ValueSome StringComparison.CurrentCulture
223-
| Globalization.CompareOptions.IgnoreCase when isCurrentCulture ->
224-
ValueSome StringComparison.CurrentCultureIgnoreCase
225-
| _ -> ValueNone
220+
// Fallback for non-singleton comparers (e.g. StringComparer.Create(...)).
221+
let mutable isOrdinalIgnoreCase = false
222+
223+
if StringComparer.IsWellKnownOrdinalComparer (sc, &isOrdinalIgnoreCase) then
224+
if isOrdinalIgnoreCase then
225+
ValueSome StringComparison.OrdinalIgnoreCase
226+
else
227+
ValueSome StringComparison.Ordinal
226228
else
227-
ValueNone
229+
let mutable compareInfo = Unchecked.defaultof<Globalization.CompareInfo>
230+
let mutable compareOptions = Globalization.CompareOptions.None
231+
232+
if StringComparer.IsWellKnownCultureAwareComparer (sc, &compareInfo, &compareOptions) then
233+
let isInvariantCulture = compareInfo.Equals Globalization.CultureInfo.InvariantCulture.CompareInfo
234+
let isCurrentCulture = compareInfo.Equals Globalization.CultureInfo.CurrentCulture.CompareInfo
235+
236+
match compareOptions with
237+
| Globalization.CompareOptions.None when isInvariantCulture -> ValueSome StringComparison.InvariantCulture
238+
| Globalization.CompareOptions.IgnoreCase when isInvariantCulture ->
239+
ValueSome StringComparison.InvariantCultureIgnoreCase
240+
| Globalization.CompareOptions.None when isCurrentCulture -> ValueSome StringComparison.CurrentCulture
241+
| Globalization.CompareOptions.IgnoreCase when isCurrentCulture ->
242+
ValueSome StringComparison.CurrentCultureIgnoreCase
243+
| _ -> ValueNone
244+
else
245+
ValueNone
228246
| _ -> ValueNone
229247

230248
/// Gets the type from a MemberInfo (PropertyInfo or FieldInfo).

tests/FSharp.Data.GraphQL.Tests/ObjectListFilter/ObjectListFilterComparerMappingTests.fs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,9 +53,9 @@ let ``comparerToStringComparison singleton mappings are all distinct`` () =
5353

5454
// ─────────────────────────────────────────────────────────────────────────────
5555
// IsWellKnownCultureAwareComparer fallback path
56-
// StringComparer.Create produces a non-singleton comparer that is still
57-
// well-known, so it falls through the ReferenceEquals branch and hits the
58-
// IsWellKnownCultureAwareComparer fallback.
56+
// StringComparer.Create produces a non-singleton comparer; the singleton
57+
// ReferenceEquals fast path is skipped and IsWellKnownCultureAwareComparer
58+
// is used instead.
5959
// ─────────────────────────────────────────────────────────────────────────────
6060

6161
[<Fact>]

0 commit comments

Comments
 (0)