From fb2b397663d5a431468b304d96d002813bb5f1a0 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Wed, 4 Sep 2024 16:14:22 -0400 Subject: [PATCH 1/7] WIP on IN operator --- src/Common/Library.fs | 9 +++++++++ src/Postgres/Library.fs | 11 +++++++++++ src/Sqlite/Library.fs | 7 +++++++ src/Tests/PostgresTests.fs | 12 ++++++++++++ src/Tests/SqliteTests.fs | 6 ++++++ 5 files changed, 45 insertions(+) diff --git a/src/Common/Library.fs b/src/Common/Library.fs index bf6f9bd..03308b7 100644 --- a/src/Common/Library.fs +++ b/src/Common/Library.fs @@ -19,6 +19,10 @@ type Op = | NE /// Between (BETWEEN) | BT + /// In (IN) + | IN + // Array Contains/Exists (PostgreSQL: |? SQLite: EXISTS / json_each / IN) + //| AEX /// Exists (IS NOT NULL) | EX /// Does Not Exist (IS NULL) @@ -33,6 +37,7 @@ type Op = | LE -> "<=" | NE -> "<>" | BT -> "BETWEEN" + | IN -> "IN" | EX -> "IS NOT NULL" | NEX -> "IS NULL" @@ -89,6 +94,10 @@ type Field = { static member BT name (min: obj) (max: obj) = { Name = name; Op = BT; Value = [ min; max ]; ParameterName = None; Qualifier = None } + /// Create an IN field criterion + static member IN name (values: obj seq) = + { Name = name; Op = IN; Value = values; ParameterName = None; Qualifier = None } + /// Create an exists (IS NOT NULL) field criterion static member EX name = { Name = name; Op = EX; Value = obj (); ParameterName = None; Qualifier = None } diff --git a/src/Postgres/Library.fs b/src/Postgres/Library.fs index 4095549..fd37426 100644 --- a/src/Postgres/Library.fs +++ b/src/Postgres/Library.fs @@ -96,6 +96,13 @@ module Parameters = 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 -> + let p = name.Derive it.ParameterName + yield! + it.Value :?> obj seq + |> Seq.mapi (fun idx v -> + let paramName = $"{p}_{idx}" + paramName, Sql.parameter (NpgsqlParameter(paramName, v))) | _ -> let p = name.Derive it.ParameterName yield (p, parameterFor it.Value (fun v -> Sql.parameter (NpgsqlParameter(p, v)))) }) @@ -138,6 +145,10 @@ module Query = 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 + let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", " + $"({paramNames})", defaultArg (Seq.tryHead values) (obj ()) | _ -> p, it.Value if isNumeric value then $"({it.Path PostgreSQL})::numeric {it.Op} {param}" diff --git a/src/Sqlite/Library.fs b/src/Sqlite/Library.fs index d34d3f1..4458ccb 100644 --- a/src/Sqlite/Library.fs +++ b/src/Sqlite/Library.fs @@ -42,6 +42,10 @@ module Query = | BT -> let p = name.Derive it.ParameterName $"{it.Path SQLite} {it.Op} {p}min AND {p}max" + | IN -> + 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}") |> String.concat $" {howMatched} " @@ -110,6 +114,9 @@ module Parameters = 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 + yield! it.Value :?> obj seq |> Seq.mapi (fun idx v -> SqliteParameter($"{p}_{idx}", v)) | _ -> yield SqliteParameter(name.Derive it.ParameterName, it.Value) }) |> Seq.collect id |> Seq.append parameters diff --git a/src/Tests/PostgresTests.fs b/src/Tests/PostgresTests.fs index 497e712..fd83d72 100644 --- a/src/Tests/PostgresTests.fs +++ b/src/Tests/PostgresTests.fs @@ -177,6 +177,18 @@ let queryTests = testList "Query" [ "(data->>'aField')::numeric BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max" "WHERE clause not correct" } + test "succeeds for a field with an IN operator with alphanumeric values" { + Expect.equal + (Query.whereByFields All [ Field.IN "this" [ "a"; "b"; "c" ] ]) + "data->>'this' IN (@field0_0, @field0_1, @field0_2)" + "WHERE clause not correct" + } + test "succeeds for a field with an IN operator with numeric values" { + Expect.equal + (Query.whereByFields All [ Field.IN "this" [ 7; 14; 21 ] ]) + "(data->>'this')::numeric IN (@field0_0, @field0_1, @field0_2)" + "WHERE clause not correct" + } ] testList "whereById" [ test "succeeds for numeric ID" { diff --git a/src/Tests/SqliteTests.fs b/src/Tests/SqliteTests.fs index 1a2e71d..1cf4aa8 100644 --- a/src/Tests/SqliteTests.fs +++ b/src/Tests/SqliteTests.fs @@ -51,6 +51,12 @@ let queryTests = testList "Query" [ "data->>'aField' BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max" "WHERE clause not correct" } + test "succeeds for a field with an IN operator" { + Expect.equal + (Query.whereByFields All [ Field.IN "this" [ "a"; "b"; "c" ] ]) + "data->>'this' IN (@field0_0, @field0_1, @field0_2)" + "WHERE clause not correct" + } ] test "whereById succeeds" { Expect.equal (Query.whereById "@id") "data->>'Id' = @id" "WHERE clause not correct" -- 2.45.1 From 14c80f32fe6878302d977d767eac9aef3c7f7781 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sun, 8 Sep 2024 22:16:43 -0400 Subject: [PATCH 2/7] Add IN to some tests --- src/Tests.CSharp/PostgresCSharpTests.cs | 20 ++++++++++---------- src/Tests.CSharp/SqliteCSharpTests.cs | 23 ++++++++++------------- src/Tests.CSharp/Types.cs | 12 ++++++++++++ src/Tests/PostgresTests.fs | 12 ++++++++++-- src/Tests/SqliteTests.fs | 9 ++++++++- 5 files changed, 50 insertions(+), 26 deletions(-) diff --git a/src/Tests.CSharp/PostgresCSharpTests.cs b/src/Tests.CSharp/PostgresCSharpTests.cs index a224094..63460ed 100644 --- a/src/Tests.CSharp/PostgresCSharpTests.cs +++ b/src/Tests.CSharp/PostgresCSharpTests.cs @@ -314,21 +314,12 @@ public static class PostgresCSharpTests }) ]); - private static readonly List TestDocuments = - [ - new() { Id = "one", Value = "FIRST!", NumValue = 0 }, - new() { Id = "two", Value = "another", NumValue = 10, Sub = new() { Foo = "green", Bar = "blue" } }, - new() { Id = "three", Value = "", NumValue = 4 }, - new() { Id = "four", Value = "purple", NumValue = 17, Sub = new() { Foo = "green", Bar = "red" } }, - new() { Id = "five", Value = "purple", NumValue = 18 } - ]; - /// /// Add the test documents to the database /// internal static async Task LoadDocs() { - foreach (var doc in TestDocuments) await Document.Insert(SqliteDb.TableName, doc); + foreach (var doc in JsonDocument.TestDocuments) await Document.Insert(SqliteDb.TableName, doc); } /// @@ -881,6 +872,15 @@ public static class PostgresCSharpTests [Field.EQ("Value", "another")]); Expect.hasLength(docs, 1, "There should have been one document returned"); }), + TestCase("succeeds when documents are found using IN with numeric field", async () => + { + await using var db = PostgresDb.BuildDb(); + await LoadDocs(); + + var docs = await Find.ByFields(PostgresDb.TableName, FieldMatch.All, + [Field.IN("NumValue", [2, 4, 6, 8])]); + Expect.hasLength(docs, 1, "There should have been one document returned"); + }), TestCase("succeeds when documents are not found", async () => { await using var db = PostgresDb.BuildDb(); diff --git a/src/Tests.CSharp/SqliteCSharpTests.cs b/src/Tests.CSharp/SqliteCSharpTests.cs index 71d38b4..44a50c3 100644 --- a/src/Tests.CSharp/SqliteCSharpTests.cs +++ b/src/Tests.CSharp/SqliteCSharpTests.cs @@ -129,24 +129,12 @@ public static class SqliteCSharpTests // Results are exhaustively executed in the context of other tests - /// - /// Documents used for integration tests - /// - private static readonly List TestDocuments = - [ - new() { Id = "one", Value = "FIRST!", NumValue = 0 }, - new() { Id = "two", Value = "another", NumValue = 10, Sub = new() { Foo = "green", Bar = "blue" } }, - new() { Id = "three", Value = "", NumValue = 4 }, - new() { Id = "four", Value = "purple", NumValue = 17, Sub = new() { Foo = "green", Bar = "red" } }, - new() { Id = "five", Value = "purple", NumValue = 18 } - ]; - /// /// Add the test documents to the database /// internal static async Task LoadDocs() { - foreach (var doc in TestDocuments) await Document.Insert(SqliteDb.TableName, doc); + foreach (var doc in JsonDocument.TestDocuments) await Document.Insert(SqliteDb.TableName, doc); } /// @@ -608,6 +596,15 @@ public static class SqliteCSharpTests [Field.GT("NumValue", 15)]); Expect.equal(docs.Count, 2, "There should have been two documents returned"); }), + TestCase("succeeds when documents are found using IN with numeric field", async () => + { + await using var db = await SqliteDb.BuildDb(); + await LoadDocs(); + + var docs = await Find.ByFields(SqliteDb.TableName, FieldMatch.All, + [Field.IN("NumValue", [2, 4, 6, 8])]); + Expect.hasLength(docs, 1, "There should have been one document returned"); + }), TestCase("succeeds when documents are not found", async () => { await using var db = await SqliteDb.BuildDb(); diff --git a/src/Tests.CSharp/Types.cs b/src/Tests.CSharp/Types.cs index ce63230..88d8830 100644 --- a/src/Tests.CSharp/Types.cs +++ b/src/Tests.CSharp/Types.cs @@ -18,4 +18,16 @@ public class JsonDocument public string Value { get; set; } = ""; public int NumValue { get; set; } = 0; public SubDocument? Sub { get; set; } = null; + + /// + /// A set of documents used for integration tests + /// + public static readonly List TestDocuments = + [ + new() { Id = "one", Value = "FIRST!", NumValue = 0 }, + new() { Id = "two", Value = "another", NumValue = 10, Sub = new() { Foo = "green", Bar = "blue" } }, + new() { Id = "three", Value = "", NumValue = 4 }, + new() { Id = "four", Value = "purple", NumValue = 17, Sub = new() { Foo = "green", Bar = "red" } }, + new() { Id = "five", Value = "purple", NumValue = 18 } + ]; } diff --git a/src/Tests/PostgresTests.fs b/src/Tests/PostgresTests.fs index fd83d72..7e04c94 100644 --- a/src/Tests/PostgresTests.fs +++ b/src/Tests/PostgresTests.fs @@ -719,8 +719,16 @@ let findTests = testList "Find" [ do! loadDocs () let! docs = - Find.byFields PostgresDb.TableName All [ Field.EQ "Value" "purple"; Field.EX "Sub" ] - Expect.equal (List.length docs) 1 "There should have been one document returned" + Find.byFields + PostgresDb.TableName All [ Field.IN "Value" [ "purple"; "blue" ]; Field.EX "Sub" ] + Expect.hasLength docs 1 "There should have been one document returned" + } + testTask "succeeds when documents are found using IN with numeric field" { + use db = PostgresDb.BuildDb() + do! loadDocs () + + let! docs = Find.byFields PostgresDb.TableName All [ Field.IN "NumValue" [ 2; 4; 6; 8 ] ] + Expect.hasLength docs 1 "There should have been one document returned" } testTask "succeeds when documents are not found" { use db = PostgresDb.BuildDb() diff --git a/src/Tests/SqliteTests.fs b/src/Tests/SqliteTests.fs index 1cf4aa8..de02b9f 100644 --- a/src/Tests/SqliteTests.fs +++ b/src/Tests/SqliteTests.fs @@ -515,7 +515,14 @@ let findTests = testList "Find" [ do! loadDocs () let! docs = Find.byFields SqliteDb.TableName Any [ Field.GT "NumValue" 15 ] - Expect.equal (List.length docs) 2 "There should have been two documents returned" + Expect.hasLength docs 2 "There should have been two documents returned" + } + testTask "succeeds when documents are found using IN with numeric field" { + use! db = SqliteDb.BuildDb() + do! loadDocs () + + let! docs = Find.byFields SqliteDb.TableName All [ Field.IN "NumValue" [ 2; 4; 6; 8 ] ] + Expect.hasLength docs 1 "There should have been one document returned" } testTask "succeeds when documents are not found" { use! db = SqliteDb.BuildDb() -- 2.45.1 From b07ae3f097086960315f627fa220eafbdce630ca Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sun, 15 Sep 2024 17:45:52 -0400 Subject: [PATCH 3/7] Change Op to Comparison DU --- src/Common/Library.fs | 88 ++++++++++++++------------- src/Postgres/Library.fs | 43 +++++++------ src/Sqlite/Library.fs | 37 +++++------ src/Tests.CSharp/CommonCSharpTests.cs | 81 +++++++++++++----------- src/Tests/CommonTests.fs | 78 +++++++++++++----------- 5 files changed, 173 insertions(+), 154 deletions(-) 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 -- 2.45.1 From 566e5ce74dc9a3808e346d9fd68256bdf6bd48c5 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sun, 15 Sep 2024 21:05:07 -0400 Subject: [PATCH 4/7] Spell out field names --- src/Common/Library.fs | 84 +++++++++----- src/Postgres/Library.fs | 6 +- src/Sqlite/Library.fs | 6 +- src/Tests.CSharp/CommonCSharpTests.cs | 66 +++++------ .../PostgresCSharpExtensionTests.cs | 44 +++---- src/Tests.CSharp/PostgresCSharpTests.cs | 73 ++++++------ src/Tests.CSharp/PostgresDb.cs | 1 - .../SqliteCSharpExtensionTests.cs | 44 +++---- src/Tests.CSharp/SqliteCSharpTests.cs | 74 ++++++------ src/Tests/CommonTests.fs | 66 +++++------ src/Tests/PostgresExtensionTests.fs | 79 +++++++------ src/Tests/PostgresTests.fs | 107 +++++++++--------- src/Tests/SqliteExtensionTests.fs | 41 +++---- src/Tests/SqliteTests.fs | 68 +++++------ 14 files changed, 400 insertions(+), 359 deletions(-) diff --git a/src/Common/Library.fs b/src/Common/Library.fs index 471ac37..c50f815 100644 --- a/src/Common/Library.fs +++ b/src/Common/Library.fs @@ -5,7 +5,7 @@ open System.Security.Cryptography /// The types of comparisons available for JSON fields type Comparison = /// Equals (=) - | Equals of obj + | Equal of obj /// Greater Than (>) | Greater of obj /// Greater Than or Equal To (>=) @@ -20,7 +20,7 @@ type Comparison = | Between of obj * obj /// In (IN) | In of obj seq - // Array Contains/Exists (PostgreSQL: |? SQLite: EXISTS / json_each / IN) + // Array Contains (PostgreSQL: |? SQLite: EXISTS / json_each / IN) | Contains of obj /// Exists (IS NOT NULL) | Exists @@ -30,7 +30,7 @@ type Comparison = /// Get the operator SQL for this comparison member this.OpSql = match this with - | Equals _ -> "=" + | Equal _ -> "=" | Greater _ -> ">" | GreaterOrEqual _ -> ">=" | Less _ -> "<" @@ -50,68 +50,94 @@ type Dialect = | SQLite /// Criteria for a field WHERE clause -type Field = { - /// The name of the field - Name: string +type Field = + { /// The name of the field + Name: string - Comparison: Comparison - // /// The operation by which the field will be compared - // Op: Op - // - // /// The value of the field - // Value: obj + /// The comparison for the field + Comparison: Comparison - /// The name of the parameter for this field - ParameterName: string option + /// The name of the parameter for this field + ParameterName: string option - /// The table qualifier for this field - Qualifier: string option -} with + /// The table qualifier for this 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) = - Field.Where name (Equals value) + static member Equal name (value: obj) = + Field.Where name (Equal value) + + /// Create an equals (=) field criterion (alias) + static member EQ name (value: obj) = Field.Equal name value /// Create a greater than (>) field criterion - static member GT name (value: obj) = + static member Greater name (value: obj) = Field.Where name (Greater value) + /// Create a greater than (>) field criterion (alias) + static member GT name (value: obj) = Field.Greater name value + /// Create a greater than or equal to (>=) field criterion - static member GE name (value: obj) = + static member GreaterOrEqual name (value: obj) = 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 + /// Create a less than (<) field criterion - static member LT name (value: obj) = + static member Less name (value: obj) = Field.Where name (Less value) + /// Create a less than (<) field criterion (alias) + static member LT name (value: obj) = Field.Less name value + /// Create a less than or equal to (<=) field criterion - static member LE name (value: obj) = + static member LessOrEqual name (value: obj) = 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 + /// Create a not equals (<>) field criterion - static member NE name (value: obj) = + static member NotEqual name (value: obj) = Field.Where name (NotEqual value) + /// Create a not equals (<>) field criterion (alias) + static member NE name (value: obj) = Field.NotEqual name value + /// Create a BETWEEN field criterion - static member BT name (min: obj) (max: obj) = + static member Between name (min: obj) (max: obj) = 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 + /// Create an IN field criterion - static member IN name (values: obj seq) = + static member In name (values: obj seq) = Field.Where name (In values) + /// Create an IN field criterion (alias) + static member IN name (values: obj seq) = Field.In name values + /// Create an exists (IS NOT NULL) field criterion - static member EX name = + static member Exists name = Field.Where name Exists + /// Create an exists (IS NOT NULL) field criterion (alias) + static member EX name = Field.Exists name + /// Create a not exists (IS NULL) field criterion - static member NEX name = + static member NotExists name = Field.Where name NotExists + /// Create a not exists (IS NULL) field criterion (alias) + static member NEX name = Field.NotExists name + /// Transform a field name (a.b.c) to a path for the given SQL dialect static member NameToPath (name: string) dialect = let path = @@ -124,7 +150,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 = - Field.Where name (Equals "") + Field.Where name (Equal "") /// 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 3dd90ac..0cfb7b8 100644 --- a/src/Postgres/Library.fs +++ b/src/Postgres/Library.fs @@ -101,7 +101,7 @@ module Parameters = let paramName = $"{p}_{idx}" paramName, Sql.parameter (NpgsqlParameter(paramName, v))) | Contains _ -> () // TODO - | Equals v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v -> + | Equal v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v -> let p = name.Derive it.ParameterName yield (p, parameterFor v (fun l -> Sql.parameter (NpgsqlParameter(p, l)))) }) |> Seq.collect id @@ -147,7 +147,7 @@ module Query = let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", " $"({paramNames})", defaultArg (Seq.tryHead values) (obj ()) | 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 + | Equal v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v -> p, v | _ -> p, "" if isNumeric value then $"({it.Path PostgreSQL})::numeric {it.Comparison.OpSql} {param}" @@ -157,7 +157,7 @@ module Query = /// Create a WHERE clause fragment to implement an ID-based query [] let whereById<'TKey> (docId: 'TKey) = - whereByFields Any [ { Field.EQ (Configuration.idField ()) docId with ParameterName = Some "@id" } ] + whereByFields Any [ { Field.Equal (Configuration.idField ()) docId with ParameterName = Some "@id" } ] /// Table and index definition queries module Definition = diff --git a/src/Sqlite/Library.fs b/src/Sqlite/Library.fs index a965110..69f4e8a 100644 --- a/src/Sqlite/Library.fs +++ b/src/Sqlite/Library.fs @@ -53,7 +53,7 @@ module Query = /// Create a WHERE clause fragment to implement an ID-based query [] let whereById paramName = - whereByFields Any [ { Field.EQ (Configuration.idField ()) 0 with ParameterName = Some paramName } ] + whereByFields Any [ { Field.Equal (Configuration.idField ()) 0 with ParameterName = Some paramName } ] /// Create an UPDATE statement to patch documents [] @@ -71,7 +71,7 @@ module Query = let byId<'TKey> statement (docId: 'TKey) = Query.statementWhere statement - (whereByFields Any [ { Field.EQ (Configuration.idField ()) docId with ParameterName = Some "@id" } ]) + (whereByFields Any [ { Field.Equal (Configuration.idField ()) docId with ParameterName = Some "@id" } ]) /// Create a query on JSON fields [] @@ -117,7 +117,7 @@ module Parameters = 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 -> + | Equal v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v -> yield SqliteParameter(name.Derive it.ParameterName, v) }) |> Seq.collect id |> Seq.append parameters diff --git a/src/Tests.CSharp/CommonCSharpTests.cs b/src/Tests.CSharp/CommonCSharpTests.cs index 3a68f85..75b6400 100644 --- a/src/Tests.CSharp/CommonCSharpTests.cs +++ b/src/Tests.CSharp/CommonCSharpTests.cs @@ -25,9 +25,9 @@ public static class CommonCSharpTests /// private static readonly Test OpTests = TestList("Comparison.OpSql", [ - TestCase("Equals succeeds", () => + TestCase("Equal succeeds", () => { - Expect.equal(Comparison.NewEquals("").OpSql, "=", "The Equals SQL was not correct"); + Expect.equal(Comparison.NewEqual("").OpSql, "=", "The Equals SQL was not correct"); }), TestCase("Greater succeeds", () => { @@ -76,64 +76,64 @@ public static class CommonCSharpTests /// private static readonly Test FieldTests = TestList("Field", [ - TestCase("EQ succeeds", () => + TestCase("Equal succeeds", () => { - var field = Field.EQ("Test", 14); + var field = Field.Equal("Test", 14); Expect.equal(field.Name, "Test", "Field name incorrect"); - Expect.equal(field.Comparison, Comparison.NewEquals(14), "Comparison incorrect"); + Expect.equal(field.Comparison, Comparison.NewEqual(14), "Comparison incorrect"); }), - TestCase("GT succeeds", () => + TestCase("Greater succeeds", () => { - var field = Field.GT("Great", "night"); + var field = Field.Greater("Great", "night"); Expect.equal(field.Name, "Great", "Field name incorrect"); Expect.equal(field.Comparison, Comparison.NewGreater("night"), "Comparison incorrect"); }), - TestCase("GE succeeds", () => + TestCase("GreaterOrEqual succeeds", () => { - var field = Field.GE("Nice", 88L); + var field = Field.GreaterOrEqual("Nice", 88L); Expect.equal(field.Name, "Nice", "Field name incorrect"); Expect.equal(field.Comparison, Comparison.NewGreaterOrEqual(88L), "Comparison incorrect"); }), - TestCase("LT succeeds", () => + TestCase("Less succeeds", () => { - var field = Field.LT("Lesser", "seven"); + var field = Field.Less("Lesser", "seven"); Expect.equal(field.Name, "Lesser", "Field name incorrect"); Expect.equal(field.Comparison, Comparison.NewLess("seven"), "Comparison incorrect"); }), - TestCase("LE succeeds", () => + TestCase("LessOrEqual succeeds", () => { - var field = Field.LE("Nobody", "KNOWS"); + var field = Field.LessOrEqual("Nobody", "KNOWS"); Expect.equal(field.Name, "Nobody", "Field name incorrect"); Expect.equal(field.Comparison, Comparison.NewLessOrEqual("KNOWS"), "Comparison incorrect"); }), - TestCase("NE succeeds", () => + TestCase("NotEqual succeeds", () => { - var field = Field.NE("Park", "here"); + var field = Field.NotEqual("Park", "here"); Expect.equal(field.Name, "Park", "Field name incorrect"); Expect.equal(field.Comparison, Comparison.NewNotEqual("here"), "Comparison incorrect"); }), - TestCase("BT succeeds", () => + TestCase("Between succeeds", () => { - var field = Field.BT("Age", 18, 49); + var field = Field.Between("Age", 18, 49); Expect.equal(field.Name, "Age", "Field name incorrect"); Expect.equal(field.Comparison, Comparison.NewBetween(18, 49), "Comparison incorrect"); }), - TestCase("IN succeeds", () => + TestCase("In succeeds", () => { - var field = Field.IN("Here", [8, 16, 32]); + 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("Exists succeeds", () => { - var field = Field.EX("Groovy"); + var field = Field.Exists("Groovy"); Expect.equal(field.Name, "Groovy", "Field name incorrect"); Expect.isTrue(field.Comparison.IsExists, "Comparison incorrect"); }), - TestCase("NEX succeeds", () => + TestCase("NotExists succeeds", () => { - var field = Field.NEX("Rad"); + var field = Field.NotExists("Rad"); Expect.equal(field.Name, "Rad", "Field name incorrect"); Expect.isTrue(field.Comparison.IsNotExists, "Comparison incorrect"); }), @@ -164,13 +164,13 @@ public static class CommonCSharpTests ]), TestCase("WithParameterName succeeds", () => { - var field = Field.EQ("Bob", "Tom").WithParameterName("@name"); + var field = Field.Equal("Bob", "Tom").WithParameterName("@name"); Expect.isSome(field.ParameterName, "The parameter name should have been filled"); Expect.equal("@name", field.ParameterName.Value, "The parameter name is incorrect"); }), TestCase("WithQualifier succeeds", () => { - var field = Field.EQ("Bill", "Matt").WithQualifier("joe"); + var field = Field.Equal("Bill", "Matt").WithQualifier("joe"); Expect.isSome(field.Qualifier, "The table qualifier should have been filled"); Expect.equal("joe", field.Qualifier.Value, "The table qualifier is incorrect"); }), @@ -178,47 +178,47 @@ public static class CommonCSharpTests [ TestCase("succeeds for a PostgreSQL single field with no qualifier", () => { - var field = Field.GE("SomethingCool", 18); + var field = Field.GreaterOrEqual("SomethingCool", 18); Expect.equal("data->>'SomethingCool'", field.Path(Dialect.PostgreSQL), "The PostgreSQL path is incorrect"); }), TestCase("succeeds for a PostgreSQL single field with a qualifier", () => { - var field = Field.LT("SomethingElse", 9).WithQualifier("this"); + var field = Field.Less("SomethingElse", 9).WithQualifier("this"); Expect.equal("this.data->>'SomethingElse'", field.Path(Dialect.PostgreSQL), "The PostgreSQL path is incorrect"); }), TestCase("succeeds for a PostgreSQL nested field with no qualifier", () => { - var field = Field.EQ("My.Nested.Field", "howdy"); + var field = Field.Equal("My.Nested.Field", "howdy"); Expect.equal("data#>>'{My,Nested,Field}'", field.Path(Dialect.PostgreSQL), "The PostgreSQL path is incorrect"); }), TestCase("succeeds for a PostgreSQL nested field with a qualifier", () => { - var field = Field.EQ("Nest.Away", "doc").WithQualifier("bird"); + var field = Field.Equal("Nest.Away", "doc").WithQualifier("bird"); Expect.equal("bird.data#>>'{Nest,Away}'", field.Path(Dialect.PostgreSQL), "The PostgreSQL path is incorrect"); }), TestCase("succeeds for a SQLite single field with no qualifier", () => { - var field = Field.GE("SomethingCool", 18); + var field = Field.GreaterOrEqual("SomethingCool", 18); Expect.equal("data->>'SomethingCool'", field.Path(Dialect.SQLite), "The SQLite path is incorrect"); }), TestCase("succeeds for a SQLite single field with a qualifier", () => { - var field = Field.LT("SomethingElse", 9).WithQualifier("this"); + var field = Field.Less("SomethingElse", 9).WithQualifier("this"); Expect.equal("this.data->>'SomethingElse'", field.Path(Dialect.SQLite), "The SQLite path is incorrect"); }), TestCase("succeeds for a SQLite nested field with no qualifier", () => { - var field = Field.EQ("My.Nested.Field", "howdy"); + var field = Field.Equal("My.Nested.Field", "howdy"); Expect.equal("data->>'My'->>'Nested'->>'Field'", field.Path(Dialect.SQLite), "The SQLite path is incorrect"); }), TestCase("succeeds for a SQLite nested field with a qualifier", () => { - var field = Field.EQ("Nest.Away", "doc").WithQualifier("bird"); + var field = Field.Equal("Nest.Away", "doc").WithQualifier("bird"); Expect.equal("bird.data->>'Nest'->>'Away'", field.Path(Dialect.SQLite), "The SQLite path is incorrect"); }) ]) diff --git a/src/Tests.CSharp/PostgresCSharpExtensionTests.cs b/src/Tests.CSharp/PostgresCSharpExtensionTests.cs index 054143a..65b0743 100644 --- a/src/Tests.CSharp/PostgresCSharpExtensionTests.cs +++ b/src/Tests.CSharp/PostgresCSharpExtensionTests.cs @@ -205,7 +205,7 @@ public class PostgresCSharpExtensionTests } }) ]), - TestList("save", + TestList("Save", [ TestCase("succeeds when a document is inserted", async () => { @@ -253,7 +253,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); var theCount = await conn.CountByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "purple")]); + [Field.Equal("Value", "purple")]); Expect.equal(theCount, 2, "There should have been 2 matching documents"); }), TestCase("CountByContains succeeds", async () => @@ -303,7 +303,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - var exists = await conn.ExistsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EX("Sub")]); + var exists = await conn.ExistsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Exists("Sub")]); Expect.isTrue(exists, "There should have been existing documents"); }), TestCase("succeeds when documents do not exist", async () => @@ -313,7 +313,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); var exists = - await conn.ExistsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", "six")]); + await conn.ExistsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "six")]); Expect.isFalse(exists, "There should not have been existing documents"); }) ]), @@ -450,7 +450,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); var docs = await conn.FindByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "another")]); + [Field.Equal("Value", "another")]); Expect.equal(docs.Count, 1, "There should have been one document returned"); }), TestCase("succeeds when documents are not found", async () => @@ -460,7 +460,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); var docs = await conn.FindByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "mauve")]); + [Field.Equal("Value", "mauve")]); Expect.isEmpty(docs, "There should have been no documents returned"); }) ]), @@ -473,7 +473,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); var docs = await conn.FindByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "purple")], [Field.Named("Id")]); + [Field.Equal("Value", "purple")], [Field.Named("Id")]); Expect.hasLength(docs, 2, "There should have been two document returned"); Expect.equal(string.Join('|', docs.Select(x => x.Id)), "five|four", "The documents were not ordered correctly"); @@ -485,7 +485,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); var docs = await conn.FindByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "purple")], [Field.Named("Id DESC")]); + [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]); Expect.hasLength(docs, 2, "There should have been two document returned"); Expect.equal(string.Join('|', docs.Select(x => x.Id)), "four|five", "The documents were not ordered correctly"); @@ -599,7 +599,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); var doc = await conn.FindFirstByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "another")]); + [Field.Equal("Value", "another")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal(doc.Id, "two", "The incorrect document was returned"); }), @@ -610,7 +610,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); var doc = await conn.FindFirstByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "purple")]); + [Field.Equal("Value", "purple")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.contains(["five", "four"], doc.Id, "An incorrect document was returned"); }), @@ -621,7 +621,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); var doc = await conn.FindFirstByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "absent")]); + [Field.Equal("Value", "absent")]); Expect.isNull(doc, "There should not have been a document returned"); }) ]), @@ -634,7 +634,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); var doc = await conn.FindFirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "purple")], [Field.Named("Id")]); + [Field.Equal("Value", "purple")], [Field.Named("Id")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal("five", doc.Id, "An incorrect document was returned"); }), @@ -645,7 +645,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); var doc = await conn.FindFirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "purple")], [Field.Named("Id DESC")]); + [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal("four", doc.Id, "An incorrect document was returned"); }) @@ -859,10 +859,10 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - await conn.PatchByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("Value", "purple")], + await conn.PatchByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")], new { NumValue = 77 }); var after = await conn.CountByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("NumValue", "77")]); + [Field.Equal("NumValue", 77)]); Expect.equal(after, 2, "There should have been 2 documents returned"); }), TestCase("succeeds when no document is updated", async () => @@ -873,7 +873,7 @@ public class PostgresCSharpExtensionTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await conn.PatchByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("Value", "burgundy")], + await conn.PatchByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "burgundy")], new { Foo = "green" }); }) ]), @@ -975,7 +975,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - await conn.RemoveFieldsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", "17")], + await conn.RemoveFieldsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "17")], ["Sub", "Value"]); var updated = await Find.ById(PostgresDb.TableName, "four"); Expect.isNotNull(updated, "The updated document should have been retrieved"); @@ -988,7 +988,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - await conn.RemoveFieldsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", "17")], + await conn.RemoveFieldsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "17")], ["Sub"]); var updated = await Find.ById(PostgresDb.TableName, "four"); Expect.isNotNull(updated, "The updated document should have been retrieved"); @@ -1002,7 +1002,7 @@ public class PostgresCSharpExtensionTests await LoadDocs(); // This not raising an exception is the test - await conn.RemoveFieldsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", "17")], + await conn.RemoveFieldsByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "17")], ["Nothing"]); }), TestCase("succeeds when no document is matched", async () => @@ -1012,7 +1012,7 @@ public class PostgresCSharpExtensionTests // This not raising an exception is the test await conn.RemoveFieldsByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.NE("Abracadabra", "apple")], ["Value"]); + [Field.NotEqual("Abracadabra", "apple")], ["Value"]); }) ]), TestList("RemoveFieldsByContains", @@ -1134,7 +1134,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - await conn.DeleteByFields(PostgresDb.TableName, FieldMatch.Any, [Field.NE("Value", "purple")]); + await conn.DeleteByFields(PostgresDb.TableName, FieldMatch.Any, [Field.NotEqual("Value", "purple")]); var remaining = await conn.CountAll(PostgresDb.TableName); Expect.equal(remaining, 2, "There should have been 2 documents remaining"); }), @@ -1144,7 +1144,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - await conn.DeleteByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("Value", "crimson")]); + await conn.DeleteByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "crimson")]); var remaining = await conn.CountAll(PostgresDb.TableName); Expect.equal(remaining, 5, "There should have been 5 documents remaining"); }) diff --git a/src/Tests.CSharp/PostgresCSharpTests.cs b/src/Tests.CSharp/PostgresCSharpTests.cs index 63460ed..570fdfd 100644 --- a/src/Tests.CSharp/PostgresCSharpTests.cs +++ b/src/Tests.CSharp/PostgresCSharpTests.cs @@ -111,7 +111,7 @@ public static class PostgresCSharpTests [ TestCase("succeeds when a parameter is added", () => { - var paramList = Parameters.AddFields([Field.EQ("it", "242")], []).ToList(); + var paramList = Parameters.AddFields([Field.Equal("it", "242")], []).ToList(); Expect.hasLength(paramList, 1, "There should have been a parameter added"); var (name, value) = paramList[0]; Expect.equal(name, "@field0", "Field parameter name not correct"); @@ -119,7 +119,7 @@ public static class PostgresCSharpTests }), TestCase("succeeds when multiple independent parameters are added", () => { - var paramList = Parameters.AddFields([Field.EQ("me", "you"), Field.GT("us", "them")], + var paramList = Parameters.AddFields([Field.Equal("me", "you"), Field.Greater("us", "them")], [Parameters.Id(14)]).ToList(); Expect.hasLength(paramList, 3, "There should have been 2 parameters added"); var (name, value) = paramList[0]; @@ -134,13 +134,13 @@ public static class PostgresCSharpTests }), TestCase("succeeds when a parameter is not added", () => { - var paramList = Parameters.AddFields([Field.EX("tacos")], []).ToList(); + var paramList = Parameters.AddFields([Field.Exists("tacos")], []).ToList(); Expect.isEmpty(paramList, "There should not have been any parameters added"); }), TestCase("succeeds when two parameters are added for one field", () => { var paramList = - Parameters.AddFields([Field.BT("that", "eh", "zed").WithParameterName("@test")], []).ToList(); + Parameters.AddFields([Field.Between("that", "eh", "zed").WithParameterName("@test")], []).ToList(); Expect.hasLength(paramList, 2, "There should have been 2 parameters added"); var (name, value) = paramList[0]; Expect.equal(name, "@testmin", "Minimum field name not correct"); @@ -188,40 +188,40 @@ public static class PostgresCSharpTests { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.Any, - [Field.GT("theField", "0").WithParameterName("@test")]), + [Field.Greater("theField", "0").WithParameterName("@test")]), "data->>'theField' > @test", "WHERE clause not correct"); }), TestCase("succeeds for a single field when an existence operator is passed", () => { - Expect.equal(Postgres.Query.WhereByFields(FieldMatch.Any, [Field.NEX("thatField")]), + Expect.equal(Postgres.Query.WhereByFields(FieldMatch.Any, [Field.NotExists("thatField")]), "data->>'thatField' IS NULL", "WHERE clause not correct"); }), TestCase("succeeds for a single field when a between operator is passed with numeric values", () => { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.All, - [Field.BT("aField", 50, 99).WithParameterName("@range")]), + [Field.Between("aField", 50, 99).WithParameterName("@range")]), "(data->>'aField')::numeric BETWEEN @rangemin AND @rangemax", "WHERE clause not correct"); }), TestCase("succeeds for a single field when a between operator is passed with non-numeric values", () => { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.Any, - [Field.BT("field0", "a", "b").WithParameterName("@alpha")]), + [Field.Between("field0", "a", "b").WithParameterName("@alpha")]), "data->>'field0' BETWEEN @alphamin AND @alphamax", "WHERE clause not correct"); }), TestCase("succeeds for all multiple fields with logical operators", () => { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.All, - [Field.EQ("theFirst", "1"), Field.EQ("numberTwo", "2")]), + [Field.Equal("theFirst", "1"), Field.Equal("numberTwo", "2")]), "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1", "WHERE clause not correct"); }), TestCase("succeeds for any multiple fields with an existence operator", () => { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.Any, - [Field.NEX("thatField"), Field.GE("thisField", 18)]), + [Field.NotExists("thatField"), Field.GreaterOrEqual("thisField", 18)]), "data->>'thatField' IS NULL OR (data->>'thisField')::numeric >= @field0", "WHERE clause not correct"); }), @@ -229,7 +229,7 @@ public static class PostgresCSharpTests { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.All, - [Field.BT("aField", 50, 99), Field.BT("anotherField", "a", "b")]), + [Field.Between("aField", 50, 99), Field.Between("anotherField", "a", "b")]), "(data->>'aField')::numeric BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max", "WHERE clause not correct"); }) @@ -299,7 +299,7 @@ public static class PostgresCSharpTests }), TestCase("ByFields succeeds", () => { - Expect.equal(Postgres.Query.ByFields("unit", FieldMatch.Any, [Field.GT("That", 14)]), + Expect.equal(Postgres.Query.ByFields("unit", FieldMatch.Any, [Field.Greater("That", 14)]), "unit WHERE (data->>'That')::numeric > @field0", "By-Field query not correct"); }), TestCase("ByContains succeeds", () => @@ -667,7 +667,7 @@ public static class PostgresCSharpTests await LoadDocs(); var theCount = await Count.ByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.BT("NumValue", 10, 20)]); + [Field.Between("NumValue", 10, 20)]); Expect.equal(theCount, 3, "There should have been 3 matching documents"); }), TestCase("succeeds for non-numeric range", async () => @@ -676,7 +676,7 @@ public static class PostgresCSharpTests await LoadDocs(); var theCount = await Count.ByFields(PostgresDb.TableName, FieldMatch.All, - [Field.BT("Value", "aardvark", "apple")]); + [Field.Between("Value", "aardvark", "apple")]); Expect.equal(theCount, 1, "There should have been 1 matching document"); }) ]), @@ -729,7 +729,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - var exists = await Exists.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.NEX("Sub")]); + var exists = await Exists.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.NotExists("Sub")]); Expect.isTrue(exists, "There should have been existing documents"); }), TestCase("succeeds when documents do not exist", async () => @@ -737,7 +737,8 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - var exists = await Exists.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", "six")]); + var exists = await Exists.ByFields(PostgresDb.TableName, FieldMatch.Any, + [Field.Equal("NumValue", "six")]); Expect.isFalse(exists, "There should not have been existing documents"); }) ]), @@ -869,7 +870,7 @@ public static class PostgresCSharpTests await LoadDocs(); var docs = await Find.ByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "another")]); + [Field.Equal("Value", "another")]); Expect.hasLength(docs, 1, "There should have been one document returned"); }), TestCase("succeeds when documents are found using IN with numeric field", async () => @@ -878,7 +879,7 @@ public static class PostgresCSharpTests await LoadDocs(); var docs = await Find.ByFields(PostgresDb.TableName, FieldMatch.All, - [Field.IN("NumValue", [2, 4, 6, 8])]); + [Field.In("NumValue", [2, 4, 6, 8])]); Expect.hasLength(docs, 1, "There should have been one document returned"); }), TestCase("succeeds when documents are not found", async () => @@ -887,7 +888,7 @@ public static class PostgresCSharpTests await LoadDocs(); var docs = await Find.ByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "mauve")]); + [Field.Equal("Value", "mauve")]); Expect.isEmpty(docs, "There should have been no documents returned"); }) ]), @@ -899,7 +900,7 @@ public static class PostgresCSharpTests await LoadDocs(); var docs = await Find.ByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "purple")], [Field.Named("Id")]); + [Field.Equal("Value", "purple")], [Field.Named("Id")]); Expect.hasLength(docs, 2, "There should have been two document returned"); Expect.equal(string.Join('|', docs.Select(x => x.Id)), "five|four", "The documents were not ordered correctly"); @@ -910,7 +911,7 @@ public static class PostgresCSharpTests await LoadDocs(); var docs = await Find.ByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "purple")], [Field.Named("Id DESC")]); + [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]); Expect.hasLength(docs, 2, "There should have been two document returned"); Expect.equal(string.Join('|', docs.Select(x => x.Id)), "four|five", "The documents were not ordered correctly"); @@ -1015,7 +1016,7 @@ public static class PostgresCSharpTests await LoadDocs(); var doc = await Find.FirstByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "another")]); + [Field.Equal("Value", "another")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal(doc.Id, "two", "The incorrect document was returned"); }), @@ -1025,7 +1026,7 @@ public static class PostgresCSharpTests await LoadDocs(); var doc = await Find.FirstByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "purple")]); + [Field.Equal("Value", "purple")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.contains(["five", "four"], doc.Id, "An incorrect document was returned"); }), @@ -1035,7 +1036,7 @@ public static class PostgresCSharpTests await LoadDocs(); var doc = await Find.FirstByFields(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "absent")]); + [Field.Equal("Value", "absent")]); Expect.isNull(doc, "There should not have been a document returned"); }) ]), @@ -1047,7 +1048,7 @@ public static class PostgresCSharpTests await LoadDocs(); var doc = await Find.FirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "purple")], [Field.Named("Id")]); + [Field.Equal("Value", "purple")], [Field.Named("Id")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal("five", doc.Id, "An incorrect document was returned"); }), @@ -1057,7 +1058,7 @@ public static class PostgresCSharpTests await LoadDocs(); var doc = await Find.FirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "purple")], [Field.Named("Id DESC")]); + [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal("four", doc.Id, "An incorrect document was returned"); }) @@ -1271,9 +1272,9 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - await Patch.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("Value", "purple")], + await Patch.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")], new { NumValue = 77 }); - var after = await Count.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", "77")]); + var after = await Count.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "77")]); Expect.equal(after, 2, "There should have been 2 documents returned"); }), TestCase("succeeds when no document is updated", async () => @@ -1284,7 +1285,7 @@ public static class PostgresCSharpTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await Patch.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("Value", "burgundy")], + await Patch.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "burgundy")], new { Foo = "green" }); }) ]), @@ -1386,7 +1387,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - await RemoveFields.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", "17")], + await RemoveFields.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "17")], ["Sub", "Value"]); var updated = await Find.ById(PostgresDb.TableName, "four"); Expect.isNotNull(updated, "The updated document should have been retrieved"); @@ -1398,7 +1399,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - await RemoveFields.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", "17")], + await RemoveFields.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "17")], ["Sub"]); var updated = await Find.ById(PostgresDb.TableName, "four"); Expect.isNotNull(updated, "The updated document should have been retrieved"); @@ -1411,7 +1412,7 @@ public static class PostgresCSharpTests await LoadDocs(); // This not raising an exception is the test - await RemoveFields.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", "17")], + await RemoveFields.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", "17")], ["Nothing"]); }), TestCase("succeeds when no document is matched", async () => @@ -1419,8 +1420,8 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); // This not raising an exception is the test - await RemoveFields.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.NE("Abracadabra", "apple")], - ["Value"]); + await RemoveFields.ByFields(PostgresDb.TableName, FieldMatch.Any, + [Field.NotEqual("Abracadabra", "apple")], ["Value"]); }) ]), TestList("ByContains", @@ -1538,7 +1539,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - await Delete.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("Value", "purple")]); + await Delete.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")]); var remaining = await Count.All(PostgresDb.TableName); Expect.equal(remaining, 3, "There should have been 3 documents remaining"); }), @@ -1547,7 +1548,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - await Delete.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.EQ("Value", "crimson")]); + await Delete.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "crimson")]); var remaining = await Count.All(PostgresDb.TableName); Expect.equal(remaining, 5, "There should have been 5 documents remaining"); }) diff --git a/src/Tests.CSharp/PostgresDb.cs b/src/Tests.CSharp/PostgresDb.cs index 4d84e2c..063c299 100644 --- a/src/Tests.CSharp/PostgresDb.cs +++ b/src/Tests.CSharp/PostgresDb.cs @@ -1,4 +1,3 @@ -using BitBadger.Documents.Postgres; using Npgsql; using Npgsql.FSharp; using ThrowawayDb.Postgres; diff --git a/src/Tests.CSharp/SqliteCSharpExtensionTests.cs b/src/Tests.CSharp/SqliteCSharpExtensionTests.cs index 7290183..5d23375 100644 --- a/src/Tests.CSharp/SqliteCSharpExtensionTests.cs +++ b/src/Tests.CSharp/SqliteCSharpExtensionTests.cs @@ -221,7 +221,8 @@ public static class SqliteCSharpExtensionTests await using var conn = Sqlite.Configuration.DbConn(); await LoadDocs(); - var theCount = await conn.CountByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Value", "purple")]); + var theCount = await conn.CountByFields(SqliteDb.TableName, FieldMatch.Any, + [Field.Equal("Value", "purple")]); Expect.equal(theCount, 2L, "There should have been 2 matching documents"); }), TestList("ExistsById", @@ -253,7 +254,8 @@ public static class SqliteCSharpExtensionTests await using var conn = Sqlite.Configuration.DbConn(); await LoadDocs(); - var exists = await conn.ExistsByFields(SqliteDb.TableName, FieldMatch.Any, [Field.GE("NumValue", 10)]); + var exists = await conn.ExistsByFields(SqliteDb.TableName, FieldMatch.Any, + [Field.GreaterOrEqual("NumValue", 10)]); Expect.isTrue(exists, "There should have been existing documents"); }), TestCase("succeeds when no matching documents exist", async () => @@ -263,7 +265,7 @@ public static class SqliteCSharpExtensionTests await LoadDocs(); var exists = - await conn.ExistsByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Nothing", "none")]); + await conn.ExistsByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("Nothing", "none")]); Expect.isFalse(exists, "There should not have been any existing documents"); }) ]), @@ -357,7 +359,7 @@ public static class SqliteCSharpExtensionTests await LoadDocs(); var docs = await conn.FindByFields(SqliteDb.TableName, FieldMatch.Any, - [Field.GT("NumValue", 15)]); + [Field.Greater("NumValue", 15)]); Expect.equal(docs.Count, 2, "There should have been two documents returned"); }), TestCase("succeeds when documents are not found", async () => @@ -367,7 +369,7 @@ public static class SqliteCSharpExtensionTests await LoadDocs(); var docs = await conn.FindByFields(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "mauve")]); + [Field.Equal("Value", "mauve")]); Expect.isEmpty(docs, "There should have been no documents returned"); }) ]), @@ -380,7 +382,7 @@ public static class SqliteCSharpExtensionTests await LoadDocs(); var docs = await conn.FindByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, - [Field.GT("NumValue", 15)], [Field.Named("Id")]); + [Field.Greater("NumValue", 15)], [Field.Named("Id")]); Expect.equal(string.Join('|', docs.Select(x => x.Id)), "five|four", "There should have been two documents returned"); }), @@ -391,7 +393,7 @@ public static class SqliteCSharpExtensionTests await LoadDocs(); var docs = await conn.FindByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, - [Field.GT("NumValue", 15)], [Field.Named("Id DESC")]); + [Field.Greater("NumValue", 15)], [Field.Named("Id DESC")]); Expect.equal(string.Join('|', docs.Select(x => x.Id)), "four|five", "There should have been two documents returned"); }) @@ -405,7 +407,7 @@ public static class SqliteCSharpExtensionTests await LoadDocs(); var doc = await conn.FindFirstByFields(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "another")]); + [Field.Equal("Value", "another")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal(doc!.Id, "two", "The incorrect document was returned"); }), @@ -416,7 +418,7 @@ public static class SqliteCSharpExtensionTests await LoadDocs(); var doc = await conn.FindFirstByFields(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Sub.Foo", "green")]); + [Field.Equal("Sub.Foo", "green")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.contains(["two", "four"], doc!.Id, "An incorrect document was returned"); }), @@ -427,7 +429,7 @@ public static class SqliteCSharpExtensionTests await LoadDocs(); var doc = await conn.FindFirstByFields(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "absent")]); + [Field.Equal("Value", "absent")]); Expect.isNull(doc, "There should not have been a document returned"); }) ]), @@ -440,7 +442,7 @@ public static class SqliteCSharpExtensionTests await LoadDocs(); var doc = await conn.FindFirstByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Sub.Foo", "green")], [Field.Named("Sub.Bar")]); + [Field.Equal("Sub.Foo", "green")], [Field.Named("Sub.Bar")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal("two", doc!.Id, "An incorrect document was returned"); }), @@ -451,7 +453,7 @@ public static class SqliteCSharpExtensionTests await LoadDocs(); var doc = await conn.FindFirstByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Sub.Foo", "green")], [Field.Named("Sub.Bar DESC")]); + [Field.Equal("Sub.Foo", "green")], [Field.Named("Sub.Bar DESC")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal("four", doc!.Id, "An incorrect document was returned"); }) @@ -547,9 +549,9 @@ public static class SqliteCSharpExtensionTests await using var conn = Sqlite.Configuration.DbConn(); await LoadDocs(); - await conn.PatchByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Value", "purple")], + await conn.PatchByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")], new { NumValue = 77 }); - var after = await conn.CountByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 77)]); + var after = await conn.CountByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", 77)]); Expect.equal(after, 2L, "There should have been 2 documents returned"); }), TestCase("succeeds when no document is updated", async () => @@ -560,7 +562,7 @@ public static class SqliteCSharpExtensionTests Expect.isEmpty(before, "There should have been no documents returned"); // This not raising an exception is the test - await conn.PatchByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Value", "burgundy")], + await conn.PatchByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("Value", "burgundy")], new { Foo = "green" }); }) ]), @@ -604,7 +606,7 @@ public static class SqliteCSharpExtensionTests await using var conn = Sqlite.Configuration.DbConn(); await LoadDocs(); - await conn.RemoveFieldsByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)], + await conn.RemoveFieldsByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", 17)], ["Sub"]); var updated = await Find.ById(SqliteDb.TableName, "four"); Expect.isNotNull(updated, "The updated document should have been retrieved"); @@ -617,7 +619,7 @@ public static class SqliteCSharpExtensionTests await LoadDocs(); // This not raising an exception is the test - await conn.RemoveFieldsByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)], + await conn.RemoveFieldsByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", 17)], ["Nothing"]); }), TestCase("succeeds when no document is matched", async () => @@ -626,8 +628,8 @@ public static class SqliteCSharpExtensionTests await using var conn = Sqlite.Configuration.DbConn(); // This not raising an exception is the test - await conn.RemoveFieldsByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NE("Abracadabra", "apple")], - ["Value"]); + await conn.RemoveFieldsByFields(SqliteDb.TableName, FieldMatch.Any, + [Field.NotEqual("Abracadabra", "apple")], ["Value"]); }) ]), TestList("DeleteById", @@ -661,7 +663,7 @@ public static class SqliteCSharpExtensionTests await using var conn = Sqlite.Configuration.DbConn(); await LoadDocs(); - await conn.DeleteByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NE("Value", "purple")]); + await conn.DeleteByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NotEqual("Value", "purple")]); var remaining = await conn.CountAll(SqliteDb.TableName); Expect.equal(remaining, 2L, "There should have been 2 documents remaining"); }), @@ -671,7 +673,7 @@ public static class SqliteCSharpExtensionTests await using var conn = Sqlite.Configuration.DbConn(); await LoadDocs(); - await conn.DeleteByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Value", "crimson")]); + await conn.DeleteByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("Value", "crimson")]); var remaining = await conn.CountAll(SqliteDb.TableName); Expect.equal(remaining, 5L, "There should have been 5 documents remaining"); }) diff --git a/src/Tests.CSharp/SqliteCSharpTests.cs b/src/Tests.CSharp/SqliteCSharpTests.cs index 44a50c3..731a512 100644 --- a/src/Tests.CSharp/SqliteCSharpTests.cs +++ b/src/Tests.CSharp/SqliteCSharpTests.cs @@ -22,38 +22,41 @@ public static class SqliteCSharpTests TestCase("succeeds for a single field when a logical operator is passed", () => { Expect.equal( - Sqlite.Query.WhereByFields(FieldMatch.Any, [Field.GT("theField", 0).WithParameterName("@test")]), + Sqlite.Query.WhereByFields(FieldMatch.Any, + [Field.Greater("theField", 0).WithParameterName("@test")]), "data->>'theField' > @test", "WHERE clause not correct"); }), TestCase("succeeds for a single field when an existence operator is passed", () => { - Expect.equal(Sqlite.Query.WhereByFields(FieldMatch.Any, [Field.NEX("thatField")]), + Expect.equal(Sqlite.Query.WhereByFields(FieldMatch.Any, [Field.NotExists("thatField")]), "data->>'thatField' IS NULL", "WHERE clause not correct"); }), TestCase("succeeds for a single field when a between operator is passed", () => { Expect.equal( Sqlite.Query.WhereByFields(FieldMatch.All, - [Field.BT("aField", 50, 99).WithParameterName("@range")]), + [Field.Between("aField", 50, 99).WithParameterName("@range")]), "data->>'aField' BETWEEN @rangemin AND @rangemax", "WHERE clause not correct"); }), TestCase("succeeds for all multiple fields with logical operators", () => { Expect.equal( - Sqlite.Query.WhereByFields(FieldMatch.All, [Field.EQ("theFirst", "1"), Field.EQ("numberTwo", "2")]), + Sqlite.Query.WhereByFields(FieldMatch.All, + [Field.Equal("theFirst", "1"), Field.Equal("numberTwo", "2")]), "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1", "WHERE clause not correct"); }), TestCase("succeeds for any multiple fields with an existence operator", () => { Expect.equal( - Sqlite.Query.WhereByFields(FieldMatch.Any, [Field.NEX("thatField"), Field.GE("thisField", 18)]), + Sqlite.Query.WhereByFields(FieldMatch.Any, + [Field.NotExists("thatField"), Field.GreaterOrEqual("thisField", 18)]), "data->>'thatField' IS NULL OR data->>'thisField' >= @field0", "WHERE clause not correct"); }), TestCase("succeeds for all multiple fields with between operators", () => { Expect.equal( Sqlite.Query.WhereByFields(FieldMatch.All, - [Field.BT("aField", 50, 99), Field.BT("anotherField", "a", "b")]), + [Field.Between("aField", 50, 99), Field.Between("anotherField", "a", "b")]), "data->>'aField' BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max", "WHERE clause not correct"); }) @@ -79,7 +82,7 @@ public static class SqliteCSharpTests }), TestCase("ByFields succeeds", () => { - Expect.equal(Sqlite.Query.ByFields("unit", FieldMatch.Any, [Field.GT("That", 14)]), + Expect.equal(Sqlite.Query.ByFields("unit", FieldMatch.Any, [Field.Greater("That", 14)]), "unit WHERE data->>'That' > @field0", "By-Field query not correct"); }), TestCase("Definition.EnsureTable succeeds", () => @@ -109,7 +112,7 @@ public static class SqliteCSharpTests #pragma warning disable CS0618 TestCase("AddField succeeds when adding a parameter", () => { - var paramList = Parameters.AddField("@field", Field.EQ("it", 99), []).ToList(); + var paramList = Parameters.AddField("@field", Field.Equal("it", 99), []).ToList(); Expect.hasLength(paramList, 1, "There should have been a parameter added"); var theParam = paramList[0]; Expect.equal(theParam.ParameterName, "@field", "The parameter name is incorrect"); @@ -117,7 +120,7 @@ public static class SqliteCSharpTests }), TestCase("AddField succeeds when not adding a parameter", () => { - var paramSeq = Parameters.AddField("@it", Field.EX("Coffee"), []); + var paramSeq = Parameters.AddField("@it", Field.Exists("Coffee"), []); Expect.isEmpty(paramSeq, "There should not have been any parameters added"); }), #pragma warning restore CS0618 @@ -447,7 +450,8 @@ public static class SqliteCSharpTests await using var db = await SqliteDb.BuildDb(); await LoadDocs(); - var theCount = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.BT("NumValue", 10, 20)]); + var theCount = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any, + [Field.Between("NumValue", 10, 20)]); Expect.equal(theCount, 3L, "There should have been 3 matching documents"); }), TestCase("succeeds for non-numeric range", async () => @@ -456,7 +460,7 @@ public static class SqliteCSharpTests await LoadDocs(); var theCount = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any, - [Field.BT("Value", "aardvark", "apple")]); + [Field.Between("Value", "aardvark", "apple")]); Expect.equal(theCount, 1L, "There should have been 1 matching document"); }) ]) @@ -493,7 +497,8 @@ public static class SqliteCSharpTests await using var db = await SqliteDb.BuildDb(); await LoadDocs(); - var exists = await Exists.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.GE("NumValue", 10)]); + var exists = await Exists.ByFields(SqliteDb.TableName, FieldMatch.Any, + [Field.GreaterOrEqual("NumValue", 10)]); Expect.isTrue(exists, "There should have been existing documents"); }), TestCase("succeeds when no matching documents exist", async () => @@ -501,7 +506,8 @@ public static class SqliteCSharpTests await using var db = await SqliteDb.BuildDb(); await LoadDocs(); - var exists = await Exists.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Nothing", "none")]); + var exists = await Exists.ByFields(SqliteDb.TableName, FieldMatch.Any, + [Field.Equal("Nothing", "none")]); Expect.isFalse(exists, "There should not have been any existing documents"); }) ]) @@ -593,7 +599,7 @@ public static class SqliteCSharpTests await LoadDocs(); var docs = await Find.ByFields(SqliteDb.TableName, FieldMatch.Any, - [Field.GT("NumValue", 15)]); + [Field.Greater("NumValue", 15)]); Expect.equal(docs.Count, 2, "There should have been two documents returned"); }), TestCase("succeeds when documents are found using IN with numeric field", async () => @@ -602,7 +608,7 @@ public static class SqliteCSharpTests await LoadDocs(); var docs = await Find.ByFields(SqliteDb.TableName, FieldMatch.All, - [Field.IN("NumValue", [2, 4, 6, 8])]); + [Field.In("NumValue", [2, 4, 6, 8])]); Expect.hasLength(docs, 1, "There should have been one document returned"); }), TestCase("succeeds when documents are not found", async () => @@ -611,7 +617,7 @@ public static class SqliteCSharpTests await LoadDocs(); var docs = await Find.ByFields(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "mauve")]); + [Field.Equal("Value", "mauve")]); Expect.isEmpty(docs, "There should have been no documents returned"); }) ]), @@ -623,7 +629,7 @@ public static class SqliteCSharpTests await LoadDocs(); var docs = await Find.ByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, - [Field.GT("NumValue", 15)], [Field.Named("Id")]); + [Field.Greater("NumValue", 15)], [Field.Named("Id")]); Expect.hasLength(docs, 2, "There should have been two documents returned"); Expect.equal(string.Join('|', docs.Select(x => x.Id)), "five|four", "The documents were not sorted correctly"); @@ -634,7 +640,7 @@ public static class SqliteCSharpTests await LoadDocs(); var docs = await Find.ByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, - [Field.GT("NumValue", 15)], [Field.Named("Id DESC")]); + [Field.Greater("NumValue", 15)], [Field.Named("Id DESC")]); Expect.hasLength(docs, 2, "There should have been two documents returned"); Expect.equal(string.Join('|', docs.Select(x => x.Id)), "four|five", "The documents were not sorted correctly"); @@ -645,7 +651,7 @@ public static class SqliteCSharpTests await LoadDocs(); var docs = await Find.ByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, - [Field.LE("NumValue", 10)], [Field.Named("Value")]); + [Field.LessOrEqual("NumValue", 10)], [Field.Named("Value")]); Expect.hasLength(docs, 3, "There should have been three documents returned"); Expect.equal(string.Join('|', docs.Select(x => x.Id)), "three|one|two", "The documents were not sorted correctly"); @@ -656,7 +662,7 @@ public static class SqliteCSharpTests await LoadDocs(); var docs = await Find.ByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, - [Field.LE("NumValue", 10)], [Field.Named("i:Value")]); + [Field.LessOrEqual("NumValue", 10)], [Field.Named("i:Value")]); Expect.hasLength(docs, 3, "There should have been three documents returned"); Expect.equal(string.Join('|', docs.Select(x => x.Id)), "three|two|one", "The documents were not sorted correctly"); @@ -670,7 +676,7 @@ public static class SqliteCSharpTests await LoadDocs(); var doc = await Find.FirstByFields(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "another")]); + [Field.Equal("Value", "another")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal(doc!.Id, "two", "The incorrect document was returned"); }), @@ -680,7 +686,7 @@ public static class SqliteCSharpTests await LoadDocs(); var doc = await Find.FirstByFields(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Sub.Foo", "green")]); + [Field.Equal("Sub.Foo", "green")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.contains(["two", "four"], doc!.Id, "An incorrect document was returned"); }), @@ -690,7 +696,7 @@ public static class SqliteCSharpTests await LoadDocs(); var doc = await Find.FirstByFields(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Value", "absent")]); + [Field.Equal("Value", "absent")]); Expect.isNull(doc, "There should not have been a document returned"); }) ]), @@ -702,7 +708,7 @@ public static class SqliteCSharpTests await LoadDocs(); var doc = await Find.FirstByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Sub.Foo", "green")], [Field.Named("Sub.Bar")]); + [Field.Equal("Sub.Foo", "green")], [Field.Named("Sub.Bar")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal("two", doc!.Id, "An incorrect document was returned"); }), @@ -712,7 +718,7 @@ public static class SqliteCSharpTests await LoadDocs(); var doc = await Find.FirstByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, - [Field.EQ("Sub.Foo", "green")], [Field.Named("Sub.Bar DESC")]); + [Field.Equal("Sub.Foo", "green")], [Field.Named("Sub.Bar DESC")]); Expect.isNotNull(doc, "There should have been a document returned"); Expect.equal("four", doc!.Id, "An incorrect document was returned"); }) @@ -818,9 +824,9 @@ public static class SqliteCSharpTests await using var db = await SqliteDb.BuildDb(); await LoadDocs(); - await Patch.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Value", "purple")], + await Patch.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")], new { NumValue = 77 }); - var after = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 77)]); + var after = await Count.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", 77)]); Expect.equal(after, 2L, "There should have been 2 documents returned"); }), TestCase("succeeds when no document is updated", async () => @@ -831,7 +837,7 @@ public static class SqliteCSharpTests Expect.isEmpty(before, "There should have been no documents returned"); // This not raising an exception is the test - await Patch.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("Value", "burgundy")], + await Patch.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("Value", "burgundy")], new { Foo = "green" }); }) ]) @@ -878,7 +884,7 @@ public static class SqliteCSharpTests await using var db = await SqliteDb.BuildDb(); await LoadDocs(); - await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)], ["Sub"]); + await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", 17)], ["Sub"]); var updated = await Find.ById(SqliteDb.TableName, "four"); Expect.isNotNull(updated, "The updated document should have been retrieved"); Expect.isNull(updated.Sub, "The sub-document should have been removed"); @@ -889,7 +895,7 @@ public static class SqliteCSharpTests await LoadDocs(); // This not raising an exception is the test - await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.EQ("NumValue", 17)], + await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("NumValue", 17)], ["Nothing"]); }), TestCase("succeeds when no document is matched", async () => @@ -897,8 +903,8 @@ public static class SqliteCSharpTests await using var db = await SqliteDb.BuildDb(); // This not raising an exception is the test - await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NE("Abracadabra", "apple")], - ["Value"]); + await RemoveFields.ByFields(SqliteDb.TableName, FieldMatch.Any, + [Field.NotEqual("Abracadabra", "apple")], ["Value"]); }) ]) ]); @@ -936,7 +942,7 @@ public static class SqliteCSharpTests await using var db = await SqliteDb.BuildDb(); await LoadDocs(); - await Delete.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NE("Value", "purple")]); + await Delete.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.NotEqual("Value", "purple")]); var remaining = await Count.All(SqliteDb.TableName); Expect.equal(remaining, 2L, "There should have been 2 documents remaining"); }), @@ -945,7 +951,7 @@ public static class SqliteCSharpTests await using var db = await SqliteDb.BuildDb(); await LoadDocs(); - await Delete.ByFields(SqliteDb.TableName, FieldMatch.All, [Field.EQ("Value", "crimson")]); + await Delete.ByFields(SqliteDb.TableName, FieldMatch.All, [Field.Equal("Value", "crimson")]); var remaining = await Count.All(SqliteDb.TableName); Expect.equal(remaining, 5L, "There should have been 5 documents remaining"); }) diff --git a/src/Tests/CommonTests.fs b/src/Tests/CommonTests.fs index f3f73ad..7230af8 100644 --- a/src/Tests/CommonTests.fs +++ b/src/Tests/CommonTests.fs @@ -8,8 +8,8 @@ let tbl = "test_table" /// Unit tests for the Op DU let comparisonTests = testList "Comparison.OpSql" [ - test "Equals succeeds" { - Expect.equal (Equals "").OpSql "=" "The Equals SQL was not correct" + test "Equal succeeds" { + Expect.equal (Equal "").OpSql "=" "The Equals SQL was not correct" } test "Greater succeeds" { Expect.equal (Greater "").OpSql ">" "The Greater SQL was not correct" @@ -45,71 +45,71 @@ let comparisonTests = testList "Comparison.OpSql" [ /// Unit tests for the Field class let fieldTests = testList "Field" [ - test "EQ succeeds" { - let field = Field.EQ "Test" 14 + test "Equal succeeds" { + let field = Field.Equal "Test" 14 Expect.equal field.Name "Test" "Field name incorrect" - Expect.equal field.Comparison (Equals 14) "Comparison incorrect" + Expect.equal field.Comparison (Equal 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" + test "Greater succeeds" { + let field = Field.Greater "Great" "night" Expect.equal field.Name "Great" "Field name 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 + test "GreaterOrEqual succeeds" { + let field = Field.GreaterOrEqual "Nice" 88L Expect.equal field.Name "Nice" "Field name 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" + test "Less succeeds" { + let field = Field.Less "Lesser" "seven" Expect.equal field.Name "Lesser" "Field name 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"; + test "LessOrEqual succeeds" { + let field = Field.LessOrEqual "Nobody" "KNOWS"; Expect.equal field.Name "Nobody" "Field name 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" + test "NotEqual succeeds" { + let field = Field.NotEqual "Park" "here" Expect.equal field.Name "Park" "Field name 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 + test "Between succeeds" { + let field = Field.Between "Age" 18 49 Expect.equal field.Name "Age" "Field name 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 |] + 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" + test "Exists succeeds" { + let field = Field.Exists "Groovy" Expect.equal field.Name "Groovy" "Field name 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" + test "NotExists succeeds" { + let field = Field.NotExists "Rad" Expect.equal field.Name "Rad" "Field name incorrect" Expect.equal field.Comparison NotExists "Comparison incorrect" Expect.isNone field.ParameterName "The default parameter name should be None" @@ -136,46 +136,46 @@ let fieldTests = testList "Field" [ } ] test "WithParameterName succeeds" { - let field = (Field.EQ "Bob" "Tom").WithParameterName "@name" + let field = (Field.Equal "Bob" "Tom").WithParameterName "@name" Expect.isSome field.ParameterName "The parameter name should have been filled" Expect.equal "@name" field.ParameterName.Value "The parameter name is incorrect" } test "WithQualifier succeeds" { - let field = (Field.EQ "Bill" "Matt").WithQualifier "joe" + let field = (Field.Equal "Bill" "Matt").WithQualifier "joe" Expect.isSome field.Qualifier "The table qualifier should have been filled" Expect.equal "joe" field.Qualifier.Value "The table qualifier is incorrect" } testList "Path" [ test "succeeds for a PostgreSQL single field with no qualifier" { - let field = Field.GE "SomethingCool" 18 + let field = Field.GreaterOrEqual "SomethingCool" 18 Expect.equal "data->>'SomethingCool'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" } test "succeeds for a PostgreSQL single field with a qualifier" { - let field = { Field.LT "SomethingElse" 9 with Qualifier = Some "this" } + let field = { Field.Less "SomethingElse" 9 with Qualifier = Some "this" } Expect.equal "this.data->>'SomethingElse'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" } test "succeeds for a PostgreSQL nested field with no qualifier" { - let field = Field.EQ "My.Nested.Field" "howdy" + let field = Field.Equal "My.Nested.Field" "howdy" Expect.equal "data#>>'{My,Nested,Field}'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" } test "succeeds for a PostgreSQL nested field with a qualifier" { - let field = { Field.EQ "Nest.Away" "doc" with Qualifier = Some "bird" } + let field = { Field.Equal "Nest.Away" "doc" with Qualifier = Some "bird" } Expect.equal "bird.data#>>'{Nest,Away}'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" } test "succeeds for a SQLite single field with no qualifier" { - let field = Field.GE "SomethingCool" 18 + let field = Field.GreaterOrEqual "SomethingCool" 18 Expect.equal "data->>'SomethingCool'" (field.Path SQLite) "The SQLite path is incorrect" } test "succeeds for a SQLite single field with a qualifier" { - let field = { Field.LT "SomethingElse" 9 with Qualifier = Some "this" } + let field = { Field.Less "SomethingElse" 9 with Qualifier = Some "this" } Expect.equal "this.data->>'SomethingElse'" (field.Path SQLite) "The SQLite path is incorrect" } test "succeeds for a SQLite nested field with no qualifier" { - let field = Field.EQ "My.Nested.Field" "howdy" + let field = Field.Equal "My.Nested.Field" "howdy" Expect.equal "data->>'My'->>'Nested'->>'Field'" (field.Path SQLite) "The SQLite path is incorrect" } test "succeeds for a SQLite nested field with a qualifier" { - let field = { Field.EQ "Nest.Away" "doc" with Qualifier = Some "bird" } + let field = { Field.Equal "Nest.Away" "doc" with Qualifier = Some "bird" } Expect.equal "bird.data->>'Nest'->>'Away'" (field.Path SQLite) "The SQLite path is incorrect" } ] diff --git a/src/Tests/PostgresExtensionTests.fs b/src/Tests/PostgresExtensionTests.fs index 533cf12..60fcf31 100644 --- a/src/Tests/PostgresExtensionTests.fs +++ b/src/Tests/PostgresExtensionTests.fs @@ -214,7 +214,7 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - let! theCount = conn.countByFields PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] + let! theCount = conn.countByFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] Expect.equal theCount 2 "There should have been 2 matching documents" } testTask "countByContains succeeds" { @@ -257,7 +257,7 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - let! exists = conn.existsByFields PostgresDb.TableName Any [ Field.EX "Sub" ] + let! exists = conn.existsByFields PostgresDb.TableName Any [ Field.Exists "Sub" ] Expect.isTrue exists "There should have been existing documents" } testTask "succeeds when documents do not exist" { @@ -265,7 +265,7 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - let! exists = conn.existsByFields PostgresDb.TableName Any [ Field.EQ "NumValue" "six" ] + let! exists = conn.existsByFields PostgresDb.TableName Any [ Field.Equal "NumValue" "six" ] Expect.isFalse exists "There should not have been existing documents" } ] @@ -390,7 +390,7 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - let! docs = conn.findByFields PostgresDb.TableName Any [ Field.EQ "Value" "another" ] + let! docs = conn.findByFields PostgresDb.TableName Any [ Field.Equal "Value" "another" ] Expect.equal (List.length docs) 1 "There should have been one document returned" } testTask "succeeds when documents are not found" { @@ -398,7 +398,7 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - let! docs = conn.findByFields PostgresDb.TableName Any [ Field.EQ "Value" "mauve" ] + let! docs = conn.findByFields PostgresDb.TableName Any [ Field.Equal "Value" "mauve" ] Expect.isEmpty docs "There should have been no documents returned" } ] @@ -410,7 +410,7 @@ let integrationTests = let! docs = conn.findByFieldsOrdered - PostgresDb.TableName All [ Field.EQ "Value" "purple" ] [ Field.Named "Id" ] + PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] Expect.hasLength docs 2 "There should have been two documents returned" Expect.equal (docs |> List.map _.Id |> String.concat "|") "five|four" "Documents not ordered correctly" @@ -422,7 +422,7 @@ let integrationTests = let! docs = conn.findByFieldsOrdered - PostgresDb.TableName All [ Field.EQ "Value" "purple" ] [ Field.Named "Id DESC" ] + PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] Expect.hasLength docs 2 "There should have been two documents returned" Expect.equal (docs |> List.map _.Id |> String.concat "|") "four|five" "Documents not ordered correctly" @@ -524,7 +524,8 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - let! doc = conn.findFirstByFields PostgresDb.TableName Any [ Field.EQ "Value" "another" ] + let! doc = + conn.findFirstByFields PostgresDb.TableName Any [ Field.Equal "Value" "another" ] Expect.isSome doc "There should have been a document returned" Expect.equal doc.Value.Id "two" "The incorrect document was returned" } @@ -533,7 +534,8 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - let! doc = conn.findFirstByFields PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] + let! doc = + conn.findFirstByFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] Expect.isSome doc "There should have been a document returned" Expect.contains [ "five"; "four" ] doc.Value.Id "An incorrect document was returned" } @@ -542,7 +544,8 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - let! doc = conn.findFirstByFields PostgresDb.TableName Any [ Field.EQ "Value" "absent" ] + let! doc = + conn.findFirstByFields PostgresDb.TableName Any [ Field.Equal "Value" "absent" ] Expect.isNone doc "There should not have been a document returned" } ] @@ -554,7 +557,7 @@ let integrationTests = let! doc = conn.findFirstByFieldsOrdered - PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] [ Field.Named "Id" ] + PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] Expect.isSome doc "There should have been a document returned" Expect.equal "five" doc.Value.Id "An incorrect document was returned" } @@ -565,7 +568,7 @@ let integrationTests = let! doc = conn.findFirstByFieldsOrdered - PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] [ Field.Named "Id DESC" ] + PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] Expect.isSome doc "There should have been a document returned" Expect.equal "four" doc.Value.Id "An incorrect document was returned" } @@ -750,8 +753,8 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - do! conn.patchByFields PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] {| NumValue = 77 |} - let! after = conn.countByFields PostgresDb.TableName Any [ Field.EQ "NumValue" "77" ] + do! conn.patchByFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] {| NumValue = 77 |} + let! after = conn.countByFields PostgresDb.TableName Any [ Field.Equal "NumValue" "77" ] Expect.equal after 2 "There should have been 2 documents returned" } testTask "succeeds when no document is updated" { @@ -761,7 +764,7 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! conn.patchByFields PostgresDb.TableName Any [ Field.EQ "Value" "burgundy" ] {| Foo = "green" |} + do! conn.patchByFields PostgresDb.TableName Any [ Field.Equal "Value" "burgundy" ] {| Foo = "green" |} } ] testList "patchByContains" [ @@ -811,9 +814,9 @@ let integrationTests = do! loadDocs conn do! conn.removeFieldsById PostgresDb.TableName "two" [ "Sub"; "Value" ] - let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 1 "There should be 1 document without Value fields" } testTask "succeeds when a single field is removed" { @@ -822,9 +825,9 @@ let integrationTests = do! loadDocs conn do! conn.removeFieldsById PostgresDb.TableName "two" [ "Sub" ] - let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 0 "There should be no documents without Value fields" } testTask "succeeds when a field is not removed" { @@ -849,10 +852,11 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - do! conn.removeFieldsByFields PostgresDb.TableName Any [ Field.EQ "NumValue" "17" ] [ "Sub"; "Value" ] - let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + do! conn.removeFieldsByFields + PostgresDb.TableName Any [ Field.Equal "NumValue" "17" ] [ "Sub"; "Value" ] + let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 1 "There should be 1 document without Value fields" } testTask "succeeds when a single field is removed" { @@ -860,10 +864,10 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - do! conn.removeFieldsByFields PostgresDb.TableName Any [ Field.EQ "NumValue" "17" ] [ "Sub" ] - let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + do! conn.removeFieldsByFields PostgresDb.TableName Any [ Field.Equal "NumValue" "17" ] [ "Sub" ] + let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 0 "There should be no documents without Value fields" } testTask "succeeds when a field is not removed" { @@ -872,14 +876,15 @@ let integrationTests = do! loadDocs conn // This not raising an exception is the test - do! conn.removeFieldsByFields PostgresDb.TableName Any [ Field.EQ "NumValue" "17" ] [ "Nothing" ] + do! conn.removeFieldsByFields PostgresDb.TableName Any [ Field.Equal "NumValue" "17" ] [ "Nothing" ] } testTask "succeeds when no document is matched" { use db = PostgresDb.BuildDb() use conn = mkConn db // This not raising an exception is the test - do! conn.removeFieldsByFields PostgresDb.TableName Any [ Field.NE "Abracadabra" "apple" ] [ "Value" ] + do! conn.removeFieldsByFields + PostgresDb.TableName Any [ Field.NotEqual "Abracadabra" "apple" ] [ "Value" ] } ] testList "removeFieldsByContains" [ @@ -889,9 +894,9 @@ let integrationTests = do! loadDocs conn do! conn.removeFieldsByContains PostgresDb.TableName {| NumValue = 17 |} [ "Sub"; "Value" ] - let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 1 "There should be 1 document without Value fields" } testTask "succeeds when a single field is removed" { @@ -900,9 +905,9 @@ let integrationTests = do! loadDocs conn do! conn.removeFieldsByContains PostgresDb.TableName {| NumValue = 17 |} [ "Sub" ] - let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 0 "There should be no documents without Value fields" } testTask "succeeds when a field is not removed" { @@ -928,9 +933,9 @@ let integrationTests = do! loadDocs conn do! conn.removeFieldsByJsonPath PostgresDb.TableName "$.NumValue ? (@ == 17)" [ "Sub"; "Value" ] - let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 1 "There should be 1 document without Value fields" } testTask "succeeds when a single field is removed" { @@ -939,9 +944,9 @@ let integrationTests = do! loadDocs conn do! conn.removeFieldsByJsonPath PostgresDb.TableName "$.NumValue ? (@ == 17)" [ "Sub" ] - let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = conn.countByFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 0 "There should be no documents without Value fields" } testTask "succeeds when a field is not removed" { @@ -986,7 +991,7 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - do! conn.deleteByFields PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] + do! conn.deleteByFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] let! remaining = conn.countAll PostgresDb.TableName Expect.equal remaining 3 "There should have been 3 documents remaining" } @@ -995,7 +1000,7 @@ let integrationTests = use conn = mkConn db do! loadDocs conn - do! conn.deleteByFields PostgresDb.TableName Any [ Field.EQ "Value" "crimson" ] + do! conn.deleteByFields PostgresDb.TableName Any [ Field.Equal "Value" "crimson" ] let! remaining = conn.countAll PostgresDb.TableName Expect.equal remaining 5 "There should have been 5 documents remaining" } diff --git a/src/Tests/PostgresTests.fs b/src/Tests/PostgresTests.fs index 7e04c94..cd37e8c 100644 --- a/src/Tests/PostgresTests.fs +++ b/src/Tests/PostgresTests.fs @@ -83,14 +83,14 @@ let parametersTests = testList "Parameters" [ } testList "addFieldParams" [ test "succeeds when a parameter is added" { - let paramList = addFieldParams [ Field.EQ "it" "242" ] [] + let paramList = addFieldParams [ Field.Where "it" (Equal "242") ] [] Expect.hasLength paramList 1 "There should have been a parameter added" let name, value = Seq.head paramList Expect.equal name "@field0" "Field parameter name not correct" Expect.equal value (Sql.string "242") "Parameter value not correct" } test "succeeds when multiple independent parameters are added" { - let paramList = addFieldParams [ Field.EQ "me" "you"; Field.GT "us" "them" ] [ idParam 14 ] + let paramList = addFieldParams [ Field.Equal "me" "you"; Field.Greater "us" "them" ] [ idParam 14 ] Expect.hasLength paramList 3 "There should have been 2 parameters added" let p = Array.ofSeq paramList Expect.equal (fst p[0]) "@id" "First field parameter name not correct" @@ -101,11 +101,11 @@ let parametersTests = testList "Parameters" [ Expect.equal (snd p[2]) (Sql.string "them") "Third parameter value not correct" } test "succeeds when a parameter is not added" { - let paramList = addFieldParams [ Field.EX "tacos" ] [] + let paramList = addFieldParams [ Field.Exists "tacos" ] [] Expect.isEmpty paramList "There should not have been any parameters added" } test "succeeds when two parameters are added for one field" { - let paramList = addFieldParams [ { Field.BT "that" "eh" "zed" with ParameterName = Some "@test" } ] [] + let paramList = addFieldParams [ { Field.Between "that" "eh" "zed" with ParameterName = Some "@test" } ] [] Expect.hasLength paramList 2 "There should have been 2 parameters added" let name, value = Seq.head paramList Expect.equal name "@testmin" "Minimum field name not correct" @@ -137,55 +137,55 @@ let queryTests = testList "Query" [ testList "whereByFields" [ test "succeeds for a single field when a logical operator is passed" { Expect.equal - (Query.whereByFields Any [ { Field.GT "theField" "0" with ParameterName = Some "@test" } ]) + (Query.whereByFields Any [ { Field.Greater "theField" "0" with ParameterName = Some "@test" } ]) "data->>'theField' > @test" "WHERE clause not correct" } test "succeeds for a single field when an existence operator is passed" { Expect.equal - (Query.whereByFields Any [ Field.NEX "thatField" ]) + (Query.whereByFields Any [ Field.NotExists "thatField" ]) "data->>'thatField' IS NULL" "WHERE clause not correct" } test "succeeds for a single field when a between operator is passed with numeric values" { Expect.equal - (Query.whereByFields All [ { Field.BT "aField" 50 99 with ParameterName = Some "@range" } ]) + (Query.whereByFields All [ { Field.Between "aField" 50 99 with ParameterName = Some "@range" } ]) "(data->>'aField')::numeric BETWEEN @rangemin AND @rangemax" "WHERE clause not correct" } test "succeeds for a single field when a between operator is passed with non-numeric values" { Expect.equal - (Query.whereByFields Any [ { Field.BT "field0" "a" "b" with ParameterName = Some "@alpha" } ]) + (Query.whereByFields Any [ { Field.Between "field0" "a" "b" with ParameterName = Some "@alpha" } ]) "data->>'field0' BETWEEN @alphamin AND @alphamax" "WHERE clause not correct" } test "succeeds for all multiple fields with logical operators" { Expect.equal - (Query.whereByFields All [ Field.EQ "theFirst" "1"; Field.EQ "numberTwo" "2" ]) + (Query.whereByFields All [ Field.Equal "theFirst" "1"; Field.Equal "numberTwo" "2" ]) "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1" "WHERE clause not correct" } test "succeeds for any multiple fields with an existence operator" { Expect.equal - (Query.whereByFields Any [ Field.NEX "thatField"; Field.GE "thisField" 18 ]) + (Query.whereByFields Any [ Field.NotExists "thatField"; Field.GreaterOrEqual "thisField" 18 ]) "data->>'thatField' IS NULL OR (data->>'thisField')::numeric >= @field0" "WHERE clause not correct" } test "succeeds for all multiple fields with between operators" { Expect.equal - (Query.whereByFields All [ Field.BT "aField" 50 99; Field.BT "anotherField" "a" "b" ]) + (Query.whereByFields All [ Field.Between "aField" 50 99; Field.Between "anotherField" "a" "b" ]) "(data->>'aField')::numeric BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max" "WHERE clause not correct" } test "succeeds for a field with an IN operator with alphanumeric values" { Expect.equal - (Query.whereByFields All [ Field.IN "this" [ "a"; "b"; "c" ] ]) + (Query.whereByFields All [ Field.In "this" [ "a"; "b"; "c" ] ]) "data->>'this' IN (@field0_0, @field0_1, @field0_2)" "WHERE clause not correct" } test "succeeds for a field with an IN operator with numeric values" { Expect.equal - (Query.whereByFields All [ Field.IN "this" [ 7; 14; 21 ] ]) + (Query.whereByFields All [ Field.In "this" [ 7; 14; 21 ] ]) "(data->>'this')::numeric IN (@field0_0, @field0_1, @field0_2)" "WHERE clause not correct" } @@ -246,7 +246,7 @@ let queryTests = testList "Query" [ } test "byFields succeeds" { Expect.equal - (Query.byFields "unit" Any [ Field.GT "That" 14 ]) + (Query.byFields "unit" Any [ Field.Greater "That" 14 ]) "unit WHERE (data->>'That')::numeric > @field0" "By-Field query not correct" } @@ -544,14 +544,15 @@ let countTests = testList "Count" [ use db = PostgresDb.BuildDb() do! loadDocs () - let! theCount = Count.byFields PostgresDb.TableName Any [ Field.BT "NumValue" 15 20; Field.EQ "NumValue" 0 ] + let! theCount = + Count.byFields PostgresDb.TableName Any [ Field.Between "NumValue" 15 20; Field.Equal "NumValue" 0 ] Expect.equal theCount 3 "There should have been 3 matching documents" } testTask "succeeds when items are not found" { use db = PostgresDb.BuildDb() do! loadDocs () - let! theCount = Count.byFields PostgresDb.TableName All [ Field.EX "Sub"; Field.GT "NumValue" 100 ] + let! theCount = Count.byFields PostgresDb.TableName All [ Field.Exists "Sub"; Field.Greater "NumValue" 100 ] Expect.equal theCount 0 "There should have been no matching documents" } ] @@ -594,14 +595,14 @@ let existsTests = testList "Exists" [ use db = PostgresDb.BuildDb() do! loadDocs () - let! exists = Exists.byFields PostgresDb.TableName Any [ Field.EX "Sub"; Field.EX "Boo" ] + let! exists = Exists.byFields PostgresDb.TableName Any [ Field.Exists "Sub"; Field.Exists "Boo" ] Expect.isTrue exists "There should have been existing documents" } testTask "succeeds when documents do not exist" { use db = PostgresDb.BuildDb() do! loadDocs () - let! exists = Exists.byFields PostgresDb.TableName All [ Field.EQ "NumValue" "six"; Field.EX "Nope" ] + let! exists = Exists.byFields PostgresDb.TableName All [ Field.Equal "NumValue" "six"; Field.Exists "Nope" ] Expect.isFalse exists "There should not have been existing documents" } ] @@ -720,14 +721,14 @@ let findTests = testList "Find" [ let! docs = Find.byFields - PostgresDb.TableName All [ Field.IN "Value" [ "purple"; "blue" ]; Field.EX "Sub" ] + PostgresDb.TableName All [ Field.In "Value" [ "purple"; "blue" ]; Field.Exists "Sub" ] Expect.hasLength docs 1 "There should have been one document returned" } testTask "succeeds when documents are found using IN with numeric field" { use db = PostgresDb.BuildDb() do! loadDocs () - let! docs = Find.byFields PostgresDb.TableName All [ Field.IN "NumValue" [ 2; 4; 6; 8 ] ] + let! docs = Find.byFields PostgresDb.TableName All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ] Expect.hasLength docs 1 "There should have been one document returned" } testTask "succeeds when documents are not found" { @@ -736,7 +737,7 @@ let findTests = testList "Find" [ let! docs = Find.byFields - PostgresDb.TableName All [ Field.EQ "Value" "mauve"; Field.NE "NumValue" 40 ] + PostgresDb.TableName All [ Field.Equal "Value" "mauve"; Field.NotEqual "NumValue" 40 ] Expect.isEmpty docs "There should have been no documents returned" } ] @@ -747,7 +748,7 @@ let findTests = testList "Find" [ let! docs = Find.byFieldsOrdered - PostgresDb.TableName All [ Field.EQ "Value" "purple" ] [ Field.Named "Id" ] + PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] Expect.hasLength docs 2 "There should have been two documents returned" Expect.equal (docs |> List.map _.Id |> String.concat "|") "five|four" "Documents not ordered correctly" @@ -758,7 +759,7 @@ let findTests = testList "Find" [ let! docs = Find.byFieldsOrdered - PostgresDb.TableName All [ Field.EQ "Value" "purple" ] [ Field.Named "Id DESC" ] + PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] Expect.hasLength docs 2 "There should have been two documents returned" Expect.equal (docs |> List.map _.Id |> String.concat "|") "four|five" "Documents not ordered correctly" @@ -851,7 +852,7 @@ let findTests = testList "Find" [ use db = PostgresDb.BuildDb() do! loadDocs () - let! doc = Find.firstByFields PostgresDb.TableName Any [ Field.EQ "Value" "another" ] + let! doc = Find.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "another" ] Expect.isSome doc "There should have been a document returned" Expect.equal doc.Value.Id "two" "The incorrect document was returned" } @@ -859,7 +860,7 @@ let findTests = testList "Find" [ use db = PostgresDb.BuildDb() do! loadDocs () - let! doc = Find.firstByFields PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] + let! doc = Find.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] Expect.isSome doc "There should have been a document returned" Expect.contains [ "five"; "four" ] doc.Value.Id "An incorrect document was returned" } @@ -867,7 +868,7 @@ let findTests = testList "Find" [ use db = PostgresDb.BuildDb() do! loadDocs () - let! doc = Find.firstByFields PostgresDb.TableName Any [ Field.EQ "Value" "absent" ] + let! doc = Find.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "absent" ] Expect.isNone doc "There should not have been a document returned" } ] @@ -878,7 +879,7 @@ let findTests = testList "Find" [ let! doc = Find.firstByFieldsOrdered - PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] [ Field.Named "Id" ] + PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] Expect.isSome doc "There should have been a document returned" Expect.equal "five" doc.Value.Id "An incorrect document was returned" } @@ -888,7 +889,7 @@ let findTests = testList "Find" [ let! doc = Find.firstByFieldsOrdered - PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] [ Field.Named "Id DESC" ] + PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] Expect.isSome doc "There should have been a document returned" Expect.equal "four" doc.Value.Id "An incorrect document was returned" } @@ -1065,8 +1066,8 @@ let patchTests = testList "Patch" [ use db = PostgresDb.BuildDb() do! loadDocs () - do! Patch.byFields PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] {| NumValue = 77 |} - let! after = Count.byFields PostgresDb.TableName Any [ Field.EQ "NumValue" 77 ] + do! Patch.byFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] {| NumValue = 77 |} + let! after = Count.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 77 ] Expect.equal after 2 "There should have been 2 documents returned" } testTask "succeeds when no document is updated" { @@ -1076,7 +1077,7 @@ let patchTests = testList "Patch" [ Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! Patch.byFields PostgresDb.TableName Any [ Field.EQ "Value" "burgundy" ] {| Foo = "green" |} + do! Patch.byFields PostgresDb.TableName Any [ Field.Equal "Value" "burgundy" ] {| Foo = "green" |} } ] testList "byContains" [ @@ -1127,9 +1128,9 @@ let removeFieldsTests = testList "RemoveFields" [ do! loadDocs () do! RemoveFields.byId PostgresDb.TableName "two" [ "Sub"; "Value" ] - let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 1 "There should be 1 document without Value fields" } testTask "succeeds when a single field is removed" { @@ -1137,9 +1138,9 @@ let removeFieldsTests = testList "RemoveFields" [ do! loadDocs () do! RemoveFields.byId PostgresDb.TableName "two" [ "Sub" ] - let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 0 "There should be no documents without Value fields" } testTask "succeeds when a field is not removed" { @@ -1161,20 +1162,20 @@ let removeFieldsTests = testList "RemoveFields" [ use db = PostgresDb.BuildDb() do! loadDocs () - do! RemoveFields.byFields PostgresDb.TableName Any [ Field.EQ "NumValue" "17" ] [ "Sub"; "Value" ] - let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + do! RemoveFields.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Sub"; "Value" ] + let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 1 "There should be 1 document without Value fields" } testTask "succeeds when a single field is removed" { use db = PostgresDb.BuildDb() do! loadDocs () - do! RemoveFields.byFields PostgresDb.TableName Any [ Field.EQ "NumValue" "17" ] [ "Sub" ] - let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + do! RemoveFields.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Sub" ] + let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 0 "There should be no documents without Value fields" } testTask "succeeds when a field is not removed" { @@ -1182,13 +1183,13 @@ let removeFieldsTests = testList "RemoveFields" [ do! loadDocs () // This not raising an exception is the test - do! RemoveFields.byFields PostgresDb.TableName Any [ Field.EQ "NumValue" "17" ] [ "Nothing" ] + do! RemoveFields.byFields PostgresDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Nothing" ] } testTask "succeeds when no document is matched" { use db = PostgresDb.BuildDb() // This not raising an exception is the test - do! RemoveFields.byFields PostgresDb.TableName Any [ Field.NE "Abracadabra" "apple" ] [ "Value" ] + do! RemoveFields.byFields PostgresDb.TableName Any [ Field.NotEqual "Abracadabra" "apple" ] [ "Value" ] } ] testList "byContains" [ @@ -1197,9 +1198,9 @@ let removeFieldsTests = testList "RemoveFields" [ do! loadDocs () do! RemoveFields.byContains PostgresDb.TableName {| NumValue = 17 |} [ "Sub"; "Value" ] - let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 1 "There should be 1 document without Value fields" } testTask "succeeds when a single field is removed" { @@ -1207,9 +1208,9 @@ let removeFieldsTests = testList "RemoveFields" [ do! loadDocs () do! RemoveFields.byContains PostgresDb.TableName {| NumValue = 17 |} [ "Sub" ] - let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 0 "There should be no documents without Value fields" } testTask "succeeds when a field is not removed" { @@ -1232,9 +1233,9 @@ let removeFieldsTests = testList "RemoveFields" [ do! loadDocs () do! RemoveFields.byJsonPath PostgresDb.TableName "$.NumValue ? (@ == 17)" [ "Sub"; "Value" ] - let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 1 "There should be 1 document without Value fields" } testTask "succeeds when a single field is removed" { @@ -1242,9 +1243,9 @@ let removeFieldsTests = testList "RemoveFields" [ do! loadDocs () do! RemoveFields.byJsonPath PostgresDb.TableName "$.NumValue ? (@ == 17)" [ "Sub" ] - let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NEX "Sub" ] + let! noSubs = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Sub" ] Expect.equal noSubs 4 "There should now be 4 documents without Sub fields" - let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NEX "Value" ] + let! noValue = Count.byFields PostgresDb.TableName Any [ Field.NotExists "Value" ] Expect.equal noValue 0 "There should be no documents without Value fields" } testTask "succeeds when a field is not removed" { @@ -1288,7 +1289,7 @@ let deleteTests = testList "Delete" [ use db = PostgresDb.BuildDb() do! loadDocs () - do! Delete.byFields PostgresDb.TableName Any [ Field.EQ "Value" "purple" ] + do! Delete.byFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] let! remaining = Count.all PostgresDb.TableName Expect.equal remaining 3 "There should have been 3 documents remaining" } @@ -1296,7 +1297,7 @@ let deleteTests = testList "Delete" [ use db = PostgresDb.BuildDb() do! loadDocs () - do! Delete.byFields PostgresDb.TableName Any [ Field.EQ "Value" "crimson" ] + do! Delete.byFields PostgresDb.TableName Any [ Field.Equal "Value" "crimson" ] let! remaining = Count.all PostgresDb.TableName Expect.equal remaining 5 "There should have been 5 documents remaining" } diff --git a/src/Tests/SqliteExtensionTests.fs b/src/Tests/SqliteExtensionTests.fs index 51d4f39..8f0380e 100644 --- a/src/Tests/SqliteExtensionTests.fs +++ b/src/Tests/SqliteExtensionTests.fs @@ -118,7 +118,7 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - let! theCount = conn.countByFields SqliteDb.TableName Any [ Field.EQ "Value" "purple" ] + let! theCount = conn.countByFields SqliteDb.TableName Any [ Field.Equal "Value" "purple" ] Expect.equal theCount 2L "There should have been 2 matching documents" } testList "existsById" [ @@ -145,7 +145,7 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - let! exists = conn.existsByFields SqliteDb.TableName Any [ Field.EQ "NumValue" 10 ] + let! exists = conn.existsByFields SqliteDb.TableName Any [ Field.Equal "NumValue" 10 ] Expect.isTrue exists "There should have been existing documents" } testTask "succeeds when no matching documents exist" { @@ -153,7 +153,7 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - let! exists = conn.existsByFields SqliteDb.TableName Any [ Field.EQ "Nothing" "none" ] + let! exists = conn.existsByFields SqliteDb.TableName Any [ Field.Equal "Nothing" "none" ] Expect.isFalse exists "There should not have been any existing documents" } ] @@ -244,7 +244,7 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - let! docs = conn.findByFields SqliteDb.TableName Any [ Field.EQ "Sub.Foo" "green" ] + let! docs = conn.findByFields SqliteDb.TableName Any [ Field.Equal "Sub.Foo" "green" ] Expect.hasLength docs 2 "There should have been two documents returned" } testTask "succeeds when documents are not found" { @@ -252,7 +252,7 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - let! docs = conn.findByFields SqliteDb.TableName Any [ Field.EQ "Value" "mauve" ] + let! docs = conn.findByFields SqliteDb.TableName Any [ Field.Equal "Value" "mauve" ] Expect.isEmpty docs "There should have been no documents returned" } ] @@ -264,7 +264,7 @@ let integrationTests = let! docs = conn.findByFieldsOrdered - SqliteDb.TableName Any [ Field.GT "NumValue" 15 ] [ Field.Named "Id" ] + SqliteDb.TableName Any [ Field.Greater "NumValue" 15 ] [ Field.Named "Id" ] Expect.equal (docs |> List.map _.Id |> String.concat "|") "five|four" "The documents were not ordered correctly" } @@ -275,7 +275,7 @@ let integrationTests = let! docs = conn.findByFieldsOrdered - SqliteDb.TableName Any [ Field.GT "NumValue" 15 ] [ Field.Named "Id DESC" ] + SqliteDb.TableName Any [ Field.Greater "NumValue" 15 ] [ Field.Named "Id DESC" ] Expect.equal (docs |> List.map _.Id |> String.concat "|") "four|five" "The documents were not ordered correctly" } @@ -286,7 +286,7 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - let! doc = conn.findFirstByFields SqliteDb.TableName Any [ Field.EQ "Value" "another" ] + let! doc = conn.findFirstByFields SqliteDb.TableName Any [ Field.Equal "Value" "another" ] Expect.isSome doc "There should have been a document returned" Expect.equal doc.Value.Id "two" "The incorrect document was returned" } @@ -295,7 +295,7 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - let! doc = conn.findFirstByFields SqliteDb.TableName Any [ Field.EQ "Sub.Foo" "green" ] + let! doc = conn.findFirstByFields SqliteDb.TableName Any [ Field.Equal "Sub.Foo" "green" ] Expect.isSome doc "There should have been a document returned" Expect.contains [ "two"; "four" ] doc.Value.Id "An incorrect document was returned" } @@ -304,7 +304,7 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - let! doc = conn.findFirstByFields SqliteDb.TableName Any [ Field.EQ "Value" "absent" ] + let! doc = conn.findFirstByFields SqliteDb.TableName Any [ Field.Equal "Value" "absent" ] Expect.isNone doc "There should not have been a document returned" } ] @@ -316,7 +316,7 @@ let integrationTests = let! doc = conn.findFirstByFieldsOrdered - SqliteDb.TableName Any [ Field.EQ "Sub.Foo" "green" ] [ Field.Named "Sub.Bar" ] + SqliteDb.TableName Any [ Field.Equal "Sub.Foo" "green" ] [ Field.Named "Sub.Bar" ] Expect.isSome doc "There should have been a document returned" Expect.equal "two" doc.Value.Id "An incorrect document was returned" } @@ -327,7 +327,7 @@ let integrationTests = let! doc = conn.findFirstByFieldsOrdered - SqliteDb.TableName Any [ Field.EQ "Sub.Foo" "green" ] [ Field.Named "Sub.Bar DESC" ] + SqliteDb.TableName Any [ Field.Equal "Sub.Foo" "green" ] [ Field.Named "Sub.Bar DESC" ] Expect.isSome doc "There should have been a document returned" Expect.equal "four" doc.Value.Id "An incorrect document was returned" } @@ -416,8 +416,8 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - do! conn.patchByFields SqliteDb.TableName Any [ Field.EQ "Value" "purple" ] {| NumValue = 77 |} - let! after = conn.countByFields SqliteDb.TableName Any [ Field.EQ "NumValue" 77 ] + do! conn.patchByFields SqliteDb.TableName Any [ Field.Equal "Value" "purple" ] {| NumValue = 77 |} + let! after = conn.countByFields SqliteDb.TableName Any [ Field.Equal "NumValue" 77 ] Expect.equal after 2L "There should have been 2 documents returned" } testTask "succeeds when no document is updated" { @@ -428,7 +428,7 @@ let integrationTests = Expect.isEmpty before "There should have been no documents returned" // This not raising an exception is the test - do! conn.patchByFields SqliteDb.TableName Any [ Field.EQ "Value" "burgundy" ] {| Foo = "green" |} + do! conn.patchByFields SqliteDb.TableName Any [ Field.Equal "Value" "burgundy" ] {| Foo = "green" |} } ] testList "removeFieldsById" [ @@ -467,7 +467,7 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - do! conn.removeFieldsByFields SqliteDb.TableName Any [ Field.EQ "NumValue" 17 ] [ "Sub" ] + do! conn.removeFieldsByFields SqliteDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Sub" ] try let! _ = conn.findById SqliteDb.TableName "four" Expect.isTrue false "The updated document should have failed to parse" @@ -481,14 +481,15 @@ let integrationTests = do! loadDocs () // This not raising an exception is the test - do! conn.removeFieldsByFields SqliteDb.TableName Any [ Field.EQ "NumValue" 17 ] [ "Nothing" ] + do! conn.removeFieldsByFields SqliteDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Nothing" ] } testTask "succeeds when no document is matched" { use! db = SqliteDb.BuildDb() use conn = Configuration.dbConn () // This not raising an exception is the test - do! conn.removeFieldsByFields SqliteDb.TableName Any [ Field.NE "Abracadabra" "apple" ] [ "Value" ] + do! conn.removeFieldsByFields + SqliteDb.TableName Any [ Field.NotEqual "Abracadabra" "apple" ] [ "Value" ] } ] testList "deleteById" [ @@ -517,7 +518,7 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - do! conn.deleteByFields SqliteDb.TableName Any [ Field.NE "Value" "purple" ] + do! conn.deleteByFields SqliteDb.TableName Any [ Field.NotEqual "Value" "purple" ] let! remaining = conn.countAll SqliteDb.TableName Expect.equal remaining 2L "There should have been 2 documents remaining" } @@ -526,7 +527,7 @@ let integrationTests = use conn = Configuration.dbConn () do! loadDocs () - do! conn.deleteByFields SqliteDb.TableName Any [ Field.EQ "Value" "crimson" ] + do! conn.deleteByFields SqliteDb.TableName Any [ Field.Equal "Value" "crimson" ] let! remaining = conn.countAll SqliteDb.TableName Expect.equal remaining 5L "There should have been 5 documents remaining" } diff --git a/src/Tests/SqliteTests.fs b/src/Tests/SqliteTests.fs index de02b9f..c2139af 100644 --- a/src/Tests/SqliteTests.fs +++ b/src/Tests/SqliteTests.fs @@ -17,43 +17,43 @@ let queryTests = testList "Query" [ testList "whereByFields" [ test "succeeds for a single field when a logical operator is passed" { Expect.equal - (Query.whereByFields Any [ { Field.GT "theField" 0 with ParameterName = Some "@test" } ]) + (Query.whereByFields Any [ { Field.Greater "theField" 0 with ParameterName = Some "@test" } ]) "data->>'theField' > @test" "WHERE clause not correct" } test "succeeds for a single field when an existence operator is passed" { Expect.equal - (Query.whereByFields Any [ Field.NEX "thatField" ]) + (Query.whereByFields Any [ Field.NotExists "thatField" ]) "data->>'thatField' IS NULL" "WHERE clause not correct" } test "succeeds for a single field when a between operator is passed" { Expect.equal - (Query.whereByFields All [ { Field.BT "aField" 50 99 with ParameterName = Some "@range" } ]) + (Query.whereByFields All [ { Field.Between "aField" 50 99 with ParameterName = Some "@range" } ]) "data->>'aField' BETWEEN @rangemin AND @rangemax" "WHERE clause not correct" } test "succeeds for all multiple fields with logical operators" { Expect.equal - (Query.whereByFields All [ Field.EQ "theFirst" "1"; Field.EQ "numberTwo" "2" ]) + (Query.whereByFields All [ Field.Equal "theFirst" "1"; Field.Equal "numberTwo" "2" ]) "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1" "WHERE clause not correct" } test "succeeds for any multiple fields with an existence operator" { Expect.equal - (Query.whereByFields Any [ Field.NEX "thatField"; Field.GE "thisField" 18 ]) + (Query.whereByFields Any [ Field.NotExists "thatField"; Field.GreaterOrEqual "thisField" 18 ]) "data->>'thatField' IS NULL OR data->>'thisField' >= @field0" "WHERE clause not correct" } test "succeeds for all multiple fields with between operators" { Expect.equal - (Query.whereByFields All [ Field.BT "aField" 50 99; Field.BT "anotherField" "a" "b" ]) + (Query.whereByFields All [ Field.Between "aField" 50 99; Field.Between "anotherField" "a" "b" ]) "data->>'aField' BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max" "WHERE clause not correct" } test "succeeds for a field with an IN operator" { Expect.equal - (Query.whereByFields All [ Field.IN "this" [ "a"; "b"; "c" ] ]) + (Query.whereByFields All [ Field.In "this" [ "a"; "b"; "c" ] ]) "data->>'this' IN (@field0_0, @field0_1, @field0_2)" "WHERE clause not correct" } @@ -78,7 +78,7 @@ let queryTests = testList "Query" [ } test "byFields succeeds" { Expect.equal - (Query.byFields "unit" Any [ Field.GT "That" 14 ]) + (Query.byFields "unit" Any [ Field.Greater "That" 14 ]) "unit WHERE data->>'That' > @field0" "By-Field query not correct" } @@ -104,14 +104,14 @@ let parametersTests = testList "Parameters" [ } testList "addFieldParam" [ test "succeeds when adding a parameter" { - let paramList = addFieldParam "@field" (Field.EQ "it" 99) [] + let paramList = addFieldParam "@field" (Field.Equal "it" 99) [] Expect.hasLength paramList 1 "There should have been a parameter added" let theParam = Seq.head paramList Expect.equal theParam.ParameterName "@field" "The parameter name is incorrect" Expect.equal theParam.Value 99 "The parameter value is incorrect" } test "succeeds when not adding a parameter" { - let paramList = addFieldParam "@it" (Field.NEX "Coffee") [] + let paramList = addFieldParam "@it" (Field.NotExists "Coffee") [] Expect.isEmpty paramList "There should not have been any parameters added" } ] @@ -386,14 +386,14 @@ let countTests = testList "Count" [ use! db = SqliteDb.BuildDb() do! loadDocs () - let! theCount = Count.byFields SqliteDb.TableName Any [ Field.BT "NumValue" 10 20 ] + let! theCount = Count.byFields SqliteDb.TableName Any [ Field.Between "NumValue" 10 20 ] Expect.equal theCount 3L "There should have been 3 matching documents" } testTask "succeeds for a non-numeric range" { use! db = SqliteDb.BuildDb() do! loadDocs () - let! theCount = Count.byFields SqliteDb.TableName Any [ Field.BT "Value" "aardvark" "apple" ] + let! theCount = Count.byFields SqliteDb.TableName Any [ Field.Between "Value" "aardvark" "apple" ] Expect.equal theCount 1L "There should have been 1 matching document" } ] @@ -422,14 +422,14 @@ let existsTests = testList "Exists" [ use! db = SqliteDb.BuildDb() do! loadDocs () - let! exists = Exists.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 10 ] + let! exists = Exists.byFields SqliteDb.TableName Any [ Field.Equal "NumValue" 10 ] Expect.isTrue exists "There should have been existing documents" } testTask "succeeds when no matching documents exist" { use! db = SqliteDb.BuildDb() do! loadDocs () - let! exists = Exists.byFields SqliteDb.TableName Any [ Field.LT "Nothing" "none" ] + let! exists = Exists.byFields SqliteDb.TableName Any [ Field.Less "Nothing" "none" ] Expect.isFalse exists "There should not have been any existing documents" } ] @@ -514,21 +514,21 @@ let findTests = testList "Find" [ use! db = SqliteDb.BuildDb() do! loadDocs () - let! docs = Find.byFields SqliteDb.TableName Any [ Field.GT "NumValue" 15 ] + let! docs = Find.byFields SqliteDb.TableName Any [ Field.Greater "NumValue" 15 ] Expect.hasLength docs 2 "There should have been two documents returned" } testTask "succeeds when documents are found using IN with numeric field" { use! db = SqliteDb.BuildDb() do! loadDocs () - let! docs = Find.byFields SqliteDb.TableName All [ Field.IN "NumValue" [ 2; 4; 6; 8 ] ] + let! docs = Find.byFields SqliteDb.TableName All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ] Expect.hasLength docs 1 "There should have been one document returned" } testTask "succeeds when documents are not found" { use! db = SqliteDb.BuildDb() do! loadDocs () - let! docs = Find.byFields SqliteDb.TableName Any [ Field.GT "NumValue" 100 ] + let! docs = Find.byFields SqliteDb.TableName Any [ Field.Greater "NumValue" 100 ] Expect.isTrue (List.isEmpty docs) "There should have been no documents returned" } ] @@ -539,7 +539,7 @@ let findTests = testList "Find" [ let! docs = Find.byFieldsOrdered - SqliteDb.TableName Any [ Field.GT "NumValue" 15 ] [ Field.Named "Id" ] + SqliteDb.TableName Any [ Field.Greater "NumValue" 15 ] [ Field.Named "Id" ] Expect.hasLength docs 2 "There should have been two documents returned" Expect.equal (docs |> List.map _.Id |> String.concat "|") "five|four" "The documents were not ordered correctly" @@ -550,7 +550,7 @@ let findTests = testList "Find" [ let! docs = Find.byFieldsOrdered - SqliteDb.TableName Any [ Field.GT "NumValue" 15 ] [ Field.Named "Id DESC" ] + SqliteDb.TableName Any [ Field.Greater "NumValue" 15 ] [ Field.Named "Id DESC" ] Expect.hasLength docs 2 "There should have been two documents returned" Expect.equal (docs |> List.map _.Id |> String.concat "|") "four|five" "The documents were not ordered correctly" @@ -561,7 +561,7 @@ let findTests = testList "Find" [ let! docs = Find.byFieldsOrdered - SqliteDb.TableName All [ Field.LE "NumValue" 10 ] [ Field.Named "Value" ] + SqliteDb.TableName All [ Field.LessOrEqual "NumValue" 10 ] [ Field.Named "Value" ] Expect.hasLength docs 3 "There should have been three documents returned" Expect.equal (docs |> List.map _.Id |> String.concat "|") "three|one|two" "Documents not ordered correctly" @@ -572,7 +572,7 @@ let findTests = testList "Find" [ let! docs = Find.byFieldsOrdered - SqliteDb.TableName All [ Field.LE "NumValue" 10 ] [ Field.Named "i:Value" ] + SqliteDb.TableName All [ Field.LessOrEqual "NumValue" 10 ] [ Field.Named "i:Value" ] Expect.hasLength docs 3 "There should have been three documents returned" Expect.equal (docs |> List.map _.Id |> String.concat "|") "three|two|one" "Documents not ordered correctly" @@ -583,7 +583,7 @@ let findTests = testList "Find" [ use! db = SqliteDb.BuildDb() do! loadDocs () - let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.EQ "Value" "another" ] + let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.Equal "Value" "another" ] Expect.isSome doc "There should have been a document returned" Expect.equal doc.Value.Id "two" "The incorrect document was returned" } @@ -591,7 +591,7 @@ let findTests = testList "Find" [ use! db = SqliteDb.BuildDb() do! loadDocs () - let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.EQ "Sub.Foo" "green" ] + let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.Equal "Sub.Foo" "green" ] Expect.isSome doc "There should have been a document returned" Expect.contains [ "two"; "four" ] doc.Value.Id "An incorrect document was returned" } @@ -599,7 +599,7 @@ let findTests = testList "Find" [ use! db = SqliteDb.BuildDb() do! loadDocs () - let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.EQ "Value" "absent" ] + let! doc = Find.firstByFields SqliteDb.TableName Any [ Field.Equal "Value" "absent" ] Expect.isNone doc "There should not have been a document returned" } ] @@ -610,7 +610,7 @@ let findTests = testList "Find" [ let! doc = Find.firstByFieldsOrdered - SqliteDb.TableName Any [ Field.EQ "Sub.Foo" "green" ] [ Field.Named "Sub.Bar" ] + SqliteDb.TableName Any [ Field.Equal "Sub.Foo" "green" ] [ Field.Named "Sub.Bar" ] Expect.isSome doc "There should have been a document returned" Expect.equal "two" doc.Value.Id "An incorrect document was returned" } @@ -620,7 +620,7 @@ let findTests = testList "Find" [ let! doc = Find.firstByFieldsOrdered - SqliteDb.TableName Any [ Field.EQ "Sub.Foo" "green" ] [ Field.Named "Sub.Bar DESC" ] + SqliteDb.TableName Any [ Field.Equal "Sub.Foo" "green" ] [ Field.Named "Sub.Bar DESC" ] Expect.isSome doc "There should have been a document returned" Expect.equal "four" doc.Value.Id "An incorrect document was returned" } @@ -703,8 +703,8 @@ let patchTests = testList "Patch" [ use! db = SqliteDb.BuildDb() do! loadDocs () - do! Patch.byFields SqliteDb.TableName Any [ Field.EQ "Value" "purple" ] {| NumValue = 77 |} - let! after = Count.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 77 ] + do! Patch.byFields SqliteDb.TableName Any [ Field.Equal "Value" "purple" ] {| NumValue = 77 |} + let! after = Count.byFields SqliteDb.TableName Any [ Field.Equal "NumValue" 77 ] Expect.equal after 2L "There should have been 2 documents returned" } testTask "succeeds when no document is updated" { @@ -714,7 +714,7 @@ let patchTests = testList "Patch" [ Expect.isEmpty before "There should have been no documents returned" // This not raising an exception is the test - do! Patch.byFields SqliteDb.TableName Any [ Field.EQ "Value" "burgundy" ] {| Foo = "green" |} + do! Patch.byFields SqliteDb.TableName Any [ Field.Equal "Value" "burgundy" ] {| Foo = "green" |} } ] ] @@ -753,7 +753,7 @@ let removeFieldsTests = testList "RemoveFields" [ use! db = SqliteDb.BuildDb() do! loadDocs () - do! RemoveFields.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 17 ] [ "Sub" ] + do! RemoveFields.byFields SqliteDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Sub" ] try let! _ = Find.byId SqliteDb.TableName "four" Expect.isTrue false "The updated document should have failed to parse" @@ -766,13 +766,13 @@ let removeFieldsTests = testList "RemoveFields" [ do! loadDocs () // This not raising an exception is the test - do! RemoveFields.byFields SqliteDb.TableName Any [ Field.EQ "NumValue" 17 ] [ "Nothing" ] + do! RemoveFields.byFields SqliteDb.TableName Any [ Field.Equal "NumValue" 17 ] [ "Nothing" ] } testTask "succeeds when no document is matched" { use! db = SqliteDb.BuildDb() // This not raising an exception is the test - do! RemoveFields.byFields SqliteDb.TableName Any [ Field.NE "Abracadabra" "apple" ] [ "Value" ] + do! RemoveFields.byFields SqliteDb.TableName Any [ Field.NotEqual "Abracadabra" "apple" ] [ "Value" ] } ] ] @@ -802,7 +802,7 @@ let deleteTests = testList "Delete" [ use! db = SqliteDb.BuildDb() do! loadDocs () - do! Delete.byFields SqliteDb.TableName Any [ Field.NE "Value" "purple" ] + do! Delete.byFields SqliteDb.TableName Any [ Field.NotEqual "Value" "purple" ] let! remaining = Count.all SqliteDb.TableName Expect.equal remaining 2L "There should have been 2 documents remaining" } @@ -810,7 +810,7 @@ let deleteTests = testList "Delete" [ use! db = SqliteDb.BuildDb() do! loadDocs () - do! Delete.byFields SqliteDb.TableName Any [ Field.EQ "Value" "crimson" ] + do! Delete.byFields SqliteDb.TableName Any [ Field.Equal "Value" "crimson" ] let! remaining = Count.all SqliteDb.TableName Expect.equal remaining 5L "There should have been 5 documents remaining" } -- 2.45.1 From 0aa91b8a00ab3990a1c7baecbadf9a4166186308 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Sun, 15 Sep 2024 23:09:20 -0400 Subject: [PATCH 5/7] WIP on InArray comparison --- src/Common/Library.fs | 62 ++++++++++++++++++--------- src/Postgres/Library.fs | 12 +++--- src/Sqlite/Library.fs | 16 ++++--- src/Tests.CSharp/CommonCSharpTests.cs | 41 ++++++++++-------- src/Tests/CommonTests.fs | 36 ++++++++-------- 5 files changed, 97 insertions(+), 70 deletions(-) diff --git a/src/Common/Library.fs b/src/Common/Library.fs index c50f815..735b033 100644 --- a/src/Common/Library.fs +++ b/src/Common/Library.fs @@ -5,23 +5,23 @@ open System.Security.Cryptography /// The types of comparisons available for JSON fields type Comparison = /// Equals (=) - | Equal of obj + | Equal of Value: obj /// Greater Than (>) - | Greater of obj + | Greater of Value: obj /// Greater Than or Equal To (>=) - | GreaterOrEqual of obj + | GreaterOrEqual of Value: obj /// Less Than (<) - | Less of obj + | Less of Value: obj /// Less Than or Equal To (<=) - | LessOrEqual of obj + | LessOrEqual of Value: obj /// Not Equal to (<>) - | NotEqual of obj + | NotEqual of Value: obj /// Between (BETWEEN) - | Between of obj * obj + | Between of Min: obj * Max: obj /// In (IN) - | In of obj seq - // Array Contains (PostgreSQL: |? SQLite: EXISTS / json_each / IN) - | Contains of obj + | In of Values: obj seq + /// In Array (PostgreSQL: |?, SQLite: EXISTS / json_each / IN) + | InArray of Table: string * Values: obj seq /// Exists (IS NOT NULL) | Exists /// Does Not Exist (IS NULL) @@ -38,7 +38,7 @@ type Comparison = | NotEqual _ -> "<>" | Between _ -> "BETWEEN" | In _ -> "IN" - | Contains _ -> "|?" // PostgreSQL only; SQL needs a subquery for this + | InArray _ -> "|?" // PostgreSQL only; SQL needs a subquery for this | Exists -> "IS NOT NULL" | NotExists -> "IS NULL" @@ -49,6 +49,16 @@ type Dialect = | PostgreSQL | SQLite + +/// The format in which an element of a JSON field should be extracted +[] +type FieldFormat = + /// Use ->> or #>>; extracts a text (PostgreSQL) or SQL (SQLite) value + | AsSql + /// Use -> or #>; extracts a JSONB (PostgreSQL) or JSON (SQLite) value + | AsJson + + /// Criteria for a field WHERE clause type Field = { /// The name of the field @@ -139,13 +149,20 @@ with static member NEX name = Field.NotExists name /// 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 format = let path = if name.Contains '.' then match dialect with - | PostgreSQL -> "#>>'{" + String.concat "," (name.Split '.') + "}'" - | SQLite -> "->>'" + String.concat "'->>'" (name.Split '.') + "'" - else $"->>'{name}'" + | PostgreSQL -> + (match format with AsJson -> "#>" | AsSql -> "#>>") + + "'{" + String.concat "," (name.Split '.') + "}'" + | SQLite -> + let parts = name.Split '.' + let last = Array.last parts + let final = (match format with AsJson -> "'->'" | AsSql -> "'->>'") + $"{last}'" + "->'" + String.concat "'->'" (Array.truncate (Array.length parts - 1) parts) + final + else + match format with AsJson -> $"->'{name}'" | AsSql -> $"->>'{name}'" $"data{path}" /// Create a field with a given name, but no other properties filled (op will be EQ, value will be "") @@ -161,8 +178,9 @@ with { this with Qualifier = Some alias } /// Get the qualified path to the field - member this.Path dialect = - (this.Qualifier |> Option.map (fun q -> $"{q}.") |> Option.defaultValue "") + Field.NameToPath this.Name dialect + member this.Path dialect format = + (this.Qualifier |> Option.map (fun q -> $"{q}.") |> Option.defaultValue "") + + Field.NameToPath this.Name dialect format /// How fields should be matched @@ -378,7 +396,7 @@ module Query = let parts = it.Split ' ' let fieldName = if Array.length parts = 1 then it else parts[0] let direction = if Array.length parts < 2 then "" else $" {parts[1]}" - $"({Field.NameToPath fieldName dialect}){direction}") + $"({Field.NameToPath fieldName dialect AsSql}){direction}") |> String.concat ", " $"CREATE INDEX IF NOT EXISTS idx_{tbl}_%s{indexName} ON {tableName} ({jsonFields})" @@ -444,11 +462,13 @@ module Query = |> Seq.map (fun (field, direction) -> if field.Name.StartsWith "n:" then let f = { field with Name = field.Name[2..] } - match dialect with PostgreSQL -> $"({f.Path PostgreSQL})::numeric" | SQLite -> f.Path SQLite + match dialect with + | PostgreSQL -> $"({f.Path PostgreSQL AsSql})::numeric" + | SQLite -> f.Path SQLite AsSql elif field.Name.StartsWith "i:" then - let p = { field with Name = field.Name[2..] }.Path dialect + let p = { field with Name = field.Name[2..] }.Path dialect AsSql match dialect with PostgreSQL -> $"LOWER({p})" | SQLite -> $"{p} COLLATE NOCASE" - else field.Path dialect + else field.Path dialect AsSql |> function path -> path + defaultArg direction "") |> String.concat ", " |> function it -> $" ORDER BY {it}" diff --git a/src/Postgres/Library.fs b/src/Postgres/Library.fs index 0cfb7b8..4b4b3c2 100644 --- a/src/Postgres/Library.fs +++ b/src/Postgres/Library.fs @@ -100,7 +100,9 @@ module Parameters = |> Seq.mapi (fun idx v -> let paramName = $"{p}_{idx}" paramName, Sql.parameter (NpgsqlParameter(paramName, v))) - | Contains _ -> () // TODO + | InArray (_, values) -> + let p = name.Derive it.ParameterName + yield (p, Sql.stringArray (values |> Seq.map string |> Array.ofSeq)) | Equal v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v -> let p = name.Derive it.ParameterName yield (p, parameterFor v (fun l -> Sql.parameter (NpgsqlParameter(p, l)))) }) @@ -137,7 +139,8 @@ module Query = fields |> Seq.map (fun it -> match it.Comparison with - | Exists | NotExists -> $"{it.Path PostgreSQL} {it.Comparison.OpSql}" + | Exists | NotExists -> $"{it.Path PostgreSQL AsSql} {it.Comparison.OpSql}" + | InArray _ -> $"{it.Path PostgreSQL AsJson} {it.Comparison.OpSql} {name.Derive it.ParameterName}" | _ -> let p = name.Derive it.ParameterName let param, value = @@ -146,12 +149,11 @@ module Query = | In values -> let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", " $"({paramNames})", defaultArg (Seq.tryHead values) (obj ()) - | Contains _ -> p, "" // TODO: may need to use -> vs ->> in field SQL | Equal v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v -> p, v | _ -> p, "" if isNumeric value then - $"({it.Path PostgreSQL})::numeric {it.Comparison.OpSql} {param}" - else $"{it.Path PostgreSQL} {it.Comparison.OpSql} {param}") + $"({it.Path PostgreSQL AsSql})::numeric {it.Comparison.OpSql} {param}" + else $"{it.Path PostgreSQL AsSql} {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 69f4e8a..28e8080 100644 --- a/src/Sqlite/Library.fs +++ b/src/Sqlite/Library.fs @@ -38,16 +38,19 @@ module Query = fields |> Seq.map (fun it -> match it.Comparison with - | Exists | NotExists -> $"{it.Path SQLite} {it.Comparison.OpSql}" + | Exists | NotExists -> $"{it.Path SQLite AsSql} {it.Comparison.OpSql}" | Between _ -> let p = name.Derive it.ParameterName - $"{it.Path SQLite} {it.Comparison.OpSql} {p}min AND {p}max" + $"{it.Path SQLite AsSql} {it.Comparison.OpSql} {p}min AND {p}max" | In values -> let p = 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}") + $"{it.Path SQLite AsSql} {it.Comparison.OpSql} ({paramNames})" + | InArray (table, values) -> + let p = name.Derive it.ParameterName + let paramNames = values |> Seq.mapi (fun idx _ -> $"{p}_{idx}") |> String.concat ", " + $"EXISTS (SELECT 1 FROM json_each({table}.data, '$.{it.Name}') WHERE value IN ({paramNames}))" + | _ -> $"{it.Path SQLite AsSql} {it.Comparison.OpSql} {name.Derive it.ParameterName}") |> String.concat $" {howMatched} " /// Create a WHERE clause fragment to implement an ID-based query @@ -113,10 +116,9 @@ module Parameters = | Between (min, max) -> let p = name.Derive it.ParameterName yield! [ SqliteParameter($"{p}min", min); SqliteParameter($"{p}max", max) ] - | In values -> + | In values | InArray (_, values) -> let p = name.Derive it.ParameterName yield! values |> Seq.mapi (fun idx v -> SqliteParameter($"{p}_{idx}", v)) - | Contains _ -> () // TODO | Equal v | Greater v | GreaterOrEqual v | Less v | LessOrEqual v | NotEqual v -> yield SqliteParameter(name.Derive it.ParameterName, v) }) |> Seq.collect id diff --git a/src/Tests.CSharp/CommonCSharpTests.cs b/src/Tests.CSharp/CommonCSharpTests.cs index 75b6400..ecfffa6 100644 --- a/src/Tests.CSharp/CommonCSharpTests.cs +++ b/src/Tests.CSharp/CommonCSharpTests.cs @@ -57,9 +57,9 @@ public static class CommonCSharpTests { Expect.equal(Comparison.NewIn([]).OpSql, "IN", "The In SQL was not correct"); }), - TestCase("Contains succeeds", () => + TestCase("InArray succeeds", () => { - Expect.equal(Comparison.NewContains("").OpSql, "|?", "The Contains SQL was not correct"); + Expect.equal(Comparison.NewInArray("", []).OpSql, "|?", "The InArray SQL was not correct"); }), TestCase("Exists succeeds", () => { @@ -123,7 +123,7 @@ public static class CommonCSharpTests 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"); + Expect.sequenceEqual(((Comparison.In)field.Comparison).Values, [8, 16, 32], "Value incorrect"); }), TestCase("Exists succeeds", () => { @@ -141,24 +141,24 @@ public static class CommonCSharpTests [ TestCase("succeeds for PostgreSQL and a simple name", () => { - Expect.equal("data->>'Simple'", Field.NameToPath("Simple", Dialect.PostgreSQL), + Expect.equal("data->>'Simple'", Field.NameToPath("Simple", Dialect.PostgreSQL, FieldFormat.AsSql), "Path not constructed correctly"); }), TestCase("succeeds for SQLite and a simple name", () => { - Expect.equal("data->>'Simple'", Field.NameToPath("Simple", Dialect.SQLite), + Expect.equal("data->>'Simple'", Field.NameToPath("Simple", Dialect.SQLite, FieldFormat.AsSql), "Path not constructed correctly"); }), TestCase("succeeds for PostgreSQL and a nested name", () => { Expect.equal("data#>>'{A,Long,Path,to,the,Property}'", - Field.NameToPath("A.Long.Path.to.the.Property", Dialect.PostgreSQL), + Field.NameToPath("A.Long.Path.to.the.Property", Dialect.PostgreSQL, FieldFormat.AsSql), "Path not constructed correctly"); }), TestCase("succeeds for SQLite and a nested name", () => { - Expect.equal("data->>'A'->>'Long'->>'Path'->>'to'->>'the'->>'Property'", - Field.NameToPath("A.Long.Path.to.the.Property", Dialect.SQLite), + Expect.equal("data->'A'->'Long'->'Path'->'to'->'the'->>'Property'", + Field.NameToPath("A.Long.Path.to.the.Property", Dialect.SQLite, FieldFormat.AsSql), "Path not constructed correctly"); }) ]), @@ -179,47 +179,50 @@ public static class CommonCSharpTests TestCase("succeeds for a PostgreSQL single field with no qualifier", () => { var field = Field.GreaterOrEqual("SomethingCool", 18); - Expect.equal("data->>'SomethingCool'", field.Path(Dialect.PostgreSQL), + Expect.equal("data->>'SomethingCool'", field.Path(Dialect.PostgreSQL, FieldFormat.AsSql), "The PostgreSQL path is incorrect"); }), TestCase("succeeds for a PostgreSQL single field with a qualifier", () => { var field = Field.Less("SomethingElse", 9).WithQualifier("this"); - Expect.equal("this.data->>'SomethingElse'", field.Path(Dialect.PostgreSQL), + Expect.equal("this.data->>'SomethingElse'", field.Path(Dialect.PostgreSQL, FieldFormat.AsSql), "The PostgreSQL path is incorrect"); }), TestCase("succeeds for a PostgreSQL nested field with no qualifier", () => { var field = Field.Equal("My.Nested.Field", "howdy"); - Expect.equal("data#>>'{My,Nested,Field}'", field.Path(Dialect.PostgreSQL), + Expect.equal("data#>>'{My,Nested,Field}'", field.Path(Dialect.PostgreSQL, FieldFormat.AsSql), "The PostgreSQL path is incorrect"); }), TestCase("succeeds for a PostgreSQL nested field with a qualifier", () => { var field = Field.Equal("Nest.Away", "doc").WithQualifier("bird"); - Expect.equal("bird.data#>>'{Nest,Away}'", field.Path(Dialect.PostgreSQL), + Expect.equal("bird.data#>>'{Nest,Away}'", field.Path(Dialect.PostgreSQL, FieldFormat.AsSql), "The PostgreSQL path is incorrect"); }), TestCase("succeeds for a SQLite single field with no qualifier", () => { var field = Field.GreaterOrEqual("SomethingCool", 18); - Expect.equal("data->>'SomethingCool'", field.Path(Dialect.SQLite), "The SQLite path is incorrect"); + Expect.equal("data->>'SomethingCool'", field.Path(Dialect.SQLite, FieldFormat.AsSql), + "The SQLite path is incorrect"); }), TestCase("succeeds for a SQLite single field with a qualifier", () => { var field = Field.Less("SomethingElse", 9).WithQualifier("this"); - Expect.equal("this.data->>'SomethingElse'", field.Path(Dialect.SQLite), "The SQLite path is incorrect"); + Expect.equal("this.data->>'SomethingElse'", field.Path(Dialect.SQLite, FieldFormat.AsSql), + "The SQLite path is incorrect"); }), TestCase("succeeds for a SQLite nested field with no qualifier", () => { var field = Field.Equal("My.Nested.Field", "howdy"); - Expect.equal("data->>'My'->>'Nested'->>'Field'", field.Path(Dialect.SQLite), + Expect.equal("data->'My'->'Nested'->>'Field'", field.Path(Dialect.SQLite, FieldFormat.AsSql), "The SQLite path is incorrect"); }), TestCase("succeeds for a SQLite nested field with a qualifier", () => { var field = Field.Equal("Nest.Away", "doc").WithQualifier("bird"); - Expect.equal("bird.data->>'Nest'->>'Away'", field.Path(Dialect.SQLite), "The SQLite path is incorrect"); + Expect.equal("bird.data->'Nest'->>'Away'", field.Path(Dialect.SQLite, FieldFormat.AsSql), + "The SQLite path is incorrect"); }) ]) ]); @@ -536,7 +539,7 @@ public static class CommonCSharpTests { Expect.equal( Query.Definition.EnsureIndexOn("tbl", "nest", ["a.b.c"], Dialect.SQLite), - "CREATE INDEX IF NOT EXISTS idx_tbl_nest ON tbl ((data->>'a'->>'b'->>'c'))", + "CREATE INDEX IF NOT EXISTS idx_tbl_nest ON tbl ((data->'a'->'b'->>'c'))", "CREATE INDEX for nested SQLite field incorrect"); }) ]) @@ -608,7 +611,7 @@ public static class CommonCSharpTests Field.Named("Nested.Test.Field DESC"), Field.Named("AnotherField"), Field.Named("It DESC") ], Dialect.SQLite), - " ORDER BY data->>'Nested'->>'Test'->>'Field' DESC, data->>'AnotherField', data->>'It' DESC", + " ORDER BY data->'Nested'->'Test'->>'Field' DESC, data->>'AnotherField', data->>'It' DESC", "Order By not constructed correctly"); }), TestCase("succeeds for PostgreSQL numeric fields", () => @@ -630,7 +633,7 @@ public static class CommonCSharpTests TestCase("succeeds for SQLite case-insensitive ordering", () => { Expect.equal(Query.OrderBy([Field.Named("i:Test.Field ASC NULLS LAST")], Dialect.SQLite), - " ORDER BY data->>'Test'->>'Field' COLLATE NOCASE ASC NULLS LAST", + " ORDER BY data->'Test'->>'Field' COLLATE NOCASE ASC NULLS LAST", "Order By not constructed correctly for case-insensitive field"); }) ]) diff --git a/src/Tests/CommonTests.fs b/src/Tests/CommonTests.fs index 7230af8..00a738d 100644 --- a/src/Tests/CommonTests.fs +++ b/src/Tests/CommonTests.fs @@ -32,8 +32,8 @@ let comparisonTests = testList "Comparison.OpSql" [ test "In succeeds" { Expect.equal (In []).OpSql "IN" "The In SQL was not correct" } - test "Contains succeeds" { - Expect.equal (Contains "").OpSql "|?" "The Contains SQL was not correct" + test "InArray succeeds" { + Expect.equal (InArray("", [])).OpSql "|?" "The InArray SQL was not correct" } test "Exists succeeds" { Expect.equal Exists.OpSql "IS NOT NULL" "The Exists SQL was not correct" @@ -117,21 +117,21 @@ let fieldTests = testList "Field" [ } testList "NameToPath" [ test "succeeds for PostgreSQL and a simple name" { - Expect.equal "data->>'Simple'" (Field.NameToPath "Simple" PostgreSQL) "Path not constructed correctly" + Expect.equal "data->>'Simple'" (Field.NameToPath "Simple" PostgreSQL AsSql) "Path not constructed correctly" } test "succeeds for SQLite and a simple name" { - Expect.equal "data->>'Simple'" (Field.NameToPath "Simple" SQLite) "Path not constructed correctly" + Expect.equal "data->>'Simple'" (Field.NameToPath "Simple" SQLite AsSql) "Path not constructed correctly" } test "succeeds for PostgreSQL and a nested name" { Expect.equal "data#>>'{A,Long,Path,to,the,Property}'" - (Field.NameToPath "A.Long.Path.to.the.Property" PostgreSQL) + (Field.NameToPath "A.Long.Path.to.the.Property" PostgreSQL AsSql) "Path not constructed correctly" } test "succeeds for SQLite and a nested name" { Expect.equal - "data->>'A'->>'Long'->>'Path'->>'to'->>'the'->>'Property'" - (Field.NameToPath "A.Long.Path.to.the.Property" SQLite) + "data->'A'->'Long'->'Path'->'to'->'the'->>'Property'" + (Field.NameToPath "A.Long.Path.to.the.Property" SQLite AsSql) "Path not constructed correctly" } ] @@ -148,35 +148,35 @@ let fieldTests = testList "Field" [ testList "Path" [ test "succeeds for a PostgreSQL single field with no qualifier" { let field = Field.GreaterOrEqual "SomethingCool" 18 - Expect.equal "data->>'SomethingCool'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" + Expect.equal "data->>'SomethingCool'" (field.Path PostgreSQL AsSql) "The PostgreSQL path is incorrect" } test "succeeds for a PostgreSQL single field with a qualifier" { let field = { Field.Less "SomethingElse" 9 with Qualifier = Some "this" } - Expect.equal "this.data->>'SomethingElse'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" + Expect.equal "this.data->>'SomethingElse'" (field.Path PostgreSQL AsSql) "The PostgreSQL path is incorrect" } test "succeeds for a PostgreSQL nested field with no qualifier" { let field = Field.Equal "My.Nested.Field" "howdy" - Expect.equal "data#>>'{My,Nested,Field}'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" + Expect.equal "data#>>'{My,Nested,Field}'" (field.Path PostgreSQL AsSql) "The PostgreSQL path is incorrect" } test "succeeds for a PostgreSQL nested field with a qualifier" { let field = { Field.Equal "Nest.Away" "doc" with Qualifier = Some "bird" } - Expect.equal "bird.data#>>'{Nest,Away}'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" + Expect.equal "bird.data#>>'{Nest,Away}'" (field.Path PostgreSQL AsSql) "The PostgreSQL path is incorrect" } test "succeeds for a SQLite single field with no qualifier" { let field = Field.GreaterOrEqual "SomethingCool" 18 - Expect.equal "data->>'SomethingCool'" (field.Path SQLite) "The SQLite path is incorrect" + Expect.equal "data->>'SomethingCool'" (field.Path SQLite AsSql) "The SQLite path is incorrect" } test "succeeds for a SQLite single field with a qualifier" { let field = { Field.Less "SomethingElse" 9 with Qualifier = Some "this" } - Expect.equal "this.data->>'SomethingElse'" (field.Path SQLite) "The SQLite path is incorrect" + Expect.equal "this.data->>'SomethingElse'" (field.Path SQLite AsSql) "The SQLite path is incorrect" } test "succeeds for a SQLite nested field with no qualifier" { let field = Field.Equal "My.Nested.Field" "howdy" - Expect.equal "data->>'My'->>'Nested'->>'Field'" (field.Path SQLite) "The SQLite path is incorrect" + Expect.equal "data->'My'->'Nested'->>'Field'" (field.Path SQLite AsSql) "The SQLite path is incorrect" } test "succeeds for a SQLite nested field with a qualifier" { let field = { Field.Equal "Nest.Away" "doc" with Qualifier = Some "bird" } - Expect.equal "bird.data->>'Nest'->>'Away'" (field.Path SQLite) "The SQLite path is incorrect" + Expect.equal "bird.data->'Nest'->>'Away'" (field.Path SQLite AsSql) "The SQLite path is incorrect" } ] ] @@ -379,7 +379,7 @@ let queryTests = testList "Query" [ test "succeeds for nested SQLite field" { Expect.equal (Query.Definition.ensureIndexOn tbl "nest" [ "a.b.c" ] SQLite) - $"CREATE INDEX IF NOT EXISTS idx_{tbl}_nest ON {tbl} ((data->>'a'->>'b'->>'c'))" + $"CREATE INDEX IF NOT EXISTS idx_{tbl}_nest ON {tbl} ((data->'a'->'b'->>'c'))" "CREATE INDEX for nested SQLite field incorrect" } ] @@ -441,7 +441,7 @@ let queryTests = testList "Query" [ (Query.orderBy [ Field.Named "Nested.Test.Field DESC"; Field.Named "AnotherField"; Field.Named "It DESC" ] SQLite) - " ORDER BY data->>'Nested'->>'Test'->>'Field' DESC, data->>'AnotherField', data->>'It' DESC" + " ORDER BY data->'Nested'->'Test'->>'Field' DESC, data->>'AnotherField', data->>'It' DESC" "Order By not constructed correctly" } test "succeeds for PostgreSQL numeric fields" { @@ -465,7 +465,7 @@ let queryTests = testList "Query" [ test "succeeds for SQLite case-insensitive ordering" { Expect.equal (Query.orderBy [ Field.Named "i:Test.Field ASC NULLS LAST" ] SQLite) - " ORDER BY data->>'Test'->>'Field' COLLATE NOCASE ASC NULLS LAST" + " ORDER BY data->'Test'->>'Field' COLLATE NOCASE ASC NULLS LAST" "Order By not constructed correctly for case-insensitive field" } ] -- 2.45.1 From 1c5b8042de30a2653bdbfbb953936f9d5a1b308f Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Mon, 16 Sep 2024 21:49:09 -0400 Subject: [PATCH 6/7] Add tests for InArray comparison --- src/Common/Library.fs | 18 ++++++---- src/Tests.CSharp/CommonCSharpTests.cs | 11 ++++++- src/Tests.CSharp/PostgresCSharpTests.cs | 40 ++++++++++++++++++---- src/Tests.CSharp/SqliteCSharpTests.cs | 32 ++++++++++++++++++ src/Tests.CSharp/Types.cs | 16 +++++++++ src/Tests/CommonTests.fs | 9 ++++- src/Tests/PostgresTests.fs | 44 ++++++++++++++++++++----- src/Tests/SqliteTests.fs | 40 ++++++++++++++++++---- src/Tests/Types.fs | 26 +++++++++++---- 9 files changed, 197 insertions(+), 39 deletions(-) diff --git a/src/Common/Library.fs b/src/Common/Library.fs index 735b033..6853457 100644 --- a/src/Common/Library.fs +++ b/src/Common/Library.fs @@ -38,7 +38,7 @@ type Comparison = | NotEqual _ -> "<>" | Between _ -> "BETWEEN" | In _ -> "IN" - | InArray _ -> "|?" // PostgreSQL only; SQL needs a subquery for this + | InArray _ -> "?|" // PostgreSQL only; SQL needs a subquery for this | Exists -> "IS NOT NULL" | NotExists -> "IS NULL" @@ -120,20 +120,24 @@ with /// Create a not equals (<>) field criterion (alias) static member NE name (value: obj) = Field.NotEqual name value - /// Create a BETWEEN field criterion + /// Create a Between field criterion static member Between name (min: obj) (max: obj) = Field.Where name (Between(min, max)) - /// Create a BETWEEN field criterion (alias) + /// Create a Between field criterion (alias) static member BT name (min: obj) (max: obj) = Field.Between name min max - /// Create an IN field criterion + /// Create an In field criterion static member In name (values: obj seq) = Field.Where name (In values) - - /// Create an IN field criterion (alias) + + /// Create an In field criterion (alias) static member IN name (values: obj seq) = Field.In name values - + + /// Create an InArray field criterion + static member InArray name tableName (values: obj seq) = + Field.Where name (InArray(tableName, values)) + /// Create an exists (IS NOT NULL) field criterion static member Exists name = Field.Where name Exists diff --git a/src/Tests.CSharp/CommonCSharpTests.cs b/src/Tests.CSharp/CommonCSharpTests.cs index ecfffa6..911b732 100644 --- a/src/Tests.CSharp/CommonCSharpTests.cs +++ b/src/Tests.CSharp/CommonCSharpTests.cs @@ -59,7 +59,7 @@ public static class CommonCSharpTests }), TestCase("InArray succeeds", () => { - Expect.equal(Comparison.NewInArray("", []).OpSql, "|?", "The InArray SQL was not correct"); + Expect.equal(Comparison.NewInArray("", []).OpSql, "?|", "The InArray SQL was not correct"); }), TestCase("Exists succeeds", () => { @@ -125,6 +125,15 @@ public static class CommonCSharpTests Expect.isTrue(field.Comparison.IsIn, "Comparison incorrect"); Expect.sequenceEqual(((Comparison.In)field.Comparison).Values, [8, 16, 32], "Value incorrect"); }), + TestCase("InArray succeeds", () => + { + var field = Field.InArray("ArrayField", "table", ["x", "y", "z"]); + Expect.equal(field.Name, "ArrayField", "Field name incorrect"); + Expect.isTrue(field.Comparison.IsInArray, "Comparison incorrect"); + var it = (Comparison.InArray)field.Comparison; + Expect.equal(it.Table, "table", "Table name incorrect"); + Expect.sequenceEqual(it.Values, ["x", "y", "z"], "Value incorrect"); + }), TestCase("Exists succeeds", () => { var field = Field.Exists("Groovy"); diff --git a/src/Tests.CSharp/PostgresCSharpTests.cs b/src/Tests.CSharp/PostgresCSharpTests.cs index 570fdfd..3a95a2c 100644 --- a/src/Tests.CSharp/PostgresCSharpTests.cs +++ b/src/Tests.CSharp/PostgresCSharpTests.cs @@ -184,40 +184,40 @@ public static class PostgresCSharpTests [ TestList("WhereByFields", [ - TestCase("succeeds for a single field when a logical operator is passed", () => + TestCase("succeeds for a single field when a logical comparison is passed", () => { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.Any, [Field.Greater("theField", "0").WithParameterName("@test")]), "data->>'theField' > @test", "WHERE clause not correct"); }), - TestCase("succeeds for a single field when an existence operator is passed", () => + TestCase("succeeds for a single field when an existence comparison is passed", () => { Expect.equal(Postgres.Query.WhereByFields(FieldMatch.Any, [Field.NotExists("thatField")]), "data->>'thatField' IS NULL", "WHERE clause not correct"); }), - TestCase("succeeds for a single field when a between operator is passed with numeric values", () => + TestCase("succeeds for a single field when a between comparison is passed with numeric values", () => { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.All, [Field.Between("aField", 50, 99).WithParameterName("@range")]), "(data->>'aField')::numeric BETWEEN @rangemin AND @rangemax", "WHERE clause not correct"); }), - TestCase("succeeds for a single field when a between operator is passed with non-numeric values", () => + TestCase("succeeds for a single field when a between comparison is passed with non-numeric values", () => { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.Any, [Field.Between("field0", "a", "b").WithParameterName("@alpha")]), "data->>'field0' BETWEEN @alphamin AND @alphamax", "WHERE clause not correct"); }), - TestCase("succeeds for all multiple fields with logical operators", () => + TestCase("succeeds for all multiple fields with logical comparisons", () => { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.All, [Field.Equal("theFirst", "1"), Field.Equal("numberTwo", "2")]), "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1", "WHERE clause not correct"); }), - TestCase("succeeds for any multiple fields with an existence operator", () => + TestCase("succeeds for any multiple fields with an existence comparison", () => { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.Any, @@ -225,13 +225,19 @@ public static class PostgresCSharpTests "data->>'thatField' IS NULL OR (data->>'thisField')::numeric >= @field0", "WHERE clause not correct"); }), - TestCase("succeeds for all multiple fields with between operators", () => + TestCase("succeeds for all multiple fields with between comparisons", () => { Expect.equal( Postgres.Query.WhereByFields(FieldMatch.All, [Field.Between("aField", 50, 99), Field.Between("anotherField", "a", "b")]), "(data->>'aField')::numeric BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max", "WHERE clause not correct"); + }), + TestCase("succeeds for a field with an InArray comparison", () => + { + Expect.equal( + Postgres.Query.WhereByFields(FieldMatch.All, [Field.InArray("theField", "the_table", ["q", "r"])]), + "data->'theField' ?| @field0", "WHERE clause not correct"); }) ]), TestList("WhereById", @@ -890,6 +896,26 @@ public static class PostgresCSharpTests var docs = await Find.ByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "mauve")]); Expect.isEmpty(docs, "There should have been no documents returned"); + }), + TestCase("succeeds for InArray when matching documents exist", async () => + { + await using var db = PostgresDb.BuildDb(); + await Definition.EnsureTable(PostgresDb.TableName); + foreach (var doc in ArrayDocument.TestDocuments) await Document.Insert(PostgresDb.TableName, doc); + + var docs = await Find.ByFields(PostgresDb.TableName, FieldMatch.All, + [Field.InArray("Values", PostgresDb.TableName, ["c"])]); + Expect.hasLength(docs, 2, "There should have been two document returned"); + }), + TestCase("succeeds for InArray when no matching documents exist", async () => + { + await using var db = PostgresDb.BuildDb(); + await Definition.EnsureTable(PostgresDb.TableName); + foreach (var doc in ArrayDocument.TestDocuments) await Document.Insert(PostgresDb.TableName, doc); + + var docs = await Find.ByFields(PostgresDb.TableName, FieldMatch.All, + [Field.InArray("Values", PostgresDb.TableName, ["j"])]); + Expect.isEmpty(docs, "There should have been no documents returned"); }) ]), TestList("ByFieldsOrdered", diff --git a/src/Tests.CSharp/SqliteCSharpTests.cs b/src/Tests.CSharp/SqliteCSharpTests.cs index 731a512..a9cce70 100644 --- a/src/Tests.CSharp/SqliteCSharpTests.cs +++ b/src/Tests.CSharp/SqliteCSharpTests.cs @@ -59,6 +59,18 @@ public static class SqliteCSharpTests [Field.Between("aField", 50, 99), Field.Between("anotherField", "a", "b")]), "data->>'aField' BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max", "WHERE clause not correct"); + }), + TestCase("succeeds for a field with an In comparison", () => + { + Expect.equal(Sqlite.Query.WhereByFields(FieldMatch.All, [Field.In("this", ["a", "b", "c"])]), + "data->>'this' IN (@field0_0, @field0_1, @field0_2)", "WHERE clause not correct"); + }), + TestCase("succeeds for a field with an InArray comparison", () => + { + Expect.equal( + Sqlite.Query.WhereByFields(FieldMatch.All, [Field.InArray("this", "the_table", ["a", "b"])]), + "EXISTS (SELECT 1 FROM json_each(the_table.data, '$.this') WHERE value IN (@field0_0, @field0_1))", + "WHERE clause not correct"); }) ]), TestCase("WhereById succeeds", () => @@ -619,6 +631,26 @@ public static class SqliteCSharpTests var docs = await Find.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("Value", "mauve")]); Expect.isEmpty(docs, "There should have been no documents returned"); + }), + TestCase("succeeds for InArray when matching documents exist", async () => + { + await using var db = await SqliteDb.BuildDb(); + await Definition.EnsureTable(SqliteDb.TableName); + foreach (var doc in ArrayDocument.TestDocuments) await Document.Insert(SqliteDb.TableName, doc); + + var docs = await Find.ByFields(SqliteDb.TableName, FieldMatch.All, + [Field.InArray("Values", SqliteDb.TableName, ["c"])]); + Expect.hasLength(docs, 2, "There should have been two document returned"); + }), + TestCase("succeeds for InArray when no matching documents exist", async () => + { + await using var db = await SqliteDb.BuildDb(); + await Definition.EnsureTable(SqliteDb.TableName); + foreach (var doc in ArrayDocument.TestDocuments) await Document.Insert(SqliteDb.TableName, doc); + + var docs = await Find.ByFields(SqliteDb.TableName, FieldMatch.All, + [Field.InArray("Values", SqliteDb.TableName, ["j"])]); + Expect.isEmpty(docs, "There should have been no documents returned"); }) ]), TestList("ByFieldsOrdered", diff --git a/src/Tests.CSharp/Types.cs b/src/Tests.CSharp/Types.cs index 88d8830..3acb0d0 100644 --- a/src/Tests.CSharp/Types.cs +++ b/src/Tests.CSharp/Types.cs @@ -31,3 +31,19 @@ public class JsonDocument new() { Id = "five", Value = "purple", NumValue = 18 } ]; } + +public class ArrayDocument +{ + public string Id { get; set; } = ""; + public string[] Values { get; set; } = []; + + /// + /// A set of documents used for integration tests + /// + public static readonly List TestDocuments = + [ + new() { Id = "first", Values = ["a", "b", "c"] }, + new() { Id = "second", Values = ["c", "d", "e"] }, + new() { Id = "third", Values = ["x", "y", "z"] } + ]; +} diff --git a/src/Tests/CommonTests.fs b/src/Tests/CommonTests.fs index 00a738d..95b4f2d 100644 --- a/src/Tests/CommonTests.fs +++ b/src/Tests/CommonTests.fs @@ -33,7 +33,7 @@ let comparisonTests = testList "Comparison.OpSql" [ Expect.equal (In []).OpSql "IN" "The In SQL was not correct" } test "InArray succeeds" { - Expect.equal (InArray("", [])).OpSql "|?" "The InArray SQL was not correct" + Expect.equal (InArray("", [])).OpSql "?|" "The InArray SQL was not correct" } test "Exists succeeds" { Expect.equal Exists.OpSql "IS NOT NULL" "The Exists SQL was not correct" @@ -101,6 +101,13 @@ let fieldTests = testList "Field" [ 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" + Expect.isNone field.ParameterName "The default parameter name should be None" + Expect.isNone field.Qualifier "The default table qualifier should be None" + } test "Exists succeeds" { let field = Field.Exists "Groovy" Expect.equal field.Name "Groovy" "Field name incorrect" diff --git a/src/Tests/PostgresTests.fs b/src/Tests/PostgresTests.fs index cd37e8c..6043d9c 100644 --- a/src/Tests/PostgresTests.fs +++ b/src/Tests/PostgresTests.fs @@ -135,60 +135,66 @@ let parametersTests = testList "Parameters" [ /// Unit tests for the Query module of the PostgreSQL library let queryTests = testList "Query" [ testList "whereByFields" [ - test "succeeds for a single field when a logical operator is passed" { + test "succeeds for a single field when a logical comparison is passed" { Expect.equal (Query.whereByFields Any [ { Field.Greater "theField" "0" with ParameterName = Some "@test" } ]) "data->>'theField' > @test" "WHERE clause not correct" } - test "succeeds for a single field when an existence operator is passed" { + test "succeeds for a single field when an existence comparison is passed" { Expect.equal (Query.whereByFields Any [ Field.NotExists "thatField" ]) "data->>'thatField' IS NULL" "WHERE clause not correct" } - test "succeeds for a single field when a between operator is passed with numeric values" { + test "succeeds for a single field when a between comparison is passed with numeric values" { Expect.equal (Query.whereByFields All [ { Field.Between "aField" 50 99 with ParameterName = Some "@range" } ]) "(data->>'aField')::numeric BETWEEN @rangemin AND @rangemax" "WHERE clause not correct" } - test "succeeds for a single field when a between operator is passed with non-numeric values" { + test "succeeds for a single field when a between comparison is passed with non-numeric values" { Expect.equal (Query.whereByFields Any [ { Field.Between "field0" "a" "b" with ParameterName = Some "@alpha" } ]) "data->>'field0' BETWEEN @alphamin AND @alphamax" "WHERE clause not correct" } - test "succeeds for all multiple fields with logical operators" { + test "succeeds for all multiple fields with logical comparisons" { Expect.equal (Query.whereByFields All [ Field.Equal "theFirst" "1"; Field.Equal "numberTwo" "2" ]) "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1" "WHERE clause not correct" } - test "succeeds for any multiple fields with an existence operator" { + test "succeeds for any multiple fields with an existence comparisons" { Expect.equal (Query.whereByFields Any [ Field.NotExists "thatField"; Field.GreaterOrEqual "thisField" 18 ]) "data->>'thatField' IS NULL OR (data->>'thisField')::numeric >= @field0" "WHERE clause not correct" } - test "succeeds for all multiple fields with between operators" { + test "succeeds for all multiple fields with between comparisons" { Expect.equal (Query.whereByFields All [ Field.Between "aField" 50 99; Field.Between "anotherField" "a" "b" ]) "(data->>'aField')::numeric BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max" "WHERE clause not correct" } - test "succeeds for a field with an IN operator with alphanumeric values" { + test "succeeds for a field with an In comparison with alphanumeric values" { Expect.equal (Query.whereByFields All [ Field.In "this" [ "a"; "b"; "c" ] ]) "data->>'this' IN (@field0_0, @field0_1, @field0_2)" "WHERE clause not correct" } - test "succeeds for a field with an IN operator with numeric values" { + test "succeeds for a field with an In comparison with numeric values" { Expect.equal (Query.whereByFields All [ Field.In "this" [ 7; 14; 21 ] ]) "(data->>'this')::numeric IN (@field0_0, @field0_1, @field0_2)" "WHERE clause not correct" } + test "succeeds for a field with an InArray comparison" { + Expect.equal + (Query.whereByFields All [ Field.InArray "theField" "the_table" [ "q", "r" ] ]) + "data->'theField' ?| @field0" + "WHERE clause not correct" + } ] testList "whereById" [ test "succeeds for numeric ID" { @@ -740,6 +746,26 @@ let findTests = testList "Find" [ PostgresDb.TableName All [ Field.Equal "Value" "mauve"; Field.NotEqual "NumValue" 40 ] Expect.isEmpty docs "There should have been no documents returned" } + testTask "succeeds for InArray when matching documents exist" { + use db = PostgresDb.BuildDb() + do! Definition.ensureTable PostgresDb.TableName + for doc in ArrayDocument.TestDocuments do do! insert PostgresDb.TableName doc + + let! docs = + Find.byFields + PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "c" ] ] + Expect.hasLength docs 2 "There should have been two documents returned" + } + testTask "succeeds for InArray when no matching documents exist" { + use db = PostgresDb.BuildDb() + do! Definition.ensureTable PostgresDb.TableName + for doc in ArrayDocument.TestDocuments do do! insert PostgresDb.TableName doc + + let! docs = + Find.byFields + PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "j" ] ] + Expect.isEmpty docs "There should have been no documents returned" + } ] testList "byFieldsOrdered" [ testTask "succeeds when sorting ascending" { diff --git a/src/Tests/SqliteTests.fs b/src/Tests/SqliteTests.fs index c2139af..83e1c22 100644 --- a/src/Tests/SqliteTests.fs +++ b/src/Tests/SqliteTests.fs @@ -15,48 +15,54 @@ open Types /// Unit tests for the Query module of the SQLite library let queryTests = testList "Query" [ testList "whereByFields" [ - test "succeeds for a single field when a logical operator is passed" { + test "succeeds for a single field when a logical comparison is passed" { Expect.equal (Query.whereByFields Any [ { Field.Greater "theField" 0 with ParameterName = Some "@test" } ]) "data->>'theField' > @test" "WHERE clause not correct" } - test "succeeds for a single field when an existence operator is passed" { + test "succeeds for a single field when an existence comparison is passed" { Expect.equal (Query.whereByFields Any [ Field.NotExists "thatField" ]) "data->>'thatField' IS NULL" "WHERE clause not correct" } - test "succeeds for a single field when a between operator is passed" { + test "succeeds for a single field when a between comparison is passed" { Expect.equal (Query.whereByFields All [ { Field.Between "aField" 50 99 with ParameterName = Some "@range" } ]) "data->>'aField' BETWEEN @rangemin AND @rangemax" "WHERE clause not correct" } - test "succeeds for all multiple fields with logical operators" { + test "succeeds for all multiple fields with logical comparisons" { Expect.equal (Query.whereByFields All [ Field.Equal "theFirst" "1"; Field.Equal "numberTwo" "2" ]) "data->>'theFirst' = @field0 AND data->>'numberTwo' = @field1" "WHERE clause not correct" } - test "succeeds for any multiple fields with an existence operator" { + test "succeeds for any multiple fields with an existence comparison" { Expect.equal (Query.whereByFields Any [ Field.NotExists "thatField"; Field.GreaterOrEqual "thisField" 18 ]) "data->>'thatField' IS NULL OR data->>'thisField' >= @field0" "WHERE clause not correct" } - test "succeeds for all multiple fields with between operators" { + test "succeeds for all multiple fields with between comparisons" { Expect.equal (Query.whereByFields All [ Field.Between "aField" 50 99; Field.Between "anotherField" "a" "b" ]) "data->>'aField' BETWEEN @field0min AND @field0max AND data->>'anotherField' BETWEEN @field1min AND @field1max" "WHERE clause not correct" } - test "succeeds for a field with an IN operator" { + test "succeeds for a field with an In comparison" { Expect.equal (Query.whereByFields All [ Field.In "this" [ "a"; "b"; "c" ] ]) "data->>'this' IN (@field0_0, @field0_1, @field0_2)" "WHERE clause not correct" } + test "succeeds for a field with an InArray comparison" { + Expect.equal + (Query.whereByFields All [ Field.InArray "this" "the_table" [ "a"; "b" ] ]) + "EXISTS (SELECT 1 FROM json_each(the_table.data, '$.this') WHERE value IN (@field0_0, @field0_1))" + "WHERE clause not correct" + } ] test "whereById succeeds" { Expect.equal (Query.whereById "@id") "data->>'Id' = @id" "WHERE clause not correct" @@ -531,6 +537,26 @@ let findTests = testList "Find" [ let! docs = Find.byFields SqliteDb.TableName Any [ Field.Greater "NumValue" 100 ] Expect.isTrue (List.isEmpty docs) "There should have been no documents returned" } + testTask "succeeds for InArray when matching documents exist" { + use! db = SqliteDb.BuildDb() + do! Definition.ensureTable SqliteDb.TableName + for doc in ArrayDocument.TestDocuments do do! insert SqliteDb.TableName doc + + let! docs = + Find.byFields + SqliteDb.TableName All [ Field.InArray "Values" SqliteDb.TableName [ "c" ] ] + Expect.hasLength docs 2 "There should have been two documents returned" + } + testTask "succeeds for InArray when no matching documents exist" { + use! db = SqliteDb.BuildDb() + do! Definition.ensureTable SqliteDb.TableName + for doc in ArrayDocument.TestDocuments do do! insert SqliteDb.TableName doc + + let! docs = + Find.byFields + SqliteDb.TableName All [ Field.InArray "Values" SqliteDb.TableName [ "j" ] ] + Expect.isEmpty docs "There should have been no documents returned" + } ] testList "byFieldsOrdered" [ testTask "succeeds when sorting ascending" { diff --git a/src/Tests/Types.fs b/src/Tests/Types.fs index 0deb585..bec9b16 100644 --- a/src/Tests/Types.fs +++ b/src/Tests/Types.fs @@ -8,20 +8,32 @@ type SubDocument = { Foo: string Bar: string } +type ArrayDocument = + { Id: string + Values: string list } +with + /// + /// A set of documents used for integration tests + /// + static member TestDocuments = + [ { Id = "first"; Values = [ "a"; "b"; "c" ] } + { Id = "second"; Values = [ "c"; "d"; "e" ] } + { Id = "third"; Values = [ "x"; "y"; "z" ] } ] + type JsonDocument = { Id: string Value: string NumValue: int Sub: SubDocument option } + /// An empty JsonDocument let emptyDoc = { Id = ""; Value = ""; NumValue = 0; Sub = None } /// Documents to use for testing -let testDocuments = [ - { Id = "one"; Value = "FIRST!"; NumValue = 0; Sub = None } - { Id = "two"; Value = "another"; NumValue = 10; Sub = Some { Foo = "green"; Bar = "blue" } } - { Id = "three"; Value = ""; NumValue = 4; Sub = None } - { Id = "four"; Value = "purple"; NumValue = 17; Sub = Some { Foo = "green"; Bar = "red" } } - { Id = "five"; Value = "purple"; NumValue = 18; Sub = None } -] +let testDocuments = + [ { Id = "one"; Value = "FIRST!"; NumValue = 0; Sub = None } + { Id = "two"; Value = "another"; NumValue = 10; Sub = Some { Foo = "green"; Bar = "blue" } } + { Id = "three"; Value = ""; NumValue = 4; Sub = None } + { Id = "four"; Value = "purple"; NumValue = 17; Sub = Some { Foo = "green"; Bar = "red" } } + { Id = "five"; Value = "purple"; NumValue = 18; Sub = None } ] -- 2.45.1 From f5c68617f044fdbcbd446909895bfa4fc9bc2df8 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Mon, 16 Sep 2024 22:26:29 -0400 Subject: [PATCH 7/7] Bump version; tweak READMEs --- src/Directory.Build.props | 4 ++-- src/Postgres/README.md | 2 +- src/Sqlite/README.md | 8 ++++---- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index 0c4f795..1a956d9 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -6,8 +6,8 @@ 4.0.0.0 4.0.0.0 4.0.0 - rc3 - 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 + 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 danieljsummers Bit Badger Solutions README.md diff --git a/src/Postgres/README.md b/src/Postgres/README.md index 25b493d..baa1161 100644 --- a/src/Postgres/README.md +++ b/src/Postgres/README.md @@ -66,7 +66,7 @@ var customer = await Find.ById("customer", "123"); // Find.byId type signature is string -> 'TKey -> Task<'TDoc option> let! customer = Find.byId "customer" "123" ``` -_(keys are treated as strings in the database)_ +_(keys are treated as strings or numbers depending on their defintion; however, they are indexed as strings)_ Count customers in Atlanta (using JSON containment): diff --git a/src/Sqlite/README.md b/src/Sqlite/README.md index 56546c0..6d069d3 100644 --- a/src/Sqlite/README.md +++ b/src/Sqlite/README.md @@ -73,13 +73,13 @@ Count customers in Atlanta: ```csharp // C#; parameters are table name, field, operator, and value // Count.ByField type signature is Func> -var customerCount = await Count.ByField("customer", Field.EQ("City", "Atlanta")); +var customerCount = await Count.ByField("customer", Field.Equal("City", "Atlanta")); ``` ```fsharp // F# // Count.byField type signature is string -> Field -> Task -let! customerCount = Count.byField "customer" (Field.EQ "City" "Atlanta") +let! customerCount = Count.byField "customer" (Field.Equal "City" "Atlanta") ``` Delete customers in Chicago: _(no offense, Second City; just an example...)_ @@ -87,13 +87,13 @@ Delete customers in Chicago: _(no offense, Second City; just an example...)_ ```csharp // C#; parameters are same as above, except return is void // Delete.ByField type signature is Func -await Delete.ByField("customer", Field.EQ("City", "Chicago")); +await Delete.ByField("customer", Field.Equal("City", "Chicago")); ``` ```fsharp // F# // Delete.byField type signature is string -> string -> Op -> obj -> Task -do! Delete.byField "customer" (Field.EQ "City" "Chicago") +do! Delete.byField "customer" (Field.Equal "City" "Chicago") ``` ## More Information -- 2.45.1