diff --git a/src/Postgres/Library.fs b/src/Postgres/Library.fs index 4b20b4a..62e38ae 100644 --- a/src/Postgres/Library.fs +++ b/src/Postgres/Library.fs @@ -326,13 +326,14 @@ module Results = /// The query from which JSON should be extracted /// A JSON array as a string; no results will produce an empty array ("[]") [] - let toJsonArray (mapFunc: RowReader -> string) sqlProps = + let toJsonArray (mapFunc: RowReader -> string) sqlProps = backgroundTask { let output = StringBuilder("[") - sqlProps - |> Sql.iter (fun it -> - if output.Length > 2 then ignore (output.Append ",") - mapFunc it |> output.Append |> ignore) - output.Append("]").ToString() + do! sqlProps + |> Sql.iterAsync (fun it -> + if output.Length > 2 then ignore (output.Append ",") + mapFunc it |> output.Append |> ignore) + return output.Append("]").ToString() + } /// Create a JSON array of items for the results of a query /// The mapping function to extract JSON from the query's results @@ -346,14 +347,15 @@ module Results = /// The mapping function to extract JSON from the query's results /// The query from which JSON should be extracted [] - let writeJsonArray (writer: StreamWriter) (mapFunc: RowReader -> string) sqlProps = - writer.Write "[" + let writeJsonArray (writer: StreamWriter) (mapFunc: RowReader -> string) sqlProps = backgroundTask { + do! writer.WriteAsync "[" let mutable isFirst = true - sqlProps - |> Sql.iter (fun it -> - if isFirst then isFirst <- false else writer.Write "," - mapFunc it |> writer.Write) - writer.Write "]" + do! sqlProps + |> Sql.iterAsync (fun it -> + if isFirst then isFirst <- false else writer.Write "," + writer.WriteAsync(mapFunc it).ConfigureAwait(false).GetAwaiter().GetResult()) + do! writer.WriteAsync "]" + } /// Write a JSON array of items for the results of a query to the given StreamWriter /// The StreamWriter to which results should be written diff --git a/src/Postgres/WithProps.fs b/src/Postgres/WithProps.fs index f0bf7d6..2acf943 100644 --- a/src/Postgres/WithProps.fs +++ b/src/Postgres/WithProps.fs @@ -107,9 +107,10 @@ module Custom = /// The SqlProps to use to execute the query /// The JSON document with the first matching result, or an empty document if not found [] - let jsonSingle query parameters mapFunc sqlProps = - let results = jsonArray $"%s{query} LIMIT 1" parameters mapFunc sqlProps - if results = "[]" then "{}" else results[1..results.Length - 2] + let jsonSingle query parameters mapFunc sqlProps = backgroundTask { + let! results = jsonArray $"%s{query} LIMIT 1" parameters mapFunc sqlProps + return if results = "[]" then "{}" else results[1..results.Length - 2] + } /// Execute a query that returns one or no JSON documents /// The query to retrieve the results @@ -972,8 +973,10 @@ module Json = /// The field conditions to match /// The SqlProps to use to execute the query [] - let writeFirstByFields tableName (writer: StreamWriter) howMatched fields sqlProps = - firstByFields tableName howMatched fields sqlProps |> writer.Write + let writeFirstByFields tableName (writer: StreamWriter) howMatched fields sqlProps = backgroundTask { + let! json = firstByFields tableName howMatched fields sqlProps + do! writer.WriteAsync json + } /// /// Retrieve the first JSON document matching JSON field comparisons (->> =, etc.) ordered by the given @@ -1005,7 +1008,10 @@ module Json = /// The SqlProps to use to execute the query [] let writeFirstByFieldsOrdered tableName (writer: StreamWriter) howMatched queryFields orderFields sqlProps = - firstByFieldsOrdered tableName howMatched queryFields orderFields sqlProps |> writer.Write + backgroundTask { + let! json = firstByFieldsOrdered tableName howMatched queryFields orderFields sqlProps + do! writer.WriteAsync json + } /// Retrieve the first JSON document matching a JSON containment query (@>) /// The table from which a document should be retrieved (may include schema) @@ -1025,8 +1031,10 @@ module Json = /// The document to match with the containment query /// The SqlProps to use to execute the query [] - let writeFirstByContains tableName (writer: StreamWriter) (criteria: obj) sqlProps = - firstByContains tableName criteria sqlProps |> writer.Write + let writeFirstByContains tableName (writer: StreamWriter) (criteria: obj) sqlProps = backgroundTask { + let! json = firstByContains tableName criteria sqlProps + do! writer.WriteAsync json + } /// /// Retrieve the first JSON document matching a JSON containment query (@>) ordered by the given fields in @@ -1056,7 +1064,10 @@ module Json = /// The SqlProps to use to execute the query [] let writeFirstByContainsOrdered tableName (writer: StreamWriter) (criteria: obj) orderFields sqlProps = - firstByContainsOrdered tableName criteria orderFields sqlProps |> writer.Write + backgroundTask { + let! json = firstByContainsOrdered tableName criteria orderFields sqlProps + do! writer.WriteAsync json + } /// Retrieve the first JSON document matching a JSON Path match query (@?) /// The table from which a document should be retrieved (may include schema) @@ -1076,8 +1087,10 @@ module Json = /// The JSON Path expression to match /// The SqlProps to use to execute the query [] - let writeFirstByJsonPath tableName (writer: StreamWriter) jsonPath sqlProps = - firstByJsonPath tableName jsonPath sqlProps |> writer.Write + let writeFirstByJsonPath tableName (writer: StreamWriter) jsonPath sqlProps = backgroundTask { + let! json = firstByJsonPath tableName jsonPath sqlProps + do! writer.WriteAsync json + } /// /// Retrieve the first JSON document matching a JSON Path match query (@?) ordered by the given fields in the @@ -1106,8 +1119,10 @@ module Json = /// Fields by which the results should be ordered /// The SqlProps to use to execute the query [] - let writeFirstByJsonPathOrdered tableName (writer: StreamWriter) jsonPath orderFields sqlProps = - firstByJsonPathOrdered tableName jsonPath orderFields sqlProps |> writer.Write + let writeFirstByJsonPathOrdered tableName (writer: StreamWriter) jsonPath orderFields sqlProps = backgroundTask { + let! json = firstByJsonPathOrdered tableName jsonPath orderFields sqlProps + do! writer.WriteAsync json + } /// Commands to update documents [] diff --git a/src/Tests.CSharp/PostgresCSharpTests.cs b/src/Tests.CSharp/PostgresCSharpTests.cs index 8977851..521676b 100644 --- a/src/Tests.CSharp/PostgresCSharpTests.cs +++ b/src/Tests.CSharp/PostgresCSharpTests.cs @@ -412,7 +412,8 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - var docs = Custom.JsonArray(Query.Find(PostgresDb.TableName), Parameters.None, Results.JsonFromData); + var docs = await Custom.JsonArray(Query.Find(PostgresDb.TableName), Parameters.None, + Results.JsonFromData); Expect.stringStarts(docs, "[", "The JSON array should have started with `[`"); Expect.hasLength(docs.Split("{\"Id\":"), 6, "There should have been 5 documents returned"); Expect.stringEnds(docs, "]", "The JSON array should have ended with `[`"); @@ -422,7 +423,8 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - var docs = Custom.JsonArray($"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath", + var docs = await Custom.JsonArray( + $"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath", [Tuple.Create("@path", Sql.@string("$.NumValue ? (@ > 100)"))], Results.JsonFromData); Expect.equal(docs, "[]", "There should have been no documents returned"); }) @@ -436,7 +438,8 @@ public static class PostgresCSharpTests await using MemoryStream stream = new(); await using var writer = WriteStream(stream); - Custom.WriteJsonArray(Query.Find(PostgresDb.TableName), Parameters.None, writer, Results.JsonFromData); + await Custom.WriteJsonArray(Query.Find(PostgresDb.TableName), Parameters.None, writer, + Results.JsonFromData); var docs = StreamText(stream); Expect.stringStarts(docs, "[", "The JSON array should have started with `[`"); @@ -450,7 +453,7 @@ public static class PostgresCSharpTests await using MemoryStream stream = new(); await using var writer = WriteStream(stream); - Custom.WriteJsonArray($"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath", + await Custom.WriteJsonArray($"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath", [Tuple.Create("@path", Sql.@string("$.NumValue ? (@ > 100)"))], writer, Results.JsonFromData); Expect.equal(StreamText(stream), "[]", "There should have been no documents returned"); @@ -485,7 +488,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - var doc = Custom.JsonSingle($"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id", + var doc = await Custom.JsonSingle($"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id", [Tuple.Create("@id", Sql.@string("one"))], Results.JsonFromData); Expect.stringStarts(doc, "{", "The document should have started with an open brace"); Expect.stringContains(doc, "\"Id\": \"one\"", "An incorrect document was returned"); @@ -496,7 +499,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - var doc = Custom.JsonSingle($"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id", + var doc = await Custom.JsonSingle($"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id", [Tuple.Create("@id", Sql.@string("eighty"))], Results.JsonFromData); Expect.equal(doc, "{}", "There should not have been a document returned"); }) @@ -1370,12 +1373,12 @@ public static class PostgresCSharpTests { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyAllData(Json.All(PostgresDb.TableName)); + VerifyAllData(await Json.All(PostgresDb.TableName)); }), TestCase("succeeds when there is no data", async () => { await using var db = PostgresDb.BuildDb(); - VerifyEmpty(Json.All(PostgresDb.TableName)); + VerifyEmpty(await Json.All(PostgresDb.TableName)); }) ]), TestList("AllOrdered", @@ -1384,21 +1387,21 @@ public static class PostgresCSharpTests { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyExpectedOrder(Json.AllOrdered(PostgresDb.TableName, [Field.Named("n:NumValue")]), + VerifyExpectedOrder(await Json.AllOrdered(PostgresDb.TableName, [Field.Named("n:NumValue")]), "one", "three", "two", "four", "five"); }), TestCase("succeeds when ordering numerically descending", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyExpectedOrder(Json.AllOrdered(PostgresDb.TableName, [Field.Named("n:NumValue DESC")]), + VerifyExpectedOrder(await Json.AllOrdered(PostgresDb.TableName, [Field.Named("n:NumValue DESC")]), "five", "four", "two", "three", "one"); }), TestCase("succeeds when ordering alphabetically", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyExpectedOrder(Json.AllOrdered(PostgresDb.TableName, [Field.Named("Id DESC")]), + VerifyExpectedOrder(await Json.AllOrdered(PostgresDb.TableName, [Field.Named("Id DESC")]), "two", "three", "one", "four", "five"); }) ]), @@ -1409,7 +1412,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - var json = Json.ById(PostgresDb.TableName, "two"); + var json = await Json.ById(PostgresDb.TableName, "two"); Expect.stringStarts(json, """{"Id": "two",""", "An incorrect document was returned"); Expect.stringEnds(json, "}", "JSON should have ended with this document"); }), @@ -1417,7 +1420,7 @@ public static class PostgresCSharpTests { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyNoDoc(Json.ById(PostgresDb.TableName, "three hundred eighty-seven")); + VerifyNoDoc(await Json.ById(PostgresDb.TableName, "three hundred eighty-seven")); }) ]), TestList("ByFields", @@ -1427,7 +1430,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifySingleById( - Json.ByFields(PostgresDb.TableName, FieldMatch.All, + await Json.ByFields(PostgresDb.TableName, FieldMatch.All, [Field.In("Value", ["purple", "blue"]), Field.Exists("Sub")]), "four"); }), @@ -1436,14 +1439,14 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifySingleById( - Json.ByFields(PostgresDb.TableName, FieldMatch.All, [Field.In("NumValue", [2, 4, 6, 8])]), + await Json.ByFields(PostgresDb.TableName, FieldMatch.All, [Field.In("NumValue", [2, 4, 6, 8])]), "three"); }), TestCase("succeeds when documents are not found", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyEmpty(Json.ByFields(PostgresDb.TableName, FieldMatch.All, + VerifyEmpty(await Json.ByFields(PostgresDb.TableName, FieldMatch.All, [Field.Equal("Value", "mauve"), Field.NotEqual("NumValue", 40)])); }), TestCase("succeeds for InArray when matching documents exist", async () => @@ -1452,7 +1455,7 @@ public static class PostgresCSharpTests await Definition.EnsureTable(PostgresDb.TableName); foreach (var doc in ArrayDocument.TestDocuments) await Document.Insert(PostgresDb.TableName, doc); - var json = Json.ByFields(PostgresDb.TableName, FieldMatch.All, + var json = await Json.ByFields(PostgresDb.TableName, FieldMatch.All, [Field.InArray("Values", PostgresDb.TableName, ["c"])]); VerifyBeginEnd(json); VerifyDocById(json, "first"); @@ -1463,7 +1466,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await Definition.EnsureTable(PostgresDb.TableName); foreach (var doc in ArrayDocument.TestDocuments) await Document.Insert(PostgresDb.TableName, doc); - VerifyEmpty(Json.ByFields(PostgresDb.TableName, FieldMatch.All, + VerifyEmpty(await Json.ByFields(PostgresDb.TableName, FieldMatch.All, [Field.InArray("Values", PostgresDb.TableName, ["j"])])); }) ]), @@ -1474,7 +1477,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyExpectedOrder( - Json.ByFieldsOrdered(PostgresDb.TableName, FieldMatch.All, [Field.Equal("Value", "purple")], + await Json.ByFieldsOrdered(PostgresDb.TableName, FieldMatch.All, [Field.Equal("Value", "purple")], [Field.Named("Id")]), "five", "four"); }), @@ -1483,7 +1486,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyExpectedOrder( - Json.ByFieldsOrdered(PostgresDb.TableName, FieldMatch.All, [Field.Equal("Value", "purple")], + await Json.ByFieldsOrdered(PostgresDb.TableName, FieldMatch.All, [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]), "four", "five"); }) @@ -1495,7 +1498,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - var json = Json.ByContains(PostgresDb.TableName, new { Sub = new { Foo = "green" } }); + var json = await Json.ByContains(PostgresDb.TableName, new { Sub = new { Foo = "green" } }); VerifyBeginEnd(json); VerifyDocById(json, "two"); VerifyDocById(json, "four"); @@ -1504,7 +1507,7 @@ public static class PostgresCSharpTests { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyEmpty(Json.ByContains(PostgresDb.TableName, new { Value = "mauve" })); + VerifyEmpty(await Json.ByContains(PostgresDb.TableName, new { Value = "mauve" })); }) ]), TestList("ByContainsOrdered", @@ -1515,7 +1518,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyExpectedOrder( - Json.ByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, + await Json.ByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, [Field.Named("Sub.Bar")]), "two", "four"); }), @@ -1524,7 +1527,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyExpectedOrder( - Json.ByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, + await Json.ByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, [Field.Named("Sub.Bar DESC")]), "four", "two"); }) @@ -1536,7 +1539,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); - var json = Json.ByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 15)"); + var json = await Json.ByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 15)"); VerifyBeginEnd(json); VerifyDocById(json, "one"); VerifyDocById(json, "two"); @@ -1546,7 +1549,7 @@ public static class PostgresCSharpTests { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyEmpty(Json.ByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)")); + VerifyEmpty(await Json.ByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)")); }) ]), TestList("ByJsonPathOrdered", @@ -1557,7 +1560,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyExpectedOrder( - Json.ByJsonPathOrdered(PostgresDb.TableName, "$.NumValue ? (@ < 15)", + await Json.ByJsonPathOrdered(PostgresDb.TableName, "$.NumValue ? (@ < 15)", [Field.Named("n:NumValue")]), "one", "three", "two"); }), @@ -1566,7 +1569,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyExpectedOrder( - Json.ByJsonPathOrdered(PostgresDb.TableName, "$.NumValue ? (@ < 15)", + await Json.ByJsonPathOrdered(PostgresDb.TableName, "$.NumValue ? (@ < 15)", [Field.Named("n:NumValue DESC")]), "two", "three", "one"); }) @@ -1578,7 +1581,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyDocById( - Json.FirstByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "another")]), + await Json.FirstByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "another")]), "two"); }), TestCase("succeeds when multiple documents are found", async () => @@ -1586,14 +1589,15 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyAnyById( - Json.FirstByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")]), + await Json.FirstByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")]), ["five", "four"]); }), TestCase("succeeds when a document is not found", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyNoDoc(Json.FirstByFields(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "absent")])); + VerifyNoDoc(await Json.FirstByFields(PostgresDb.TableName, FieldMatch.Any, + [Field.Equal("Value", "absent")])); }) ]), TestList("FirstByFieldsOrdered", @@ -1603,8 +1607,8 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyDocById( - Json.FirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")], - [Field.Named("Id")]), + await Json.FirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, + [Field.Equal("Value", "purple")], [Field.Named("Id")]), "five"); }), TestCase("succeeds when sorting descending", async () => @@ -1612,8 +1616,8 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyDocById( - Json.FirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, [Field.Equal("Value", "purple")], - [Field.Named("Id DESC")]), + await Json.FirstByFieldsOrdered(PostgresDb.TableName, FieldMatch.Any, + [Field.Equal("Value", "purple")], [Field.Named("Id DESC")]), "four"); }) ]), @@ -1623,20 +1627,20 @@ public static class PostgresCSharpTests { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyDocById(Json.FirstByContains(PostgresDb.TableName, new { Value = "another" }), "two"); + VerifyDocById(await Json.FirstByContains(PostgresDb.TableName, new { Value = "another" }), "two"); }), TestCase("succeeds when multiple documents are found", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyAnyById(Json.FirstByContains(PostgresDb.TableName, new { Sub = new { Foo = "green" } }), + VerifyAnyById(await Json.FirstByContains(PostgresDb.TableName, new { Sub = new { Foo = "green" } }), ["two", "four"]); }), TestCase("succeeds when a document is not found", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyNoDoc(Json.FirstByContains(PostgresDb.TableName, new { Value = "absent" })); + VerifyNoDoc(await Json.FirstByContains(PostgresDb.TableName, new { Value = "absent" })); }) ]), TestList("FirstByContainsOrdered", @@ -1646,7 +1650,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyDocById( - Json.FirstByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, + await Json.FirstByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, [Field.Named("Value")]), "two"); }), @@ -1655,7 +1659,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyDocById( - Json.FirstByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, + await Json.FirstByContainsOrdered(PostgresDb.TableName, new { Sub = new { Foo = "green" } }, [Field.Named("Value DESC")]), "four"); }) @@ -1666,20 +1670,20 @@ public static class PostgresCSharpTests { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyDocById(Json.FirstByJsonPath(PostgresDb.TableName, """$.Value ? (@ == "FIRST!")"""), "one"); + VerifyDocById(await Json.FirstByJsonPath(PostgresDb.TableName, """$.Value ? (@ == "FIRST!")"""), "one"); }), TestCase("succeeds when multiple documents are found", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyAnyById(Json.FirstByJsonPath(PostgresDb.TableName, """$.Sub.Foo ? (@ == "green")"""), + VerifyAnyById(await Json.FirstByJsonPath(PostgresDb.TableName, """$.Sub.Foo ? (@ == "green")"""), ["two", "four"]); }), TestCase("succeeds when a document is not found", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - VerifyNoDoc(Json.FirstByJsonPath(PostgresDb.TableName, """$.Id ? (@ == "nope")""")); + VerifyNoDoc(await Json.FirstByJsonPath(PostgresDb.TableName, """$.Id ? (@ == "nope")""")); }) ]), TestList("FirstByJsonPathOrdered", @@ -1689,7 +1693,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyDocById( - Json.FirstByJsonPathOrdered(PostgresDb.TableName, """$.Sub.Foo ? (@ == "green")""", + await Json.FirstByJsonPathOrdered(PostgresDb.TableName, """$.Sub.Foo ? (@ == "green")""", [Field.Named("Sub.Bar")]), "two"); }), @@ -1698,7 +1702,7 @@ public static class PostgresCSharpTests await using var db = PostgresDb.BuildDb(); await LoadDocs(); VerifyDocById( - Json.FirstByJsonPathOrdered(PostgresDb.TableName, """$.Sub.Foo ? (@ == "green")""", + await Json.FirstByJsonPathOrdered(PostgresDb.TableName, """$.Sub.Foo ? (@ == "green")""", [Field.Named("Sub.Bar DESC")]), "four"); }) diff --git a/src/Tests/PostgresTests.fs b/src/Tests/PostgresTests.fs index a5fd012..8cd730b 100644 --- a/src/Tests/PostgresTests.fs +++ b/src/Tests/PostgresTests.fs @@ -336,16 +336,16 @@ let customTests = testList "Custom" [ use db = PostgresDb.BuildDb() do! loadDocs () - let docs = Custom.jsonArray (Query.find PostgresDb.TableName) [] jsonFromData + let! docs = Custom.jsonArray (Query.find PostgresDb.TableName) [] jsonFromData Expect.stringStarts docs "[" "The JSON array should have started with `[`" - Expect.hasLength (docs.Split "{\"Id\":") 6 "There should have been 5 documents returned" + Expect.hasLength ((string docs).Split "{\"Id\":") 6 "There should have been 5 documents returned" Expect.stringEnds docs "]" "The JSON array should have ended with `[`" } testTask "succeeds when data is not found" { use db = PostgresDb.BuildDb() do! loadDocs () - let docs = + let! docs = Custom.jsonArray $"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath" [ "@path", Sql.string "$.NumValue ? (@ > 100)" ] @@ -360,7 +360,7 @@ let customTests = testList "Custom" [ use stream = new MemoryStream() use writer = writeStream stream - Custom.writeJsonArray (Query.find PostgresDb.TableName) [] writer jsonFromData + do! Custom.writeJsonArray (Query.find PostgresDb.TableName) [] writer jsonFromData let docs = streamText stream Expect.stringStarts docs "[" "The JSON array should have started with `[`" @@ -373,11 +373,11 @@ let customTests = testList "Custom" [ use stream = new MemoryStream() use writer = writeStream stream - Custom.writeJsonArray - $"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath" - [ "@path", Sql.string "$.NumValue ? (@ > 100)" ] - writer - jsonFromData + do! Custom.writeJsonArray + $"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath" + [ "@path", Sql.string "$.NumValue ? (@ > 100)" ] + writer + jsonFromData Expect.equal (streamText stream) "[]" "There should have been no documents returned" } @@ -412,7 +412,7 @@ let customTests = testList "Custom" [ use db = PostgresDb.BuildDb() do! loadDocs () - let doc = + let! doc = Custom.jsonSingle $"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id" [ "@id", Sql.string "one"] @@ -425,7 +425,7 @@ let customTests = testList "Custom" [ use db = PostgresDb.BuildDb() do! loadDocs () - let doc = + let! doc = Custom.jsonSingle $"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id" [ "@id", Sql.string "eighty" ] @@ -1113,16 +1113,16 @@ let private verifyBeginEnd json = Expect.stringEnds json "]" "The array should have ended with `]`" /// Verify the presence of a document by its ID -let private verifyDocById docId json = +let private verifyDocById json docId = Expect.stringContains json $"{{\"Id\": \"%s{docId}\"," $"Document `{docId}` not present" /// Verify the presence of a document by its ID -let private verifySingleById docId json = +let private verifySingleById json docId = verifyBeginEnd json Expect.stringContains json $"{{\"Id\": \"%s{docId}\"," $"Document `{docId}` not present" /// Verify the presence of any of the given document IDs in the given JSON -let private verifyAnyById (docIds: string list) (json: string) = +let private verifyAnyById (json: string) (docIds: string list) = match docIds |> List.tryFind (fun it -> json.Contains $"{{\"Id\": \"{it}\"") with | Some _ -> () | None -> @@ -1132,7 +1132,7 @@ let private verifyAnyById (docIds: string list) (json: string) = /// Verify the JSON for `all` returning data let private verifyAllData json = verifyBeginEnd json - for docId in [ "one"; "two"; "three"; "four"; "five" ] do verifyDocById docId json + [ "one"; "two"; "three"; "four"; "five" ] |> List.iter (verifyDocById json) /// Verify an empty JSON array let private verifyEmpty json = @@ -1143,7 +1143,7 @@ let private verifyNoDoc json = Expect.equal json "{}" "There should be no document returned" /// Verify the JSON for an ordered query -let private verifyExpectedOrder idFirst idSecond idThird idFourth idFifth (json: string) = +let private verifyExpectedOrder (json: string) idFirst idSecond idThird idFourth idFifth = let firstIdx = json.IndexOf $"{{\"Id\": \"%s{idFirst}\"," let secondIdx = json.IndexOf $"{{\"Id\": \"%s{idSecond}\"," verifyBeginEnd json @@ -1170,31 +1170,33 @@ let jsonTests = testList "Json" [ testTask "succeeds when there is data" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.all PostgresDb.TableName |> verifyAllData + let! json = Json.all PostgresDb.TableName + verifyAllData json } testTask "succeeds when there is no data" { use db = PostgresDb.BuildDb() - Json.all PostgresDb.TableName |> verifyEmpty + let! json = Json.all PostgresDb.TableName + verifyEmpty json } ] testList "allOrdered" [ testTask "succeeds when ordering numerically" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.allOrdered PostgresDb.TableName [ Field.Named "n:NumValue" ] - |> verifyExpectedOrder "one" "three" (Some "two") (Some "four") (Some "five") + let! json = Json.allOrdered PostgresDb.TableName [ Field.Named "n:NumValue" ] + verifyExpectedOrder json "one" "three" (Some "two") (Some "four") (Some "five") } testTask "succeeds when ordering numerically descending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.allOrdered PostgresDb.TableName [ Field.Named "n:NumValue DESC" ] - |> verifyExpectedOrder "five" "four" (Some "two") (Some "three") (Some "one") + let! json = Json.allOrdered PostgresDb.TableName [ Field.Named "n:NumValue DESC" ] + verifyExpectedOrder json "five" "four" (Some "two") (Some "three") (Some "one") } testTask "succeeds when ordering alphabetically" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.allOrdered PostgresDb.TableName [ Field.Named "Id DESC" ] - |> verifyExpectedOrder "two" "three" (Some "one") (Some "four") (Some "five") + let! json = Json.allOrdered PostgresDb.TableName [ Field.Named "Id DESC" ] + verifyExpectedOrder json "two" "three" (Some "one") (Some "four") (Some "five") } ] testList "byId" [ @@ -1202,64 +1204,70 @@ let jsonTests = testList "Json" [ use db = PostgresDb.BuildDb() do! loadDocs () - let json = Json.byId PostgresDb.TableName "two" + let! json = Json.byId PostgresDb.TableName "two" Expect.stringStarts json """{"Id": "two",""" "An incorrect document was returned" Expect.stringEnds json "}" "JSON should have ended with this document" } testTask "succeeds when a document is not found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byId PostgresDb.TableName "three hundred eighty-seven" |> verifyNoDoc + let! json = Json.byId PostgresDb.TableName "three hundred eighty-seven" + verifyNoDoc json } ] testList "byFields" [ testTask "succeeds when documents are found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byFields PostgresDb.TableName All [ Field.In "Value" [ "purple"; "blue" ]; Field.Exists "Sub" ] - |> verifySingleById "four" + let! json = + Json.byFields PostgresDb.TableName All [ Field.In "Value" [ "purple"; "blue" ]; Field.Exists "Sub" ] + verifySingleById json "four" } testTask "succeeds when documents are found using IN with numeric field" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byFields PostgresDb.TableName All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ] |> verifySingleById "three" + let! json = Json.byFields PostgresDb.TableName All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ] + verifySingleById json "three" } testTask "succeeds when documents are not found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byFields PostgresDb.TableName All [ Field.Equal "Value" "mauve"; Field.NotEqual "NumValue" 40 ] - |> verifyEmpty + let! json = + Json.byFields PostgresDb.TableName All [ Field.Equal "Value" "mauve"; Field.NotEqual "NumValue" 40 ] + verifyEmpty json } 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 json = Json.byFields PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "c" ] ] + let! json = Json.byFields PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "c" ] ] verifyBeginEnd json - verifyDocById "first" json - verifyDocById "second" json + verifyDocById json "first" + verifyDocById json "second" } 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 - Json.byFields PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "j" ] ] - |> verifyEmpty + let! json = Json.byFields PostgresDb.TableName All [ Field.InArray "Values" PostgresDb.TableName [ "j" ] ] + verifyEmpty json } ] testList "byFieldsOrdered" [ testTask "succeeds when sorting ascending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byFieldsOrdered PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] - |> verifyExpectedOrder "five" "four" None None None + let! json = + Json.byFieldsOrdered PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] + verifyExpectedOrder json "five" "four" None None None } testTask "succeeds when sorting descending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byFieldsOrdered PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] - |> verifyExpectedOrder "four" "five" None None None + let! json = + Json.byFieldsOrdered PostgresDb.TableName All [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] + verifyExpectedOrder json "four" "five" None None None } ] testList "byContains" [ @@ -1267,15 +1275,16 @@ let jsonTests = testList "Json" [ use db = PostgresDb.BuildDb() do! loadDocs () - let json = Json.byContains PostgresDb.TableName {| Sub = {| Foo = "green" |} |} + let! json = Json.byContains PostgresDb.TableName {| Sub = {| Foo = "green" |} |} verifyBeginEnd json - verifyDocById "two" json - verifyDocById "four" json + verifyDocById json "two" + verifyDocById json "four" } testTask "succeeds when documents are not found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byContains PostgresDb.TableName {| Value = "mauve" |} |> verifyEmpty + let! json = Json.byContains PostgresDb.TableName {| Value = "mauve" |} + verifyEmpty json } ] testList "byContainsOrdered" [ @@ -1283,14 +1292,17 @@ let jsonTests = testList "Json" [ testTask "succeeds when sorting ascending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byContainsOrdered PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar" ] - |> verifyExpectedOrder "two" "four" None None None + let! json = + Json.byContainsOrdered PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar" ] + verifyExpectedOrder json "two" "four" None None None } testTask "succeeds when sorting descending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byContainsOrdered PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar DESC" ] - |> verifyExpectedOrder "four" "two" None None None + let! json = + Json.byContainsOrdered + PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Sub.Bar DESC" ] + verifyExpectedOrder json "four" "two" None None None } ] testList "byJsonPath" [ @@ -1298,16 +1310,17 @@ let jsonTests = testList "Json" [ use db = PostgresDb.BuildDb() do! loadDocs () - let json = Json.byJsonPath PostgresDb.TableName "$.NumValue ? (@ < 15)" + let! json = Json.byJsonPath PostgresDb.TableName "$.NumValue ? (@ < 15)" verifyBeginEnd json - verifyDocById "one" json - verifyDocById "two" json - verifyDocById "three" json + verifyDocById json "one" + verifyDocById json "two" + verifyDocById json "three" } testTask "succeeds when documents are not found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byJsonPath PostgresDb.TableName "$.NumValue ? (@ < 0)" |> verifyEmpty + let! json = Json.byJsonPath PostgresDb.TableName "$.NumValue ? (@ < 0)" + verifyEmpty json } ] testList "byJsonPathOrdered" [ @@ -1315,113 +1328,127 @@ let jsonTests = testList "Json" [ testTask "succeeds when sorting ascending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byJsonPathOrdered PostgresDb.TableName "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue" ] - |> verifyExpectedOrder "one" "three" (Some "two") None None + let! json = Json.byJsonPathOrdered PostgresDb.TableName "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue" ] + verifyExpectedOrder json "one" "three" (Some "two") None None } testTask "succeeds when sorting descending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.byJsonPathOrdered PostgresDb.TableName "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue DESC" ] - |> verifyExpectedOrder "two" "three" (Some "one") None None + let! json = + Json.byJsonPathOrdered PostgresDb.TableName "$.NumValue ? (@ < 15)" [ Field.Named "n:NumValue DESC" ] + verifyExpectedOrder json "two" "three" (Some "one") None None } ] testList "firstByFields" [ testTask "succeeds when a document is found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "another" ] - |> verifyDocById "two" + let! json = Json.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "another" ] + verifyDocById json "two" } testTask "succeeds when multiple documents are found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] - |> verifyAnyById [ "five"; "four" ] + let! json = Json.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] + verifyAnyById json [ "five"; "four" ] } testTask "succeeds when a document is not found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "absent" ] |> verifyNoDoc + let! json = Json.firstByFields PostgresDb.TableName Any [ Field.Equal "Value" "absent" ] + verifyNoDoc json } ] testList "firstByFieldsOrdered" [ testTask "succeeds when sorting ascending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByFieldsOrdered PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] - |> verifyDocById "five" + let! json = + Json.firstByFieldsOrdered PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id" ] + verifyDocById json "five" } testTask "succeeds when sorting descending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByFieldsOrdered - PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] - |> verifyDocById "four" + let! json = + Json.firstByFieldsOrdered + PostgresDb.TableName Any [ Field.Equal "Value" "purple" ] [ Field.Named "Id DESC" ] + verifyDocById json "four" } ] testList "firstByContains" [ testTask "succeeds when a document is found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByContains PostgresDb.TableName {| Value = "another" |} |> verifyDocById "two" + let! json = Json.firstByContains PostgresDb.TableName {| Value = "another" |} + verifyDocById json "two" } testTask "succeeds when multiple documents are found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByContains PostgresDb.TableName {| Sub = {| Foo = "green" |} |} |> verifyAnyById [ "two"; "four" ] + let! json = Json.firstByContains PostgresDb.TableName {| Sub = {| Foo = "green" |} |} + verifyAnyById json [ "two"; "four" ] } testTask "succeeds when a document is not found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByContains PostgresDb.TableName {| Value = "absent" |} |> verifyNoDoc + let! json = Json.firstByContains PostgresDb.TableName {| Value = "absent" |} + verifyNoDoc json } ] testList "firstByContainsOrdered" [ testTask "succeeds when sorting ascending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByContainsOrdered PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Value" ] - |> verifyDocById "two" + let! json = + Json.firstByContainsOrdered PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Value" ] + verifyDocById json "two" } testTask "succeeds when sorting descending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByContainsOrdered - PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Value DESC" ] - |> verifyDocById "four" + let! json = + Json.firstByContainsOrdered + PostgresDb.TableName {| Sub = {| Foo = "green" |} |} [ Field.Named "Value DESC" ] + verifyDocById json "four" } ] testList "firstByJsonPath" [ testTask "succeeds when a document is found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByJsonPath PostgresDb.TableName """$.Value ? (@ == "FIRST!")""" |> verifyDocById "one" + let! json = Json.firstByJsonPath PostgresDb.TableName """$.Value ? (@ == "FIRST!")""" + verifyDocById json "one" } testTask "succeeds when multiple documents are found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByJsonPath PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" - |> verifyAnyById [ "two"; "four" ] + let! json = Json.firstByJsonPath PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" + verifyAnyById json [ "two"; "four" ] } testTask "succeeds when a document is not found" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByJsonPath PostgresDb.TableName """$.Id ? (@ == "nope")""" |> verifyNoDoc + let! json = Json.firstByJsonPath PostgresDb.TableName """$.Id ? (@ == "nope")""" + verifyNoDoc json } ] testList "firstByJsonPathOrdered" [ testTask "succeeds when sorting ascending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByJsonPathOrdered PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar" ] - |> verifyDocById "two" + let! json = + Json.firstByJsonPathOrdered + PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar" ] + verifyDocById json "two" } testTask "succeeds when sorting descending" { use db = PostgresDb.BuildDb() do! loadDocs () - Json.firstByJsonPathOrdered - PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar DESC" ] - |> verifyDocById "four" + let! json = + Json.firstByJsonPathOrdered + PostgresDb.TableName """$.Sub.Foo ? (@ == "green")""" [ Field.Named "Sub.Bar DESC" ] + verifyDocById json "four" } ] ]