diff --git a/src/Common/Library.fs b/src/Common/Library.fs index 03308b7..471ac37 100644 --- a/src/Common/Library.fs +++ b/src/Common/Library.fs @@ -2,44 +2,45 @@ open System.Security.Cryptography -/// The types of logical operations available for JSON fields -[] -type Op = +/// The types of comparisons available for JSON fields +type Comparison = /// Equals (=) - | EQ + | Equals of obj /// Greater Than (>) - | GT + | Greater of obj /// Greater Than or Equal To (>=) - | GE + | GreaterOrEqual of obj /// Less Than (<) - | LT + | Less of obj /// Less Than or Equal To (<=) - | LE + | LessOrEqual of obj /// Not Equal to (<>) - | NE + | NotEqual of obj /// Between (BETWEEN) - | BT + | Between of obj * obj /// In (IN) - | IN + | In of obj seq // Array Contains/Exists (PostgreSQL: |? SQLite: EXISTS / json_each / IN) - //| AEX + | Contains of obj /// Exists (IS NOT NULL) - | EX + | Exists /// Does Not Exist (IS NULL) - | NEX + | NotExists - override this.ToString() = + /// Get the operator SQL for this comparison + member this.OpSql = match this with - | EQ -> "=" - | GT -> ">" - | GE -> ">=" - | LT -> "<" - | LE -> "<=" - | NE -> "<>" - | BT -> "BETWEEN" - | IN -> "IN" - | EX -> "IS NOT NULL" - | NEX -> "IS NULL" + | Equals _ -> "=" + | Greater _ -> ">" + | GreaterOrEqual _ -> ">=" + | Less _ -> "<" + | LessOrEqual _ -> "<=" + | NotEqual _ -> "<>" + | Between _ -> "BETWEEN" + | In _ -> "IN" + | Contains _ -> "|?" // PostgreSQL only; SQL needs a subquery for this + | Exists -> "IS NOT NULL" + | NotExists -> "IS NULL" /// The dialect in which a command should be rendered @@ -53,11 +54,12 @@ type Field = { /// The name of the field Name: string - /// The operation by which the field will be compared - Op: Op - - /// The value of the field - Value: obj + Comparison: Comparison + // /// The operation by which the field will be compared + // Op: Op + // + // /// The value of the field + // Value: obj /// The name of the parameter for this field ParameterName: string option @@ -66,45 +68,49 @@ type Field = { Qualifier: string option } with + /// Create a comparison against a field + static member Where name comparison = + { Name = name; Comparison = comparison; ParameterName = None; Qualifier = None } + /// Create an equals (=) field criterion static member EQ name (value: obj) = - { Name = name; Op = EQ; Value = value; ParameterName = None; Qualifier = None } + Field.Where name (Equals value) /// Create a greater than (>) field criterion static member GT name (value: obj) = - { Name = name; Op = GT; Value = value; ParameterName = None; Qualifier = None } + Field.Where name (Greater value) /// Create a greater than or equal to (>=) field criterion static member GE name (value: obj) = - { Name = name; Op = GE; Value = value; ParameterName = None; Qualifier = None } + Field.Where name (GreaterOrEqual value) /// Create a less than (<) field criterion static member LT name (value: obj) = - { Name = name; Op = LT; Value = value; ParameterName = None; Qualifier = None } + Field.Where name (Less value) /// Create a less than or equal to (<=) field criterion static member LE name (value: obj) = - { Name = name; Op = LE; Value = value; ParameterName = None; Qualifier = None } + Field.Where name (LessOrEqual value) /// Create a not equals (<>) field criterion static member NE name (value: obj) = - { Name = name; Op = NE; Value = value; ParameterName = None; Qualifier = None } + Field.Where name (NotEqual value) /// Create a BETWEEN field criterion static member BT name (min: obj) (max: obj) = - { Name = name; Op = BT; Value = [ min; max ]; ParameterName = None; Qualifier = None } + Field.Where name (Between(min, max)) /// Create an IN field criterion static member IN name (values: obj seq) = - { Name = name; Op = IN; Value = values; ParameterName = None; Qualifier = None } + Field.Where name (In values) /// Create an exists (IS NOT NULL) field criterion static member EX name = - { Name = name; Op = EX; Value = obj (); ParameterName = None; Qualifier = None } + Field.Where name Exists /// Create a not exists (IS NULL) field criterion static member NEX name = - { Name = name; Op = NEX; Value = obj (); ParameterName = None; Qualifier = None } + Field.Where name NotExists /// Transform a field name (a.b.c) to a path for the given SQL dialect static member NameToPath (name: string) dialect = @@ -118,7 +124,7 @@ type Field = { /// Create a field with a given name, but no other properties filled (op will be EQ, value will be "") static member Named name = - { Name = name; Op = EQ; Value = ""; ParameterName = None; Qualifier = None } + Field.Where name (Equals "") /// Specify the name of the parameter for this field member this.WithParameterName name = diff --git a/src/Postgres/Library.fs b/src/Postgres/Library.fs index fd37426..3dd90ac 100644 --- a/src/Postgres/Library.fs +++ b/src/Postgres/Library.fs @@ -87,25 +87,23 @@ module Parameters = fields |> Seq.map (fun it -> seq { - match it.Op with - | EX | NEX -> () - | BT -> - let p = name.Derive it.ParameterName - let values = it.Value :?> obj list - yield ($"{p}min", - parameterFor (List.head values) (fun v -> Sql.parameter (NpgsqlParameter($"{p}min", v)))) - yield ($"{p}max", - parameterFor (List.last values) (fun v -> Sql.parameter (NpgsqlParameter($"{p}max", v)))) - | IN -> + match it.Comparison with + | Exists | NotExists -> () + | Between (min, max) -> + let p = name.Derive it.ParameterName + yield ($"{p}min", parameterFor min (fun v -> Sql.parameter (NpgsqlParameter($"{p}min", v)))) + yield ($"{p}max", parameterFor max (fun v -> Sql.parameter (NpgsqlParameter($"{p}max", v)))) + | In values -> let p = name.Derive it.ParameterName yield! - it.Value :?> obj seq + values |> Seq.mapi (fun idx v -> let paramName = $"{p}_{idx}" paramName, Sql.parameter (NpgsqlParameter(paramName, v))) - | _ -> + | Contains _ -> () // TODO + | Equals v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v -> let p = name.Derive it.ParameterName - yield (p, parameterFor it.Value (fun v -> Sql.parameter (NpgsqlParameter(p, v)))) }) + yield (p, parameterFor v (fun l -> Sql.parameter (NpgsqlParameter(p, l)))) }) |> Seq.collect id |> Seq.append parameters |> Seq.toList @@ -138,21 +136,22 @@ module Query = | _ -> false fields |> Seq.map (fun it -> - match it.Op with - | EX | NEX -> $"{it.Path PostgreSQL} {it.Op}" + match it.Comparison with + | Exists | NotExists -> $"{it.Path PostgreSQL} {it.Comparison.OpSql}" | _ -> let p = name.Derive it.ParameterName let param, value = - match it.Op with - | BT -> $"{p}min AND {p}max", (it.Value :?> obj list)[0] - | IN -> - let values = it.Value :?> obj seq + match it.Comparison with + | Between (min, _) -> $"{p}min AND {p}max", min + | In values -> let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", " $"({paramNames})", defaultArg (Seq.tryHead values) (obj ()) - | _ -> p, it.Value + | Contains _ -> p, "" // TODO: may need to use -> vs ->> in field SQL + | Equals v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v -> p, v + | _ -> p, "" if isNumeric value then - $"({it.Path PostgreSQL})::numeric {it.Op} {param}" - else $"{it.Path PostgreSQL} {it.Op} {param}") + $"({it.Path PostgreSQL})::numeric {it.Comparison.OpSql} {param}" + else $"{it.Path PostgreSQL} {it.Comparison.OpSql} {param}") |> String.concat $" {howMatched} " /// Create a WHERE clause fragment to implement an ID-based query diff --git a/src/Sqlite/Library.fs b/src/Sqlite/Library.fs index 4458ccb..a965110 100644 --- a/src/Sqlite/Library.fs +++ b/src/Sqlite/Library.fs @@ -37,16 +37,17 @@ module Query = let name = ParameterName() fields |> Seq.map (fun it -> - match it.Op with - | EX | NEX -> $"{it.Path SQLite} {it.Op}" - | BT -> + match it.Comparison with + | Exists | NotExists -> $"{it.Path SQLite} {it.Comparison.OpSql}" + | Between _ -> let p = name.Derive it.ParameterName - $"{it.Path SQLite} {it.Op} {p}min AND {p}max" - | IN -> + $"{it.Path SQLite} {it.Comparison.OpSql} {p}min AND {p}max" + | In values -> let p = name.Derive it.ParameterName - let paramNames = it.Value :?> obj seq |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", " - $"{it.Path SQLite} {it.Op} ({paramNames})" - | _ -> $"{it.Path SQLite} {it.Op} {name.Derive it.ParameterName}") + let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", " + $"{it.Path SQLite} {it.Comparison.OpSql} ({paramNames})" + | Contains _ -> "" // TODO + | _ -> $"{it.Path SQLite} {it.Comparison.OpSql} {name.Derive it.ParameterName}") |> String.concat $" {howMatched} " /// Create a WHERE clause fragment to implement an ID-based query @@ -107,17 +108,17 @@ module Parameters = fields |> Seq.map (fun it -> seq { - match it.Op with - | EX | NEX -> () - | BT -> - let p = name.Derive it.ParameterName - let values = it.Value :?> obj list - yield SqliteParameter($"{p}min", List.head values) - yield SqliteParameter($"{p}max", List.last values) - | IN -> + match it.Comparison with + | Exists | NotExists -> () + | Between (min, max) -> let p = name.Derive it.ParameterName - yield! it.Value :?> obj seq |> Seq.mapi (fun idx v -> SqliteParameter($"{p}_{idx}", v)) - | _ -> yield SqliteParameter(name.Derive it.ParameterName, it.Value) }) + yield! [ SqliteParameter($"{p}min", min); SqliteParameter($"{p}max", max) ] + | In values -> + let p = name.Derive it.ParameterName + yield! values |> Seq.mapi (fun idx v -> SqliteParameter($"{p}_{idx}", v)) + | Contains _ -> () // TODO + | Equals v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v -> + yield SqliteParameter(name.Derive it.ParameterName, v) }) |> Seq.collect id |> Seq.append parameters |> Seq.toList diff --git a/src/Tests.CSharp/CommonCSharpTests.cs b/src/Tests.CSharp/CommonCSharpTests.cs index 0e33791..3a68f85 100644 --- a/src/Tests.CSharp/CommonCSharpTests.cs +++ b/src/Tests.CSharp/CommonCSharpTests.cs @@ -1,6 +1,5 @@ using Expecto.CSharp; using Expecto; -using Microsoft.FSharp.Collections; using Microsoft.FSharp.Core; namespace BitBadger.Documents.Tests.CSharp; @@ -22,45 +21,53 @@ internal class TestSerializer : IDocumentSerializer public static class CommonCSharpTests { /// - /// Unit tests for the Op enum + /// Unit tests for the OpSql property of the Comparison discriminated union /// - private static readonly Test OpTests = TestList("Op", + private static readonly Test OpTests = TestList("Comparison.OpSql", [ - TestCase("EQ succeeds", () => + TestCase("Equals succeeds", () => { - Expect.equal(Op.EQ.ToString(), "=", "The equals operator was not correct"); + Expect.equal(Comparison.NewEquals("").OpSql, "=", "The Equals SQL was not correct"); }), - TestCase("GT succeeds", () => + TestCase("Greater succeeds", () => { - Expect.equal(Op.GT.ToString(), ">", "The greater than operator was not correct"); + Expect.equal(Comparison.NewGreater("").OpSql, ">", "The Greater SQL was not correct"); }), - TestCase("GE succeeds", () => + TestCase("GreaterOrEqual succeeds", () => { - Expect.equal(Op.GE.ToString(), ">=", "The greater than or equal to operator was not correct"); + Expect.equal(Comparison.NewGreaterOrEqual("").OpSql, ">=", "The GreaterOrEqual SQL was not correct"); }), - TestCase("LT succeeds", () => + TestCase("Less succeeds", () => { - Expect.equal(Op.LT.ToString(), "<", "The less than operator was not correct"); + Expect.equal(Comparison.NewLess("").OpSql, "<", "The Less SQL was not correct"); }), - TestCase("LE succeeds", () => + TestCase("LessOrEqual succeeds", () => { - Expect.equal(Op.LE.ToString(), "<=", "The less than or equal to operator was not correct"); + Expect.equal(Comparison.NewLessOrEqual("").OpSql, "<=", "The LessOrEqual SQL was not correct"); }), - TestCase("NE succeeds", () => + TestCase("NotEqual succeeds", () => { - Expect.equal(Op.NE.ToString(), "<>", "The not equal to operator was not correct"); + Expect.equal(Comparison.NewNotEqual("").OpSql, "<>", "The NotEqual SQL was not correct"); }), - TestCase("BT succeeds", () => + TestCase("Between succeeds", () => { - Expect.equal(Op.BT.ToString(), "BETWEEN", "The \"between\" operator was not correct"); + Expect.equal(Comparison.NewBetween("", "").OpSql, "BETWEEN", "The Between SQL was not correct"); }), - TestCase("EX succeeds", () => + TestCase("In succeeds", () => { - Expect.equal(Op.EX.ToString(), "IS NOT NULL", "The \"exists\" operator was not correct"); + Expect.equal(Comparison.NewIn([]).OpSql, "IN", "The In SQL was not correct"); }), - TestCase("NEX succeeds", () => + TestCase("Contains succeeds", () => { - Expect.equal(Op.NEX.ToString(), "IS NULL", "The \"not exists\" operator was not correct"); + Expect.equal(Comparison.NewContains("").OpSql, "|?", "The Contains SQL was not correct"); + }), + TestCase("Exists succeeds", () => + { + Expect.equal(Comparison.Exists.OpSql, "IS NOT NULL", "The Exists SQL was not correct"); + }), + TestCase("NotExists succeeds", () => + { + Expect.equal(Comparison.NotExists.OpSql, "IS NULL", "The NotExists SQL was not correct"); }) ]); @@ -73,62 +80,62 @@ public static class CommonCSharpTests { var field = Field.EQ("Test", 14); Expect.equal(field.Name, "Test", "Field name incorrect"); - Expect.equal(field.Op, Op.EQ, "Operator incorrect"); - Expect.equal(field.Value, 14, "Value incorrect"); + Expect.equal(field.Comparison, Comparison.NewEquals(14), "Comparison incorrect"); }), TestCase("GT succeeds", () => { var field = Field.GT("Great", "night"); Expect.equal(field.Name, "Great", "Field name incorrect"); - Expect.equal(field.Op, Op.GT, "Operator incorrect"); - Expect.equal(field.Value, "night", "Value incorrect"); + Expect.equal(field.Comparison, Comparison.NewGreater("night"), "Comparison incorrect"); }), TestCase("GE succeeds", () => { var field = Field.GE("Nice", 88L); Expect.equal(field.Name, "Nice", "Field name incorrect"); - Expect.equal(field.Op, Op.GE, "Operator incorrect"); - Expect.equal(field.Value, 88L, "Value incorrect"); + Expect.equal(field.Comparison, Comparison.NewGreaterOrEqual(88L), "Comparison incorrect"); }), TestCase("LT succeeds", () => { var field = Field.LT("Lesser", "seven"); Expect.equal(field.Name, "Lesser", "Field name incorrect"); - Expect.equal(field.Op, Op.LT, "Operator incorrect"); - Expect.equal(field.Value, "seven", "Value incorrect"); + Expect.equal(field.Comparison, Comparison.NewLess("seven"), "Comparison incorrect"); }), TestCase("LE succeeds", () => { var field = Field.LE("Nobody", "KNOWS"); Expect.equal(field.Name, "Nobody", "Field name incorrect"); - Expect.equal(field.Op, Op.LE, "Operator incorrect"); - Expect.equal(field.Value, "KNOWS", "Value incorrect"); + Expect.equal(field.Comparison, Comparison.NewLessOrEqual("KNOWS"), "Comparison incorrect"); }), TestCase("NE succeeds", () => { var field = Field.NE("Park", "here"); Expect.equal(field.Name, "Park", "Field name incorrect"); - Expect.equal(field.Op, Op.NE, "Operator incorrect"); - Expect.equal(field.Value, "here", "Value incorrect"); + Expect.equal(field.Comparison, Comparison.NewNotEqual("here"), "Comparison incorrect"); }), TestCase("BT succeeds", () => { var field = Field.BT("Age", 18, 49); Expect.equal(field.Name, "Age", "Field name incorrect"); - Expect.equal(field.Op, Op.BT, "Operator incorrect"); - Expect.equal(((FSharpList)field.Value).ToArray(), [18, 49], "Value incorrect"); + Expect.equal(field.Comparison, Comparison.NewBetween(18, 49), "Comparison incorrect"); + }), + TestCase("IN succeeds", () => + { + var field = Field.IN("Here", [8, 16, 32]); + Expect.equal(field.Name, "Here", "Field name incorrect"); + Expect.isTrue(field.Comparison.IsIn, "Comparison incorrect"); + Expect.sequenceEqual(((Comparison.In)field.Comparison).Item, [8, 16, 32], "Value incorrect"); }), TestCase("EX succeeds", () => { var field = Field.EX("Groovy"); Expect.equal(field.Name, "Groovy", "Field name incorrect"); - Expect.equal(field.Op, Op.EX, "Operator incorrect"); + Expect.isTrue(field.Comparison.IsExists, "Comparison incorrect"); }), TestCase("NEX succeeds", () => { var field = Field.NEX("Rad"); Expect.equal(field.Name, "Rad", "Field name incorrect"); - Expect.equal(field.Op, Op.NEX, "Operator incorrect"); + Expect.isTrue(field.Comparison.IsNotExists, "Comparison incorrect"); }), TestList("NameToPath", [ diff --git a/src/Tests/CommonTests.fs b/src/Tests/CommonTests.fs index 5718789..f3f73ad 100644 --- a/src/Tests/CommonTests.fs +++ b/src/Tests/CommonTests.fs @@ -7,33 +7,39 @@ open Expecto let tbl = "test_table" /// Unit tests for the Op DU -let opTests = testList "Op" [ - test "EQ succeeds" { - Expect.equal (string EQ) "=" "The equals operator was not correct" +let comparisonTests = testList "Comparison.OpSql" [ + test "Equals succeeds" { + Expect.equal (Equals "").OpSql "=" "The Equals SQL was not correct" } - test "GT succeeds" { - Expect.equal (string GT) ">" "The greater than operator was not correct" + test "Greater succeeds" { + Expect.equal (Greater "").OpSql ">" "The Greater SQL was not correct" } - test "GE succeeds" { - Expect.equal (string GE) ">=" "The greater than or equal to operator was not correct" + test "GreaterOrEqual succeeds" { + Expect.equal (GreaterOrEqual "").OpSql ">=" "The GreaterOrEqual SQL was not correct" } - test "LT succeeds" { - Expect.equal (string LT) "<" "The less than operator was not correct" + test "Less succeeds" { + Expect.equal (Less "").OpSql "<" "The Less SQL was not correct" } - test "LE succeeds" { - Expect.equal (string LE) "<=" "The less than or equal to operator was not correct" + test "LessOrEqual succeeds" { + Expect.equal (LessOrEqual "").OpSql "<=" "The LessOrEqual SQL was not correct" } - test "NE succeeds" { - Expect.equal (string NE) "<>" "The not equal to operator was not correct" + test "NotEqual succeeds" { + Expect.equal (NotEqual "").OpSql "<>" "The NotEqual SQL was not correct" } - test "BT succeeds" { - Expect.equal (string BT) "BETWEEN" """The "between" operator was not correct""" + test "Between succeeds" { + Expect.equal (Between("", "")).OpSql "BETWEEN" "The Between SQL was not correct" } - test "EX succeeds" { - Expect.equal (string EX) "IS NOT NULL" """The "exists" operator was not correct""" + test "In succeeds" { + Expect.equal (In []).OpSql "IN" "The In SQL was not correct" } - test "NEX succeeds" { - Expect.equal (string NEX) "IS NULL" """The "not exists" operator was not correct""" + test "Contains succeeds" { + Expect.equal (Contains "").OpSql "|?" "The Contains SQL was not correct" + } + test "Exists succeeds" { + Expect.equal Exists.OpSql "IS NOT NULL" "The Exists SQL was not correct" + } + test "NotExists succeeds" { + Expect.equal NotExists.OpSql "IS NULL" "The NotExists SQL was not correct" } ] @@ -42,70 +48,70 @@ let fieldTests = testList "Field" [ test "EQ succeeds" { let field = Field.EQ "Test" 14 Expect.equal field.Name "Test" "Field name incorrect" - Expect.equal field.Op EQ "Operator incorrect" - Expect.equal field.Value 14 "Value incorrect" + Expect.equal field.Comparison (Equals 14) "Comparison incorrect" Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.Qualifier "The default table qualifier should be None" } test "GT succeeds" { let field = Field.GT "Great" "night" Expect.equal field.Name "Great" "Field name incorrect" - Expect.equal field.Op GT "Operator incorrect" - Expect.equal field.Value "night" "Value incorrect" + Expect.equal field.Comparison (Greater "night") "Comparison incorrect" Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.Qualifier "The default table qualifier should be None" } test "GE succeeds" { let field = Field.GE "Nice" 88L Expect.equal field.Name "Nice" "Field name incorrect" - Expect.equal field.Op GE "Operator incorrect" - Expect.equal field.Value 88L "Value incorrect" + Expect.equal field.Comparison (GreaterOrEqual 88L) "Comparison incorrect" Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.Qualifier "The default table qualifier should be None" } test "LT succeeds" { let field = Field.LT "Lesser" "seven" Expect.equal field.Name "Lesser" "Field name incorrect" - Expect.equal field.Op LT "Operator incorrect" - Expect.equal field.Value "seven" "Value incorrect" + Expect.equal field.Comparison (Less "seven") "Comparison incorrect" Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.Qualifier "The default table qualifier should be None" } test "LE succeeds" { let field = Field.LE "Nobody" "KNOWS"; Expect.equal field.Name "Nobody" "Field name incorrect" - Expect.equal field.Op LE "Operator incorrect" - Expect.equal field.Value "KNOWS" "Value incorrect" + Expect.equal field.Comparison (LessOrEqual "KNOWS") "Comparison incorrect" Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.Qualifier "The default table qualifier should be None" } test "NE succeeds" { let field = Field.NE "Park" "here" Expect.equal field.Name "Park" "Field name incorrect" - Expect.equal field.Op NE "Operator incorrect" - Expect.equal field.Value "here" "Value incorrect" + Expect.equal field.Comparison (NotEqual "here") "Comparison incorrect" Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.Qualifier "The default table qualifier should be None" } test "BT succeeds" { let field = Field.BT "Age" 18 49 Expect.equal field.Name "Age" "Field name incorrect" - Expect.equal field.Op BT "Operator incorrect" - Expect.sequenceEqual (field.Value :?> obj list) [ 18; 49 ] "Value incorrect" + Expect.equal field.Comparison (Between(18, 49)) "Comparison incorrect" + Expect.isNone field.ParameterName "The default parameter name should be None" + Expect.isNone field.Qualifier "The default table qualifier should be None" + } + 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" Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.Qualifier "The default table qualifier should be None" } test "EX succeeds" { let field = Field.EX "Groovy" Expect.equal field.Name "Groovy" "Field name incorrect" - Expect.equal field.Op EX "Operator incorrect" + Expect.equal field.Comparison Exists "Comparison incorrect" Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.Qualifier "The default table qualifier should be None" } test "NEX succeeds" { let field = Field.NEX "Rad" Expect.equal field.Name "Rad" "Field name incorrect" - Expect.equal field.Op NEX "Operator incorrect" + Expect.equal field.Comparison NotExists "Comparison incorrect" Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.Qualifier "The default table qualifier should be None" } @@ -467,7 +473,7 @@ let queryTests = testList "Query" [ /// Tests which do not hit the database let all = testList "Common" [ - opTests + comparisonTests fieldTests fieldMatchTests parameterNameTests