From 740767661cb0ebabb715b3f4ab1919b518751243 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Wed, 18 Sep 2024 13:36:14 +0000 Subject: [PATCH] Make Field constructor functions generic (#8) F# can upcast types to `obj` if those types are used in place. However, a `string seq` (`IEnumerable` in C#) cannot be upcast to an `obj seq` (`IEnumerable`) without mapping each item in the sequence. Making the `Field` constructor functions generic will allow them to take any object type, and these functions handle the conversion to `obj` (for `In` and `InArray`; others work transparently). Reviewed-on: https://git.bitbadger.solutions/bit-badger/BitBadger.Documents/pulls/8 --- src/Common/Library.fs | 40 +++++++++++++++++++-------------------- src/Directory.Build.props | 13 +++++++++++-- src/Tests/CommonTests.fs | 10 ++++++++-- 3 files changed, 39 insertions(+), 24 deletions(-) diff --git a/src/Common/Library.fs b/src/Common/Library.fs index 6853457..83053be 100644 --- a/src/Common/Library.fs +++ b/src/Common/Library.fs @@ -75,68 +75,68 @@ type Field = with /// Create a comparison against a field - static member Where name comparison = + static member Where name (comparison: Comparison) = { Name = name; Comparison = comparison; ParameterName = None; Qualifier = None } /// Create an equals (=) field criterion - static member Equal name (value: obj) = + static member Equal<'T> name (value: 'T) = Field.Where name (Equal value) /// Create an equals (=) field criterion (alias) - static member EQ name (value: obj) = Field.Equal name value + static member EQ<'T> name (value: 'T) = Field.Equal name value /// Create a greater than (>) field criterion - static member Greater name (value: obj) = + static member Greater<'T> name (value: 'T) = Field.Where name (Greater value) /// Create a greater than (>) field criterion (alias) - static member GT name (value: obj) = Field.Greater name value + static member GT<'T> name (value: 'T) = Field.Greater name value /// Create a greater than or equal to (>=) field criterion - static member GreaterOrEqual name (value: obj) = + static member GreaterOrEqual<'T> name (value: 'T) = Field.Where name (GreaterOrEqual value) /// Create a greater than or equal to (>=) field criterion (alias) - static member GE name (value: obj) = Field.GreaterOrEqual name value + static member GE<'T> name (value: 'T) = Field.GreaterOrEqual name value /// Create a less than (<) field criterion - static member Less name (value: obj) = + static member Less<'T> name (value: 'T) = Field.Where name (Less value) /// Create a less than (<) field criterion (alias) - static member LT name (value: obj) = Field.Less name value + static member LT<'T> name (value: 'T) = Field.Less name value /// Create a less than or equal to (<=) field criterion - static member LessOrEqual name (value: obj) = + static member LessOrEqual<'T> name (value: 'T) = Field.Where name (LessOrEqual value) /// Create a less than or equal to (<=) field criterion (alias) - static member LE name (value: obj) = Field.LessOrEqual name value + static member LE<'T> name (value: 'T) = Field.LessOrEqual name value /// Create a not equals (<>) field criterion - static member NotEqual name (value: obj) = + static member NotEqual<'T> name (value: 'T) = Field.Where name (NotEqual value) /// Create a not equals (<>) field criterion (alias) - static member NE name (value: obj) = Field.NotEqual name value + static member NE<'T> name (value: 'T) = Field.NotEqual name value /// Create a Between field criterion - static member Between name (min: obj) (max: obj) = + static member Between<'T> name (min: 'T) (max: 'T) = Field.Where name (Between(min, max)) /// Create a Between field criterion (alias) - static member BT name (min: obj) (max: obj) = Field.Between name min max + static member BT<'T> name (min: 'T) (max: 'T) = Field.Between name min max /// Create an In field criterion - static member In name (values: obj seq) = - Field.Where name (In values) + static member In<'T> name (values: 'T seq) = + Field.Where name (In (Seq.map box values)) /// Create an In field criterion (alias) - static member IN name (values: obj seq) = Field.In name values + static member IN<'T> name (values: 'T seq) = Field.In name values /// Create an InArray field criterion - static member InArray name tableName (values: obj seq) = - Field.Where name (InArray(tableName, values)) + static member InArray<'T> name tableName (values: 'T seq) = + Field.Where name (InArray(tableName, Seq.map box values)) /// Create an exists (IS NOT NULL) field criterion static member Exists name = diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 1a956d9..425a298 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -6,8 +6,17 @@ 4.0.0.0 4.0.0.0 4.0.0 - rc4 - From rc3: Add In/InArray field comparisons, revamp internal comparison handling. From rc2: preserve additional ORDER BY qualifiers. From rc1: add case-insensitive ordering. From v3.1: Change ByField to ByFields; support dot-access to nested document fields; add Find*Ordered functions/methods; see project site for breaking changes and compatibility + rc5 + From v3.1: (see project site for breaking changes and compatibility) +- Change ByField to ByFields +- Support dot-access to nested document fields +- Add Find*Ordered functions/methods + +Release Candidate Changes: +- from v4-rc4: Field construction functions are now generic. +- from v4-rc3: Add In/InArray field comparisons, revamp internal comparison handling. +- from v4-rc2: preserve additional ORDER BY qualifiers. +- from v4-rc1: add case-insensitive ordering. danieljsummers Bit Badger Solutions README.md diff --git a/src/Tests/CommonTests.fs b/src/Tests/CommonTests.fs index 95b4f2d..98f6fe8 100644 --- a/src/Tests/CommonTests.fs +++ b/src/Tests/CommonTests.fs @@ -97,14 +97,20 @@ let fieldTests = testList "Field" [ test "In succeeds" { let field = Field.In "Here" [| 8; 16; 32 |] Expect.equal field.Name "Here" "Field name incorrect" - Expect.equal field.Comparison (In [| 8; 16; 32 |]) "Comparison incorrect" + match field.Comparison with + | In values -> Expect.equal (List.ofSeq values) [ box 8; box 16; box 32 ] "Comparison incorrect" + | it -> Expect.isTrue false $"Expected In, received %A{it}" Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.Qualifier "The default table qualifier should be None" } test "InArray succeeds" { let field = Field.InArray "ArrayField" "table" [| "z" |] Expect.equal field.Name "ArrayField" "Field name incorrect" - Expect.equal field.Comparison (InArray("table", [| "z" |])) "Comparison incorrect" + match field.Comparison with + | InArray (table, values) -> + Expect.equal table "table" "Comparison table incorrect" + Expect.equal (List.ofSeq values) [ box "z" ] "Comparison values incorrect" + | it -> Expect.isTrue false $"Expected InArray, received %A{it}" Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.Qualifier "The default table qualifier should be None" }