From 35755df99aa3cebea82ff027c72fd05ba63cb28a Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Fri, 9 Aug 2024 20:15:08 -0400 Subject: [PATCH] WIP on pulling code up to Common --- src/Common/Library.fs | 52 +++++++++++++------ src/Postgres/Library.fs | 25 ++++----- src/Sqlite/Library.fs | 17 +++---- src/Tests.CSharp/CommonCSharpTests.cs | 68 +++++++++++++++---------- src/Tests.CSharp/PostgresCSharpTests.cs | 5 -- src/Tests.CSharp/PostgresDb.cs | 3 +- src/Tests.CSharp/SqliteCSharpTests.cs | 5 -- src/Tests/CommonTests.fs | 64 +++++++++++++---------- src/Tests/PostgresTests.fs | 12 ++--- src/Tests/SqliteTests.fs | 3 -- 10 files changed, 135 insertions(+), 119 deletions(-) diff --git a/src/Common/Library.fs b/src/Common/Library.fs index 564132e..3ae755a 100644 --- a/src/Common/Library.fs +++ b/src/Common/Library.fs @@ -35,6 +35,12 @@ type Op = | NEX -> "IS NULL" +/// The dialect in which a command should be rendered +[] +type Dialect = + | PostgreSQL + | SQLite + /// Criteria for a field WHERE clause type Field = { /// The name of the field @@ -89,6 +95,16 @@ type Field = { static member NEX name = { Name = name; Op = NEX; Value = obj (); ParameterName = None; Qualifier = None } + /// Transform a field name (a.b.c) to a path for the given SQL dialect + static member NameToPath (name: string) dialect = + let path = + if name.Contains '.' then + match dialect with + | PostgreSQL -> "#>>'{" + String.concat "," (name.Split '.') + "}'" + | SQLite -> "->>'" + String.concat "'->>'" (name.Split '.') + "'" + else $"->>'{name}'" + $"data{path}" + /// Specify the name of the parameter for this field member this.WithParameterName name = { this with ParameterName = Some name } @@ -97,17 +113,9 @@ type Field = { member this.WithQualifier alias = { this with Qualifier = Some alias } - /// Get the path for this field in PostgreSQL's format - member this.PgSqlPath = - (this.Qualifier |> Option.map (fun q -> $"{q}.data") |> Option.defaultValue "data") - + if this.Name.Contains '.' then "#>>'{" + String.concat "," (this.Name.Split '.') + "}'" - else $"->>'{this.Name}'" - - /// Get the path for this field in SQLite's format - member this.SqlitePath = - (this.Qualifier |> Option.map (fun q -> $"{q}.data") |> Option.defaultValue "data") - + if this.Name.Contains '.' then "->>'" + String.concat "'->>'" (this.Name.Split '.') + "'" - else $"->>'{this.Name}'" + /// 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 /// How fields should be matched @@ -221,7 +229,7 @@ module Query = /// SQL statement to create an index on one or more fields in a JSON document [] - let ensureIndexOn tableName indexName (fields: string seq) = + let ensureIndexOn tableName indexName (fields: string seq) dialect = let _, tbl = splitSchemaAndTable tableName let jsonFields = fields @@ -229,14 +237,14 @@ 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]}" - $"(data ->> '{fieldName}'){direction}") + $"({Field.NameToPath fieldName dialect}){direction}") |> String.concat ", " $"CREATE INDEX IF NOT EXISTS idx_{tbl}_%s{indexName} ON {tableName} ({jsonFields})" /// SQL statement to create a key index for a document table [] - let ensureKey tableName = - (ensureIndexOn tableName "key" [ Configuration.idField () ]).Replace("INDEX", "UNIQUE INDEX") + let ensureKey tableName dialect = + (ensureIndexOn tableName "key" [ Configuration.idField () ] dialect).Replace("INDEX", "UNIQUE INDEX") /// Query to insert a document [] @@ -249,4 +257,16 @@ module Query = sprintf "INSERT INTO %s VALUES (@data) ON CONFLICT ((data->>'%s')) DO UPDATE SET data = EXCLUDED.data" tableName (Configuration.idField ()) - \ No newline at end of file + + /// Queries for counting documents + module Count = + + /// Query to count all documents in a table + [] + let all tableName = + $"SELECT COUNT(*) AS it FROM %s{tableName}" + + /// Query to count matching documents using a text comparison on JSON fields + [] + let byFields (whereByFields: FieldMatch -> Field seq -> string) tableName howMatched fields = + $"SELECT COUNT(*) AS it FROM %s{tableName} WHERE {whereByFields howMatched fields}" diff --git a/src/Postgres/Library.fs b/src/Postgres/Library.fs index d7d66f2..9138811 100644 --- a/src/Postgres/Library.fs +++ b/src/Postgres/Library.fs @@ -120,18 +120,18 @@ module Query = fields |> Seq.map (fun it -> match it.Op with - | EX | NEX -> $"{it.PgSqlPath} {it.Op}" - | _ -> + | EX | NEX -> $"{it.Path PostgreSQL} {it.Op}" + | BT -> let p = name.Derive it.ParameterName let path, value = match it.Op with | BT -> $"{p}min AND {p}max", (it.Value :?> obj list)[0] | _ -> p, it.Value - printfn $"%A{value}" match value with | :? int8 | :? uint8 | :? int16 | :? uint16 | :? int | :? uint32 | :? int64 | :? uint64 - | :? decimal | :? single | :? double -> $"({it.PgSqlPath})::numeric {it.Op} {path}" - | _ -> $"{it.PgSqlPath} {it.Op} {path}") + | :? decimal | :? single | :? double -> $"({it.Path PostgreSQL})::numeric {it.Op} {path}" + | _ -> $"{it.Path PostgreSQL} {it.Op} {path}" + | _ -> $"{it.Path PostgreSQL} {it.Op} {name.Derive it.ParameterName}") |> String.concat (match howMatched with Any -> " OR " | All -> " AND ") /// Create a WHERE clause fragment to implement a comparison on a field in a JSON document @@ -178,15 +178,10 @@ module Query = /// Queries for counting documents module Count = - /// Query to count all documents in a table - [] - let all tableName = - $"SELECT COUNT(*) AS it FROM %s{tableName}" - /// Query to count matching documents using a text comparison on JSON fields [] let byFields tableName howMatched fields = - $"SELECT COUNT(*) AS it FROM %s{tableName} WHERE {whereByFields howMatched fields}" + Query.Count.byFields whereByFields tableName howMatched fields /// Query to count matching documents using a text comparison on a JSON field [] @@ -197,12 +192,12 @@ module Query = /// Query to count matching documents using a JSON containment query (@>) [] let byContains tableName = - $"""SELECT COUNT(*) AS it FROM %s{tableName} WHERE {whereDataContains "@criteria"}""" + $"""{Query.Count.all tableName} WHERE {whereDataContains "@criteria"}""" /// Query to count matching documents using a JSON Path match (@?) [] let byJsonPath tableName = - $"""SELECT COUNT(*) AS it FROM %s{tableName} WHERE {whereJsonPathMatches "@path"}""" + $"""{Query.Count.all tableName} WHERE {whereJsonPathMatches "@path"}""" /// Queries for determining document existence module Exists = @@ -445,7 +440,7 @@ module WithProps = [] let ensureTable name sqlProps = backgroundTask { do! Custom.nonQuery (Query.Definition.ensureTable name) [] sqlProps - do! Custom.nonQuery (Query.Definition.ensureKey name) [] sqlProps + do! Custom.nonQuery (Query.Definition.ensureKey name PostgreSQL) [] sqlProps } /// Create an index on documents in the specified table @@ -456,7 +451,7 @@ module WithProps = /// Create an index on field(s) within documents in the specified table [] let ensureFieldIndex tableName indexName fields sqlProps = - Custom.nonQuery (Query.Definition.ensureIndexOn tableName indexName fields) [] sqlProps + Custom.nonQuery (Query.Definition.ensureIndexOn tableName indexName fields PostgreSQL) [] sqlProps /// Commands to add documents [] diff --git a/src/Sqlite/Library.fs b/src/Sqlite/Library.fs index 86df67b..b716fa0 100644 --- a/src/Sqlite/Library.fs +++ b/src/Sqlite/Library.fs @@ -38,11 +38,11 @@ module Query = fields |> Seq.map (fun it -> match it.Op with - | EX | NEX -> $"{it.SqlitePath} {it.Op}" + | EX | NEX -> $"{it.Path SQLite} {it.Op}" | BT -> let p = name.Derive it.ParameterName - $"{it.SqlitePath} {it.Op} {p}min AND {p}max" - | _ -> $"{it.SqlitePath} {it.Op} {name.Derive it.ParameterName}") + $"{it.Path SQLite} {it.Op} {p}min AND {p}max" + | _ -> $"{it.Path SQLite} {it.Op} {name.Derive it.ParameterName}") |> String.concat (match howMatched with Any -> " OR " | All -> " AND ") /// Create a WHERE clause fragment to implement a comparison on a field in a JSON document @@ -72,15 +72,10 @@ module Query = /// Queries for counting documents module Count = - /// Query to count all documents in a table - [] - let all tableName = - $"SELECT COUNT(*) AS it FROM %s{tableName}" - /// Query to count matching documents using a text comparison on JSON fields [] let byFields tableName howMatched fields = - $"SELECT COUNT(*) AS it FROM %s{tableName} WHERE {whereByFields howMatched fields}" + Query.Count.byFields whereByFields tableName howMatched fields /// Query to count matching documents using a text comparison on a JSON field [] @@ -361,13 +356,13 @@ module WithConn = [] let ensureTable name conn = backgroundTask { do! Custom.nonQuery (Query.Definition.ensureTable name) [] conn - do! Custom.nonQuery (Query.Definition.ensureKey name) [] conn + do! Custom.nonQuery (Query.Definition.ensureKey name SQLite) [] conn } /// Create an index on a document table [] let ensureFieldIndex tableName indexName fields conn = - Custom.nonQuery (Query.Definition.ensureIndexOn tableName indexName fields) [] conn + Custom.nonQuery (Query.Definition.ensureIndexOn tableName indexName fields SQLite) [] conn /// Insert a new document [] diff --git a/src/Tests.CSharp/CommonCSharpTests.cs b/src/Tests.CSharp/CommonCSharpTests.cs index eca9cfd..e823508 100644 --- a/src/Tests.CSharp/CommonCSharpTests.cs +++ b/src/Tests.CSharp/CommonCSharpTests.cs @@ -185,50 +185,54 @@ public static class CommonCSharpTests Expect.isSome(field.Qualifier, "The table qualifier should have been filled"); Expect.equal("joe", field.Qualifier.Value, "The table qualifier is incorrect"); }), - TestList("PgSqlPath", + TestList("Path", [ - TestCase("succeeds for a single field with no qualifier", () => + TestCase("succeeds for a PostgreSQL single field with no qualifier", () => { var field = Field.GE("SomethingCool", 18); - Expect.equal("data->>'SomethingCool'", field.PgSqlPath, "The PostgreSQL path is incorrect"); + Expect.equal("data->>'SomethingCool'", field.Path(Dialect.PostgreSQL), + "The PostgreSQL path is incorrect"); }), - TestCase("succeeds for a single field with a qualifier", () => + TestCase("succeeds for a PostgreSQL single field with a qualifier", () => { var field = Field.LT("SomethingElse", 9).WithQualifier("this"); - Expect.equal("this.data->>'SomethingElse'", field.PgSqlPath, "The PostgreSQL path is incorrect"); + Expect.equal("this.data->>'SomethingElse'", field.Path(Dialect.PostgreSQL), + "The PostgreSQL path is incorrect"); }), - TestCase("succeeds for a nested field with no qualifier", () => + TestCase("succeeds for a PostgreSQL nested field with no qualifier", () => { var field = Field.EQ("My.Nested.Field", "howdy"); - Expect.equal("data#>>'{My,Nested,Field}'", field.PgSqlPath, "The PostgreSQL path is incorrect"); + Expect.equal("data#>>'{My,Nested,Field}'", field.Path(Dialect.PostgreSQL), + "The PostgreSQL path is incorrect"); }), - TestCase("succeeds for a nested field with a qualifier", () => + TestCase("succeeds for a PostgreSQL nested field with a qualifier", () => { var field = Field.EQ("Nest.Away", "doc").WithQualifier("bird"); - Expect.equal("bird.data#>>'{Nest,Away}'", field.PgSqlPath, "The PostgreSQL path is incorrect"); - }) - ]), - TestList("SqlitePath", - [ - TestCase("succeeds for a single field with no qualifier", () => + 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); - Expect.equal("data->>'SomethingCool'", field.SqlitePath, "The SQLite path is incorrect"); + Expect.equal("data->>'SomethingCool'", field.Path(Dialect.SQLite), "The SQLite path is incorrect"); }), - TestCase("succeeds for a single field with a qualifier", () => + TestCase("succeeds for a SQLite single field with a qualifier", () => { var field = Field.LT("SomethingElse", 9).WithQualifier("this"); - Expect.equal("this.data->>'SomethingElse'", field.SqlitePath, "The SQLite path is incorrect"); + Expect.equal("this.data->>'SomethingElse'", field.Path(Dialect.SQLite), + "The SQLite path is incorrect"); }), - TestCase("succeeds for a nested field with no qualifier", () => + TestCase("succeeds for a SQLite nested field with no qualifier", () => { var field = Field.EQ("My.Nested.Field", "howdy"); - Expect.equal("data->>'My'->>'Nested'->>'Field'", field.SqlitePath, "The SQLite path is incorrect"); + Expect.equal("data->>'My'->>'Nested'->>'Field'", field.Path(Dialect.SQLite), + "The SQLite path is incorrect"); }), - TestCase("succeeds for a nested field with a qualifier", () => + TestCase("succeeds for a SQLite nested field with a qualifier", () => { var field = Field.EQ("Nest.Away", "doc").WithQualifier("bird"); - Expect.equal("bird.data->>'Nest'->>'Away'", field.SqlitePath, "The SQLite path is incorrect"); + Expect.equal("bird.data->>'Nest'->>'Away'", field.Path(Dialect.SQLite), + "The SQLite path is incorrect"); }) ]) ]), @@ -251,14 +255,14 @@ public static class CommonCSharpTests [ TestCase("succeeds when a schema is present", () => { - Expect.equal(Query.Definition.EnsureKey("test.table"), - "CREATE UNIQUE INDEX IF NOT EXISTS idx_table_key ON test.table ((data ->> 'Id'))", + Expect.equal(Query.Definition.EnsureKey("test.table", Dialect.SQLite), + "CREATE UNIQUE INDEX IF NOT EXISTS idx_table_key ON test.table ((data->>'Id'))", "CREATE INDEX for key statement with schema not constructed correctly"); }), TestCase("succeeds when a schema is not present", () => { - Expect.equal(Query.Definition.EnsureKey("table"), - "CREATE UNIQUE INDEX IF NOT EXISTS idx_table_key ON table ((data ->> 'Id'))", + Expect.equal(Query.Definition.EnsureKey("table", Dialect.PostgreSQL), + "CREATE UNIQUE INDEX IF NOT EXISTS idx_table_key ON table ((data->>'Id'))", "CREATE INDEX for key statement without schema not constructed correctly"); }) ]), @@ -266,9 +270,9 @@ public static class CommonCSharpTests { Expect.equal( Query.Definition.EnsureIndexOn("test.table", "gibberish", - new[] { "taco", "guac DESC", "salsa ASC" }), + new[] { "taco", "guac DESC", "salsa ASC" }, Dialect.SQLite), "CREATE INDEX IF NOT EXISTS idx_table_gibberish ON test.table " - + "((data ->> 'taco'), (data ->> 'guac') DESC, (data ->> 'salsa') ASC)", + + "((data->>'taco'), (data->>'guac') DESC, (data->>'salsa') ASC)", "CREATE INDEX for multiple field statement incorrect"); }) ]), @@ -281,7 +285,15 @@ public static class CommonCSharpTests Expect.equal(Query.Save("tbl"), "INSERT INTO tbl VALUES (@data) ON CONFLICT ((data->>'Id')) DO UPDATE SET data = EXCLUDED.data", "INSERT ON CONFLICT UPDATE statement not correct"); - }) + }), + TestList("Count", + [ + TestCase("All succeeds", () => + { + Expect.equal(Query.Count.All("a_table"), $"SELECT COUNT(*) AS it FROM a_table", + "Count query not correct"); + }), + ]) ]) ]); } diff --git a/src/Tests.CSharp/PostgresCSharpTests.cs b/src/Tests.CSharp/PostgresCSharpTests.cs index ed1b093..d3c239b 100644 --- a/src/Tests.CSharp/PostgresCSharpTests.cs +++ b/src/Tests.CSharp/PostgresCSharpTests.cs @@ -287,11 +287,6 @@ public static class PostgresCSharpTests }), TestList("Count", [ - TestCase("All succeeds", () => - { - Expect.equal(Postgres.Query.Count.All(PostgresDb.TableName), - $"SELECT COUNT(*) AS it FROM {PostgresDb.TableName}", "Count query not correct"); - }), TestCase("ByFields succeeds", () => { Expect.equal( diff --git a/src/Tests.CSharp/PostgresDb.cs b/src/Tests.CSharp/PostgresDb.cs index 301e9a6..4d84e2c 100644 --- a/src/Tests.CSharp/PostgresDb.cs +++ b/src/Tests.CSharp/PostgresDb.cs @@ -1,3 +1,4 @@ +using BitBadger.Documents.Postgres; using Npgsql; using Npgsql.FSharp; using ThrowawayDb.Postgres; @@ -131,7 +132,7 @@ public static class PostgresDb var sqlProps = Sql.connect(database.ConnectionString); Sql.executeNonQuery(Sql.query(Postgres.Query.Definition.EnsureTable(TableName), sqlProps)); - Sql.executeNonQuery(Sql.query(Query.Definition.EnsureKey(TableName), sqlProps)); + Sql.executeNonQuery(Sql.query(Query.Definition.EnsureKey(TableName, Dialect.PostgreSQL), sqlProps)); Postgres.Configuration.UseDataSource(MkDataSource(database.ConnectionString)); diff --git a/src/Tests.CSharp/SqliteCSharpTests.cs b/src/Tests.CSharp/SqliteCSharpTests.cs index cac780c..ca57e8b 100644 --- a/src/Tests.CSharp/SqliteCSharpTests.cs +++ b/src/Tests.CSharp/SqliteCSharpTests.cs @@ -99,11 +99,6 @@ public static class SqliteCSharpTests }), TestList("Count", [ - TestCase("All succeeds", () => - { - Expect.equal(Sqlite.Query.Count.All("tbl"), "SELECT COUNT(*) AS it FROM tbl", - "Count query not correct"); - }), #pragma warning disable CS0618 TestCase("ByField succeeds", () => { diff --git a/src/Tests/CommonTests.fs b/src/Tests/CommonTests.fs index 27d6fff..5020d26 100644 --- a/src/Tests/CommonTests.fs +++ b/src/Tests/CommonTests.fs @@ -119,40 +119,39 @@ let all = Expect.isSome field.Qualifier "The table qualifier should have been filled" Expect.equal "joe" field.Qualifier.Value "The table qualifier is incorrect" } - testList "PgSqlPath" [ - test "succeeds for a single field with no qualifier" { + testList "Path" [ + test "succeeds for a PostgreSQL single field with no qualifier" { let field = Field.GE "SomethingCool" 18 - Expect.equal "data->>'SomethingCool'" field.PgSqlPath "The PostgreSQL path is incorrect" + Expect.equal "data->>'SomethingCool'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" } - test "succeeds for a single field with a qualifier" { + test "succeeds for a PostgreSQL single field with a qualifier" { let field = { Field.LT "SomethingElse" 9 with Qualifier = Some "this" } - Expect.equal "this.data->>'SomethingElse'" field.PgSqlPath "The PostgreSQL path is incorrect" + Expect.equal + "this.data->>'SomethingElse'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" } - test "succeeds for a nested field with no qualifier" { + test "succeeds for a PostgreSQL nested field with no qualifier" { let field = Field.EQ "My.Nested.Field" "howdy" - Expect.equal "data#>>'{My,Nested,Field}'" field.PgSqlPath "The PostgreSQL path is incorrect" + Expect.equal "data#>>'{My,Nested,Field}'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" } - test "succeeds for a nested field with a qualifier" { + test "succeeds for a PostgreSQL nested field with a qualifier" { let field = { Field.EQ "Nest.Away" "doc" with Qualifier = Some "bird" } - Expect.equal "bird.data#>>'{Nest,Away}'" field.PgSqlPath "The PostgreSQL path is incorrect" + Expect.equal "bird.data#>>'{Nest,Away}'" (field.Path PostgreSQL) "The PostgreSQL path is incorrect" } - ] - testList "SqlitePath" [ - test "succeeds for a single field with no qualifier" { + test "succeeds for a SQLite single field with no qualifier" { let field = Field.GE "SomethingCool" 18 - Expect.equal "data->>'SomethingCool'" field.SqlitePath "The SQLite path is incorrect" + Expect.equal "data->>'SomethingCool'" (field.Path SQLite) "The SQLite path is incorrect" } - test "succeeds for a single field with a qualifier" { + test "succeeds for a SQLite single field with a qualifier" { let field = { Field.LT "SomethingElse" 9 with Qualifier = Some "this" } - Expect.equal "this.data->>'SomethingElse'" field.SqlitePath "The SQLite path is incorrect" + Expect.equal "this.data->>'SomethingElse'" (field.Path SQLite) "The SQLite path is incorrect" } - test "succeeds for a nested field with no qualifier" { + test "succeeds for a SQLite nested field with no qualifier" { let field = Field.EQ "My.Nested.Field" "howdy" - Expect.equal "data->>'My'->>'Nested'->>'Field'" field.SqlitePath "The SQLite path is incorrect" + Expect.equal "data->>'My'->>'Nested'->>'Field'" (field.Path SQLite) "The SQLite path is incorrect" } - test "succeeds for a nested field with a qualifier" { + test "succeeds for a SQLite nested field with a qualifier" { let field = { Field.EQ "Nest.Away" "doc" with Qualifier = Some "bird" } - Expect.equal "bird.data->>'Nest'->>'Away'" field.SqlitePath "The SQLite path is incorrect" + Expect.equal "bird.data->>'Nest'->>'Away'" (field.Path SQLite) "The SQLite path is incorrect" } ] ] @@ -184,22 +183,23 @@ let all = testList "ensureKey" [ test "succeeds when a schema is present" { Expect.equal - (Query.Definition.ensureKey "test.table") - "CREATE UNIQUE INDEX IF NOT EXISTS idx_table_key ON test.table ((data ->> 'Id'))" + (Query.Definition.ensureKey "test.table" PostgreSQL) + "CREATE UNIQUE INDEX IF NOT EXISTS idx_table_key ON test.table ((data->>'Id'))" "CREATE INDEX for key statement with schema not constructed correctly" } test "succeeds when a schema is not present" { Expect.equal - (Query.Definition.ensureKey "table") - "CREATE UNIQUE INDEX IF NOT EXISTS idx_table_key ON table ((data ->> 'Id'))" + (Query.Definition.ensureKey "table" SQLite) + "CREATE UNIQUE INDEX IF NOT EXISTS idx_table_key ON table ((data->>'Id'))" "CREATE INDEX for key statement without schema not constructed correctly" } ] test "ensureIndexOn succeeds for multiple fields and directions" { Expect.equal - (Query.Definition.ensureIndexOn "test.table" "gibberish" [ "taco"; "guac DESC"; "salsa ASC" ]) + (Query.Definition.ensureIndexOn + "test.table" "gibberish" [ "taco"; "guac DESC"; "salsa ASC" ] PostgreSQL) ([ "CREATE INDEX IF NOT EXISTS idx_table_gibberish ON test.table " - "((data ->> 'taco'), (data ->> 'guac') DESC, (data ->> 'salsa') ASC)" ] + "((data->>'taco'), (data->>'guac') DESC, (data->>'salsa') ASC)" ] |> String.concat "") "CREATE INDEX for multiple field statement incorrect" } @@ -213,6 +213,18 @@ let all = $"INSERT INTO {tbl} VALUES (@data) ON CONFLICT ((data->>'Id')) DO UPDATE SET data = EXCLUDED.data" "INSERT ON CONFLICT UPDATE statement not correct" } + testList "Count" [ + test "all succeeds" { + Expect.equal (Query.Count.all "a_table") "SELECT COUNT(*) AS it FROM a_table" + "Count query not correct" + } + test "byFields succeeds" { + let test = fun _ _ -> "howdy" + Expect.equal + (Query.Count.byFields test "over_here" Any []) + "SELECT COUNT(*) AS it FROM over_here WHERE howdy" + "Count by fields query not correct" + } + ] ] ] - diff --git a/src/Tests/PostgresTests.fs b/src/Tests/PostgresTests.fs index bbb9bef..81d5052 100644 --- a/src/Tests/PostgresTests.fs +++ b/src/Tests/PostgresTests.fs @@ -259,12 +259,6 @@ let unitTests = Expect.equal (Query.whereJsonPathMatches "@path") "data @? @path::jsonpath" "WHERE clause not correct" } testList "Count" [ - test "all succeeds" { - Expect.equal - (Query.Count.all PostgresDb.TableName) - $"SELECT COUNT(*) AS it FROM {PostgresDb.TableName}" - "Count query not correct" - } test "byFields succeeds" { Expect.equal (Query.Count.byFields "tbl" All [ Field.EQ "thatField" 0; Field.EQ "anotherField" 8]) @@ -664,7 +658,7 @@ let integrationTests = let! theCount = Count.all PostgresDb.TableName Expect.equal theCount 5 "There should have been 5 matching documents" } - testList "byFields" [ + ptestList "byFields" [ testTask "succeeds when items are found" { use db = PostgresDb.BuildDb() do! loadDocs () @@ -818,7 +812,7 @@ let integrationTests = Expect.equal results [] "There should have been no documents returned" } ] - ftestList "byId" [ + testList "byId" [ testTask "succeeds when a document is found" { use db = PostgresDb.BuildDb() do! loadDocs () @@ -845,7 +839,7 @@ let integrationTests = PostgresDb.TableName All [ Field.EQ "Value" "purple"; Field.EX "Sub" ] Expect.equal (List.length docs) 1 "There should have been one document returned" } - testTask "succeeds when documents are not found" { + ptestTask "succeeds when documents are not found" { use db = PostgresDb.BuildDb() do! loadDocs () diff --git a/src/Tests/SqliteTests.fs b/src/Tests/SqliteTests.fs index 4fd7b75..709f50a 100644 --- a/src/Tests/SqliteTests.fs +++ b/src/Tests/SqliteTests.fs @@ -88,9 +88,6 @@ let unitTests = "UPDATE full statement not correct" } testList "Count" [ - test "all succeeds" { - Expect.equal (Query.Count.all "tbl") $"SELECT COUNT(*) AS it FROM tbl" "Count query not correct" - } test "byField succeeds" { Expect.equal (Query.Count.byField "tbl" (Field.EQ "thatField" 0))