Change Op to Comparison DU

This commit is contained in:
Daniel J. Summers 2024-09-15 17:45:52 -04:00
parent 14c80f32fe
commit b07ae3f097
5 changed files with 173 additions and 154 deletions

View File

@ -2,44 +2,45 @@
open System.Security.Cryptography open System.Security.Cryptography
/// The types of logical operations available for JSON fields /// The types of comparisons available for JSON fields
[<Struct>] type Comparison =
type Op =
/// Equals (=) /// Equals (=)
| EQ | Equals of obj
/// Greater Than (>) /// Greater Than (>)
| GT | Greater of obj
/// Greater Than or Equal To (>=) /// Greater Than or Equal To (>=)
| GE | GreaterOrEqual of obj
/// Less Than (<) /// Less Than (<)
| LT | Less of obj
/// Less Than or Equal To (<=) /// Less Than or Equal To (<=)
| LE | LessOrEqual of obj
/// Not Equal to (<>) /// Not Equal to (<>)
| NE | NotEqual of obj
/// Between (BETWEEN) /// Between (BETWEEN)
| BT | Between of obj * obj
/// In (IN) /// In (IN)
| IN | In of obj seq
// Array Contains/Exists (PostgreSQL: |? SQLite: EXISTS / json_each / IN) // Array Contains/Exists (PostgreSQL: |? SQLite: EXISTS / json_each / IN)
//| AEX | Contains of obj
/// Exists (IS NOT NULL) /// Exists (IS NOT NULL)
| EX | Exists
/// Does Not Exist (IS NULL) /// Does Not Exist (IS NULL)
| NEX | NotExists
override this.ToString() = /// Get the operator SQL for this comparison
member this.OpSql =
match this with match this with
| EQ -> "=" | Equals _ -> "="
| GT -> ">" | Greater _ -> ">"
| GE -> ">=" | GreaterOrEqual _ -> ">="
| LT -> "<" | Less _ -> "<"
| LE -> "<=" | LessOrEqual _ -> "<="
| NE -> "<>" | NotEqual _ -> "<>"
| BT -> "BETWEEN" | Between _ -> "BETWEEN"
| IN -> "IN" | In _ -> "IN"
| EX -> "IS NOT NULL" | Contains _ -> "|?" // PostgreSQL only; SQL needs a subquery for this
| NEX -> "IS NULL" | Exists -> "IS NOT NULL"
| NotExists -> "IS NULL"
/// The dialect in which a command should be rendered /// The dialect in which a command should be rendered
@ -53,11 +54,12 @@ type Field = {
/// The name of the field /// The name of the field
Name: string Name: string
/// The operation by which the field will be compared Comparison: Comparison
Op: Op // /// The operation by which the field will be compared
// Op: Op
/// The value of the field //
Value: obj // /// The value of the field
// Value: obj
/// The name of the parameter for this field /// The name of the parameter for this field
ParameterName: string option ParameterName: string option
@ -66,45 +68,49 @@ type Field = {
Qualifier: string option Qualifier: string option
} with } 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 /// Create an equals (=) field criterion
static member EQ name (value: obj) = 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 /// Create a greater than (>) field criterion
static member GT name (value: obj) = 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 /// Create a greater than or equal to (>=) field criterion
static member GE name (value: obj) = 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 /// Create a less than (<) field criterion
static member LT name (value: obj) = 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 /// Create a less than or equal to (<=) field criterion
static member LE name (value: obj) = 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 /// Create a not equals (<>) field criterion
static member NE name (value: obj) = 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 /// Create a BETWEEN field criterion
static member BT name (min: obj) (max: obj) = 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 /// Create an IN field criterion
static member IN name (values: obj seq) = 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 /// Create an exists (IS NOT NULL) field criterion
static member EX name = 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 /// Create a not exists (IS NULL) field criterion
static member NEX name = 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 /// Transform a field name (a.b.c) to a path for the given SQL dialect
static member NameToPath (name: string) 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 "") /// Create a field with a given name, but no other properties filled (op will be EQ, value will be "")
static member Named name = 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 /// Specify the name of the parameter for this field
member this.WithParameterName name = member this.WithParameterName name =

View File

@ -87,25 +87,23 @@ module Parameters =
fields fields
|> Seq.map (fun it -> |> Seq.map (fun it ->
seq { seq {
match it.Op with match it.Comparison with
| EX | NEX -> () | Exists | NotExists -> ()
| BT -> | Between (min, max) ->
let p = name.Derive it.ParameterName let p = name.Derive it.ParameterName
let values = it.Value :?> obj list yield ($"{p}min", parameterFor min (fun v -> Sql.parameter (NpgsqlParameter($"{p}min", v))))
yield ($"{p}min", yield ($"{p}max", parameterFor max (fun v -> Sql.parameter (NpgsqlParameter($"{p}max", v))))
parameterFor (List.head values) (fun v -> Sql.parameter (NpgsqlParameter($"{p}min", v)))) | In values ->
yield ($"{p}max",
parameterFor (List.last values) (fun v -> Sql.parameter (NpgsqlParameter($"{p}max", v))))
| IN ->
let p = name.Derive it.ParameterName let p = name.Derive it.ParameterName
yield! yield!
it.Value :?> obj seq values
|> Seq.mapi (fun idx v -> |> Seq.mapi (fun idx v ->
let paramName = $"{p}_{idx}" let paramName = $"{p}_{idx}"
paramName, Sql.parameter (NpgsqlParameter(paramName, v))) 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 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.collect id
|> Seq.append parameters |> Seq.append parameters
|> Seq.toList |> Seq.toList
@ -138,21 +136,22 @@ module Query =
| _ -> false | _ -> false
fields fields
|> Seq.map (fun it -> |> Seq.map (fun it ->
match it.Op with match it.Comparison with
| EX | NEX -> $"{it.Path PostgreSQL} {it.Op}" | Exists | NotExists -> $"{it.Path PostgreSQL} {it.Comparison.OpSql}"
| _ -> | _ ->
let p = name.Derive it.ParameterName let p = name.Derive it.ParameterName
let param, value = let param, value =
match it.Op with match it.Comparison with
| BT -> $"{p}min AND {p}max", (it.Value :?> obj list)[0] | Between (min, _) -> $"{p}min AND {p}max", min
| IN -> | In values ->
let values = it.Value :?> obj seq
let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", " let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", "
$"({paramNames})", defaultArg (Seq.tryHead values) (obj ()) $"({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 if isNumeric value then
$"({it.Path PostgreSQL})::numeric {it.Op} {param}" $"({it.Path PostgreSQL})::numeric {it.Comparison.OpSql} {param}"
else $"{it.Path PostgreSQL} {it.Op} {param}") else $"{it.Path PostgreSQL} {it.Comparison.OpSql} {param}")
|> String.concat $" {howMatched} " |> String.concat $" {howMatched} "
/// Create a WHERE clause fragment to implement an ID-based query /// Create a WHERE clause fragment to implement an ID-based query

View File

@ -37,16 +37,17 @@ module Query =
let name = ParameterName() let name = ParameterName()
fields fields
|> Seq.map (fun it -> |> Seq.map (fun it ->
match it.Op with match it.Comparison with
| EX | NEX -> $"{it.Path SQLite} {it.Op}" | Exists | NotExists -> $"{it.Path SQLite} {it.Comparison.OpSql}"
| BT -> | Between _ ->
let p = name.Derive it.ParameterName let p = name.Derive it.ParameterName
$"{it.Path SQLite} {it.Op} {p}min AND {p}max" $"{it.Path SQLite} {it.Comparison.OpSql} {p}min AND {p}max"
| IN -> | In values ->
let p = name.Derive it.ParameterName let p = name.Derive it.ParameterName
let paramNames = it.Value :?> obj seq |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", " let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", "
$"{it.Path SQLite} {it.Op} ({paramNames})" $"{it.Path SQLite} {it.Comparison.OpSql} ({paramNames})"
| _ -> $"{it.Path SQLite} {it.Op} {name.Derive it.ParameterName}") | Contains _ -> "" // TODO
| _ -> $"{it.Path SQLite} {it.Comparison.OpSql} {name.Derive it.ParameterName}")
|> String.concat $" {howMatched} " |> String.concat $" {howMatched} "
/// Create a WHERE clause fragment to implement an ID-based query /// Create a WHERE clause fragment to implement an ID-based query
@ -107,17 +108,17 @@ module Parameters =
fields fields
|> Seq.map (fun it -> |> Seq.map (fun it ->
seq { seq {
match it.Op with match it.Comparison with
| EX | NEX -> () | Exists | NotExists -> ()
| BT -> | Between (min, max) ->
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 ->
let p = name.Derive it.ParameterName let p = name.Derive it.ParameterName
yield! it.Value :?> obj seq |> Seq.mapi (fun idx v -> SqliteParameter($"{p}_{idx}", v)) yield! [ SqliteParameter($"{p}min", min); SqliteParameter($"{p}max", max) ]
| _ -> yield SqliteParameter(name.Derive it.ParameterName, it.Value) }) | 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.collect id
|> Seq.append parameters |> Seq.append parameters
|> Seq.toList |> Seq.toList

View File

@ -1,6 +1,5 @@
using Expecto.CSharp; using Expecto.CSharp;
using Expecto; using Expecto;
using Microsoft.FSharp.Collections;
using Microsoft.FSharp.Core; using Microsoft.FSharp.Core;
namespace BitBadger.Documents.Tests.CSharp; namespace BitBadger.Documents.Tests.CSharp;
@ -22,45 +21,53 @@ internal class TestSerializer : IDocumentSerializer
public static class CommonCSharpTests public static class CommonCSharpTests
{ {
/// <summary> /// <summary>
/// Unit tests for the Op enum /// Unit tests for the OpSql property of the Comparison discriminated union
/// </summary> /// </summary>
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); var field = Field.EQ("Test", 14);
Expect.equal(field.Name, "Test", "Field name incorrect"); Expect.equal(field.Name, "Test", "Field name incorrect");
Expect.equal(field.Op, Op.EQ, "Operator incorrect"); Expect.equal(field.Comparison, Comparison.NewEquals(14), "Comparison incorrect");
Expect.equal(field.Value, 14, "Value incorrect");
}), }),
TestCase("GT succeeds", () => TestCase("GT succeeds", () =>
{ {
var field = Field.GT("Great", "night"); var field = Field.GT("Great", "night");
Expect.equal(field.Name, "Great", "Field name incorrect"); Expect.equal(field.Name, "Great", "Field name incorrect");
Expect.equal(field.Op, Op.GT, "Operator incorrect"); Expect.equal(field.Comparison, Comparison.NewGreater("night"), "Comparison incorrect");
Expect.equal(field.Value, "night", "Value incorrect");
}), }),
TestCase("GE succeeds", () => TestCase("GE succeeds", () =>
{ {
var field = Field.GE("Nice", 88L); var field = Field.GE("Nice", 88L);
Expect.equal(field.Name, "Nice", "Field name incorrect"); Expect.equal(field.Name, "Nice", "Field name incorrect");
Expect.equal(field.Op, Op.GE, "Operator incorrect"); Expect.equal(field.Comparison, Comparison.NewGreaterOrEqual(88L), "Comparison incorrect");
Expect.equal(field.Value, 88L, "Value incorrect");
}), }),
TestCase("LT succeeds", () => TestCase("LT succeeds", () =>
{ {
var field = Field.LT("Lesser", "seven"); var field = Field.LT("Lesser", "seven");
Expect.equal(field.Name, "Lesser", "Field name incorrect"); Expect.equal(field.Name, "Lesser", "Field name incorrect");
Expect.equal(field.Op, Op.LT, "Operator incorrect"); Expect.equal(field.Comparison, Comparison.NewLess("seven"), "Comparison incorrect");
Expect.equal(field.Value, "seven", "Value incorrect");
}), }),
TestCase("LE succeeds", () => TestCase("LE succeeds", () =>
{ {
var field = Field.LE("Nobody", "KNOWS"); var field = Field.LE("Nobody", "KNOWS");
Expect.equal(field.Name, "Nobody", "Field name incorrect"); Expect.equal(field.Name, "Nobody", "Field name incorrect");
Expect.equal(field.Op, Op.LE, "Operator incorrect"); Expect.equal(field.Comparison, Comparison.NewLessOrEqual("KNOWS"), "Comparison incorrect");
Expect.equal(field.Value, "KNOWS", "Value incorrect");
}), }),
TestCase("NE succeeds", () => TestCase("NE succeeds", () =>
{ {
var field = Field.NE("Park", "here"); var field = Field.NE("Park", "here");
Expect.equal(field.Name, "Park", "Field name incorrect"); Expect.equal(field.Name, "Park", "Field name incorrect");
Expect.equal(field.Op, Op.NE, "Operator incorrect"); Expect.equal(field.Comparison, Comparison.NewNotEqual("here"), "Comparison incorrect");
Expect.equal(field.Value, "here", "Value incorrect");
}), }),
TestCase("BT succeeds", () => TestCase("BT succeeds", () =>
{ {
var field = Field.BT("Age", 18, 49); var field = Field.BT("Age", 18, 49);
Expect.equal(field.Name, "Age", "Field name incorrect"); Expect.equal(field.Name, "Age", "Field name incorrect");
Expect.equal(field.Op, Op.BT, "Operator incorrect"); Expect.equal(field.Comparison, Comparison.NewBetween(18, 49), "Comparison incorrect");
Expect.equal(((FSharpList<object>)field.Value).ToArray(), [18, 49], "Value 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", () => TestCase("EX succeeds", () =>
{ {
var field = Field.EX("Groovy"); var field = Field.EX("Groovy");
Expect.equal(field.Name, "Groovy", "Field name incorrect"); 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", () => TestCase("NEX succeeds", () =>
{ {
var field = Field.NEX("Rad"); var field = Field.NEX("Rad");
Expect.equal(field.Name, "Rad", "Field name incorrect"); 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", TestList("NameToPath",
[ [

View File

@ -7,33 +7,39 @@ open Expecto
let tbl = "test_table" let tbl = "test_table"
/// Unit tests for the Op DU /// Unit tests for the Op DU
let opTests = testList "Op" [ let comparisonTests = testList "Comparison.OpSql" [
test "EQ succeeds" { test "Equals succeeds" {
Expect.equal (string EQ) "=" "The equals operator was not correct" Expect.equal (Equals "").OpSql "=" "The Equals SQL was not correct"
} }
test "GT succeeds" { test "Greater succeeds" {
Expect.equal (string GT) ">" "The greater than operator was not correct" Expect.equal (Greater "").OpSql ">" "The Greater SQL was not correct"
} }
test "GE succeeds" { test "GreaterOrEqual succeeds" {
Expect.equal (string GE) ">=" "The greater than or equal to operator was not correct" Expect.equal (GreaterOrEqual "").OpSql ">=" "The GreaterOrEqual SQL was not correct"
} }
test "LT succeeds" { test "Less succeeds" {
Expect.equal (string LT) "<" "The less than operator was not correct" Expect.equal (Less "").OpSql "<" "The Less SQL was not correct"
} }
test "LE succeeds" { test "LessOrEqual succeeds" {
Expect.equal (string LE) "<=" "The less than or equal to operator was not correct" Expect.equal (LessOrEqual "").OpSql "<=" "The LessOrEqual SQL was not correct"
} }
test "NE succeeds" { test "NotEqual succeeds" {
Expect.equal (string NE) "<>" "The not equal to operator was not correct" Expect.equal (NotEqual "").OpSql "<>" "The NotEqual SQL was not correct"
} }
test "BT succeeds" { test "Between succeeds" {
Expect.equal (string BT) "BETWEEN" """The "between" operator was not correct""" Expect.equal (Between("", "")).OpSql "BETWEEN" "The Between SQL was not correct"
} }
test "EX succeeds" { test "In succeeds" {
Expect.equal (string EX) "IS NOT NULL" """The "exists" operator was not correct""" Expect.equal (In []).OpSql "IN" "The In SQL was not correct"
} }
test "NEX succeeds" { test "Contains succeeds" {
Expect.equal (string NEX) "IS NULL" """The "not exists" operator was not correct""" 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" { test "EQ succeeds" {
let field = Field.EQ "Test" 14 let field = Field.EQ "Test" 14
Expect.equal field.Name "Test" "Field name incorrect" Expect.equal field.Name "Test" "Field name incorrect"
Expect.equal field.Op EQ "Operator incorrect" Expect.equal field.Comparison (Equals 14) "Comparison incorrect"
Expect.equal field.Value 14 "Value incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None" Expect.isNone field.Qualifier "The default table qualifier should be None"
} }
test "GT succeeds" { test "GT succeeds" {
let field = Field.GT "Great" "night" let field = Field.GT "Great" "night"
Expect.equal field.Name "Great" "Field name incorrect" Expect.equal field.Name "Great" "Field name incorrect"
Expect.equal field.Op GT "Operator incorrect" Expect.equal field.Comparison (Greater "night") "Comparison incorrect"
Expect.equal field.Value "night" "Value incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None" Expect.isNone field.Qualifier "The default table qualifier should be None"
} }
test "GE succeeds" { test "GE succeeds" {
let field = Field.GE "Nice" 88L let field = Field.GE "Nice" 88L
Expect.equal field.Name "Nice" "Field name incorrect" Expect.equal field.Name "Nice" "Field name incorrect"
Expect.equal field.Op GE "Operator incorrect" Expect.equal field.Comparison (GreaterOrEqual 88L) "Comparison incorrect"
Expect.equal field.Value 88L "Value incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None" Expect.isNone field.Qualifier "The default table qualifier should be None"
} }
test "LT succeeds" { test "LT succeeds" {
let field = Field.LT "Lesser" "seven" let field = Field.LT "Lesser" "seven"
Expect.equal field.Name "Lesser" "Field name incorrect" Expect.equal field.Name "Lesser" "Field name incorrect"
Expect.equal field.Op LT "Operator incorrect" Expect.equal field.Comparison (Less "seven") "Comparison incorrect"
Expect.equal field.Value "seven" "Value incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None" Expect.isNone field.Qualifier "The default table qualifier should be None"
} }
test "LE succeeds" { test "LE succeeds" {
let field = Field.LE "Nobody" "KNOWS"; let field = Field.LE "Nobody" "KNOWS";
Expect.equal field.Name "Nobody" "Field name incorrect" Expect.equal field.Name "Nobody" "Field name incorrect"
Expect.equal field.Op LE "Operator incorrect" Expect.equal field.Comparison (LessOrEqual "KNOWS") "Comparison incorrect"
Expect.equal field.Value "KNOWS" "Value incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None" Expect.isNone field.Qualifier "The default table qualifier should be None"
} }
test "NE succeeds" { test "NE succeeds" {
let field = Field.NE "Park" "here" let field = Field.NE "Park" "here"
Expect.equal field.Name "Park" "Field name incorrect" Expect.equal field.Name "Park" "Field name incorrect"
Expect.equal field.Op NE "Operator incorrect" Expect.equal field.Comparison (NotEqual "here") "Comparison incorrect"
Expect.equal field.Value "here" "Value incorrect"
Expect.isNone field.ParameterName "The default parameter name should be None" Expect.isNone field.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None" Expect.isNone field.Qualifier "The default table qualifier should be None"
} }
test "BT succeeds" { test "BT succeeds" {
let field = Field.BT "Age" 18 49 let field = Field.BT "Age" 18 49
Expect.equal field.Name "Age" "Field name incorrect" Expect.equal field.Name "Age" "Field name incorrect"
Expect.equal field.Op BT "Operator incorrect" Expect.equal field.Comparison (Between(18, 49)) "Comparison incorrect"
Expect.sequenceEqual (field.Value :?> obj list) [ 18; 49 ] "Value 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.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None" Expect.isNone field.Qualifier "The default table qualifier should be None"
} }
test "EX succeeds" { test "EX succeeds" {
let field = Field.EX "Groovy" let field = Field.EX "Groovy"
Expect.equal field.Name "Groovy" "Field name incorrect" 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.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier should be None" Expect.isNone field.Qualifier "The default table qualifier should be None"
} }
test "NEX succeeds" { test "NEX succeeds" {
let field = Field.NEX "Rad" let field = Field.NEX "Rad"
Expect.equal field.Name "Rad" "Field name incorrect" 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.ParameterName "The default parameter name should be None"
Expect.isNone field.Qualifier "The default table qualifier 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 /// Tests which do not hit the database
let all = testList "Common" [ let all = testList "Common" [
opTests comparisonTests
fieldTests fieldTests
fieldMatchTests fieldMatchTests
parameterNameTests parameterNameTests