From d9e37445a8a9799adb234b03e9a3eb6f45c5dd26 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Thu, 28 Dec 2023 19:39:02 -0500 Subject: [PATCH] Change "update partial" to "patch" for Postgres --- src/Common/Library.fs | 13 +- src/Postgres/Extensions.fs | 72 ++++----- src/Postgres/Library.fs | 149 +++++++++--------- src/Sqlite/Library.fs | 2 +- src/Tests.CSharp/CommonCSharpTests.cs | 10 +- .../PostgresCSharpExtensionTests.cs | 40 +++-- src/Tests.CSharp/PostgresCSharpTests.cs | 63 ++++---- src/Tests/CommonTests.fs | 14 +- src/Tests/PostgresExtensionTests.fs | 36 ++--- src/Tests/PostgresTests.fs | 56 +++---- 10 files changed, 225 insertions(+), 230 deletions(-) diff --git a/src/Common/Library.fs b/src/Common/Library.fs index 0c85cce..2f45c2b 100644 --- a/src/Common/Library.fs +++ b/src/Common/Library.fs @@ -163,6 +163,11 @@ module Query = "INSERT INTO %s VALUES (@data) ON CONFLICT ((data ->> '%s')) DO UPDATE SET data = EXCLUDED.data" tableName (Configuration.idField ()) + /// Query to update a document + [] + let update tableName = + $"""UPDATE %s{tableName} SET data = @data WHERE {whereById "@id"}""" + /// Queries for counting documents module Count = @@ -202,14 +207,6 @@ module Query = let byField tableName fieldName op = $"""{selectFromTable tableName} WHERE {whereByField fieldName op "@field"}""" - /// Queries to update documents - module Update = - - /// Query to update a document - [] - let full tableName = - $"""UPDATE %s{tableName} SET data = @data WHERE {whereById "@id"}""" - /// Queries to delete documents module Delete = diff --git a/src/Postgres/Extensions.fs b/src/Postgres/Extensions.fs index e1bd553..4602341 100644 --- a/src/Postgres/Extensions.fs +++ b/src/Postgres/Extensions.fs @@ -109,29 +109,29 @@ module Extensions = member conn.findFirstByJsonPath<'TDoc> tableName jsonPath = WithProps.Find.firstByJsonPath<'TDoc> tableName jsonPath (Sql.existingConnection conn) - /// Update a full document - member conn.updateFull tableName (docId: 'TKey) (document: 'TDoc) = - WithProps.Update.full tableName docId document (Sql.existingConnection conn) + /// Update an entire document by its ID + member conn.updateById tableName (docId: 'TKey) (document: 'TDoc) = + WithProps.Update.byId tableName docId document (Sql.existingConnection conn) - /// Update a full document - member conn.updateFullFunc tableName (idFunc: 'TDoc -> 'TKey) (document: 'TDoc) = - WithProps.Update.fullFunc tableName idFunc document (Sql.existingConnection conn) + /// Update an entire document by its ID, using the provided function to obtain the ID from the document + member conn.updateByFunc tableName (idFunc: 'TDoc -> 'TKey) (document: 'TDoc) = + WithProps.Update.byFunc tableName idFunc document (Sql.existingConnection conn) - /// Update a partial document - member conn.updatePartialById tableName (docId: 'TKey) (partial: 'TPartial) = - WithProps.Update.partialById tableName docId partial (Sql.existingConnection conn) + /// Patch a document by its ID + member conn.patchById tableName (docId: 'TKey) (patch: 'TPatch) = + WithProps.Patch.byId tableName docId patch (Sql.existingConnection conn) - /// Update partial documents using a JSON field comparison query in the WHERE clause (->> =) - member conn.updatePartialByField tableName fieldName op (value: obj) (partial: 'TPartial) = - WithProps.Update.partialByField tableName fieldName op value partial (Sql.existingConnection conn) + /// Patch documents using a JSON field comparison query in the WHERE clause (->> =) + member conn.patchByField tableName fieldName op (value: obj) (patch: 'TPatch) = + WithProps.Patch.byField tableName fieldName op value patch (Sql.existingConnection conn) - /// Update partial documents using a JSON containment query in the WHERE clause (@>) - member conn.updatePartialByContains tableName (criteria: 'TCriteria) (partial: 'TPartial) = - WithProps.Update.partialByContains tableName criteria partial (Sql.existingConnection conn) + /// Patch documents using a JSON containment query in the WHERE clause (@>) + member conn.patchByContains tableName (criteria: 'TCriteria) (patch: 'TPatch) = + WithProps.Patch.byContains tableName criteria patch (Sql.existingConnection conn) - /// Update partial documents using a JSON Path match query in the WHERE clause (@?) - member conn.updatePartialByJsonPath tableName jsonPath (partial: 'TPartial) = - WithProps.Update.partialByJsonPath tableName jsonPath partial (Sql.existingConnection conn) + /// Patch documents using a JSON Path match query in the WHERE clause (@?) + member conn.patchByJsonPath tableName jsonPath (patch: 'TPatch) = + WithProps.Patch.byJsonPath tableName jsonPath patch (Sql.existingConnection conn) /// Delete a document by its ID member conn.deleteById tableName (docId: 'TKey) = @@ -282,35 +282,35 @@ type NpgsqlConnectionCSharpExtensions = static member inline FindFirstByJsonPath<'TDoc when 'TDoc: null>(conn, tableName, jsonPath) = WithProps.Find.FirstByJsonPath<'TDoc>(tableName, jsonPath, Sql.existingConnection conn) - /// Update a full document + /// Update an entire document by its ID [] - static member inline UpdateFull(conn, tableName, docId: 'TKey, document: 'TDoc) = - WithProps.Update.full tableName docId document (Sql.existingConnection conn) + static member inline UpdateById(conn, tableName, docId: 'TKey, document: 'TDoc) = + WithProps.Update.byId tableName docId document (Sql.existingConnection conn) - /// Update a full document + /// Update an entire document by its ID, using the provided function to obtain the ID from the document [] - static member inline UpdateFullFunc(conn, tableName, idFunc: System.Func<'TDoc, 'TKey>, document: 'TDoc) = - WithProps.Update.FullFunc(tableName, idFunc, document, Sql.existingConnection conn) + static member inline UpdateByFunc(conn, tableName, idFunc: System.Func<'TDoc, 'TKey>, document: 'TDoc) = + WithProps.Update.ByFunc(tableName, idFunc, document, Sql.existingConnection conn) - /// Update a partial document + /// Patch a document by its ID [] - static member inline UpdatePartialById(conn, tableName, docId: 'TKey, partial: 'TPartial) = - WithProps.Update.partialById tableName docId partial (Sql.existingConnection conn) + static member inline PatchById(conn, tableName, docId: 'TKey, patch: 'TPatch) = + WithProps.Patch.byId tableName docId patch (Sql.existingConnection conn) - /// Update partial documents using a JSON field comparison query in the WHERE clause (->> =) + /// Patch documents using a JSON field comparison query in the WHERE clause (->> =) [] - static member inline UpdatePartialByField(conn, tableName, fieldName, op, value: obj, partial: 'TPartial) = - WithProps.Update.partialByField tableName fieldName op value partial (Sql.existingConnection conn) + static member inline PatchByField(conn, tableName, fieldName, op, value: obj, patch: 'TPatch) = + WithProps.Patch.byField tableName fieldName op value patch (Sql.existingConnection conn) - /// Update partial documents using a JSON containment query in the WHERE clause (@>) + /// Patch documents using a JSON containment query in the WHERE clause (@>) [] - static member inline UpdatePartialByContains(conn, tableName, criteria: 'TCriteria, partial: 'TPartial) = - WithProps.Update.partialByContains tableName criteria partial (Sql.existingConnection conn) + static member inline PatchByContains(conn, tableName, criteria: 'TCriteria, patch: 'TPatch) = + WithProps.Patch.byContains tableName criteria patch (Sql.existingConnection conn) - /// Update partial documents using a JSON Path match query in the WHERE clause (@?) + /// Patch documents using a JSON Path match query in the WHERE clause (@?) [] - static member inline UpdatePartialByJsonPath(conn, tableName, jsonPath, partial: 'TPartial) = - WithProps.Update.partialByJsonPath tableName jsonPath partial (Sql.existingConnection conn) + static member inline PatchByJsonPath(conn, tableName, jsonPath, patch: 'TPatch) = + WithProps.Patch.byJsonPath tableName jsonPath patch (Sql.existingConnection conn) /// Delete a document by its ID [] diff --git a/src/Postgres/Library.fs b/src/Postgres/Library.fs index 1ea570a..5fcb7cc 100644 --- a/src/Postgres/Library.fs +++ b/src/Postgres/Library.fs @@ -142,27 +142,27 @@ module Query = let byJsonPath tableName = $"""{Query.selectFromTable tableName} WHERE {whereJsonPathMatches "@path"}""" - /// Queries to update documents - module Update = + /// Queries to patch (partially update) documents + module Patch = - /// Query to update a document - [] - let partialById tableName = + /// Query to patch a document by its ID + [] + let byId tableName = $"""UPDATE %s{tableName} SET data = data || @data WHERE {Query.whereById "@id"}""" - /// Query to update a document - [] - let partialByField tableName fieldName op = + /// Query to patch documents match a JSON field comparison (->> =) + [] + let byField tableName fieldName op = $"""UPDATE %s{tableName} SET data = data || @data WHERE {Query.whereByField fieldName op "@field"}""" - /// Query to update partial documents matching a JSON containment query (@>) - [] - let partialByContains tableName = + /// Query to patch documents matching a JSON containment query (@>) + [] + let byContains tableName = $"""UPDATE %s{tableName} SET data = data || @data WHERE {whereDataContains "@criteria"}""" - /// Query to update partial documents matching a JSON containment query (@>) - [] - let partialByJsonPath tableName = + /// Query to patch documents matching a JSON containment query (@>) + [] + let byJsonPath tableName = $"""UPDATE %s{tableName} SET data = data || @data WHERE {whereJsonPathMatches "@path"}""" /// Queries to delete documents @@ -436,48 +436,46 @@ module WithProps = [] module Update = - /// Update an entire document - [] - let full tableName (docId: 'TKey) (document: 'TDoc) sqlProps = - Custom.nonQuery (Query.Update.full tableName) [ idParam docId; jsonParam "@data" document ] sqlProps + /// Update an entire document by its ID + [] + let byId tableName (docId: 'TKey) (document: 'TDoc) sqlProps = + Custom.nonQuery (Query.update tableName) [ idParam docId; jsonParam "@data" document ] sqlProps - /// Update an entire document - [] - let fullFunc tableName (idFunc: 'TDoc -> 'TKey) (document: 'TDoc) sqlProps = - full tableName (idFunc document) document sqlProps + /// Update an entire document by its ID, using the provided function to obtain the ID from the document + [] + let byFunc tableName (idFunc: 'TDoc -> 'TKey) (document: 'TDoc) sqlProps = + byId tableName (idFunc document) document sqlProps - /// Update an entire document - let FullFunc(tableName, idFunc: System.Func<'TDoc, 'TKey>, document: 'TDoc, sqlProps) = - fullFunc tableName idFunc.Invoke document sqlProps + /// Update an entire document by its ID, using the provided function to obtain the ID from the document + let ByFunc(tableName, idFunc: System.Func<'TDoc, 'TKey>, document: 'TDoc, sqlProps) = + byFunc tableName idFunc.Invoke document sqlProps + + /// Commands to patch (partially update) documents + [] + module Patch = - /// Update a partial document - [] - let partialById tableName (docId: 'TKey) (partial: 'TPartial) sqlProps = - Custom.nonQuery (Query.Update.partialById tableName) [ idParam docId; jsonParam "@data" partial ] sqlProps + /// Patch a document by its ID + [] + let byId tableName (docId: 'TKey) (patch: 'TPatch) sqlProps = + Custom.nonQuery (Query.Patch.byId tableName) [ idParam docId; jsonParam "@data" patch ] sqlProps - /// Update partial documents using a JSON field comparison query in the WHERE clause (->> =) - [] - let partialByField tableName fieldName op (value: obj) (partial: 'TPartial) sqlProps = + /// Patch documents using a JSON field comparison query in the WHERE clause (->> =) + [] + let byField tableName fieldName op (value: obj) (patch: 'TPatch) sqlProps = Custom.nonQuery - (Query.Update.partialByField tableName fieldName op) - [ jsonParam "@data" partial; fieldParam value ] - sqlProps + (Query.Patch.byField tableName fieldName op) [ jsonParam "@data" patch; fieldParam value ] sqlProps - /// Update partial documents using a JSON containment query in the WHERE clause (@>) - [] - let partialByContains tableName (criteria: 'TContains) (partial: 'TPartial) sqlProps = + /// Patch documents using a JSON containment query in the WHERE clause (@>) + [] + let byContains tableName (criteria: 'TContains) (patch: 'TPatch) sqlProps = Custom.nonQuery - (Query.Update.partialByContains tableName) - [ jsonParam "@data" partial; jsonParam "@criteria" criteria ] - sqlProps + (Query.Patch.byContains tableName) [ jsonParam "@data" patch; jsonParam "@criteria" criteria ] sqlProps - /// Update partial documents using a JSON Path match query in the WHERE clause (@?) - [] - let partialByJsonPath tableName jsonPath (partial: 'TPartial) sqlProps = + /// Patch documents using a JSON Path match query in the WHERE clause (@?) + [] + let byJsonPath tableName jsonPath (patch: 'TPatch) sqlProps = Custom.nonQuery - (Query.Update.partialByJsonPath tableName) - [ jsonParam "@data" partial; "@path", Sql.string jsonPath ] - sqlProps + (Query.Patch.byJsonPath tableName) [ jsonParam "@data" patch; "@path", Sql.string jsonPath ] sqlProps /// Commands to delete documents [] @@ -707,39 +705,44 @@ module Find = [] module Update = - /// Update a full document - [] - let full tableName (docId: 'TKey) (document: 'TDoc) = - WithProps.Update.full tableName docId document (fromDataSource ()) + /// Update an entire document by its ID + [] + let byId tableName (docId: 'TKey) (document: 'TDoc) = + WithProps.Update.byId tableName docId document (fromDataSource ()) - /// Update a full document + /// Update an entire document by its ID, using the provided function to obtain the ID from the document [] - let fullFunc tableName (idFunc: 'TDoc -> 'TKey) (document: 'TDoc) = - WithProps.Update.fullFunc tableName idFunc document (fromDataSource ()) + let byFunc tableName (idFunc: 'TDoc -> 'TKey) (document: 'TDoc) = + WithProps.Update.byFunc tableName idFunc document (fromDataSource ()) + + /// Update an entire document by its ID, using the provided function to obtain the ID from the document + let ByFunc(tableName, idFunc: System.Func<'TDoc, 'TKey>, document: 'TDoc) = + WithProps.Update.ByFunc(tableName, idFunc, document, fromDataSource ()) - /// Update a full document - let FullFunc(tableName, idFunc: System.Func<'TDoc, 'TKey>, document: 'TDoc) = - WithProps.Update.FullFunc(tableName, idFunc, document, fromDataSource ()) - /// Update a partial document - [] - let partialById tableName (docId: 'TKey) (partial: 'TPartial) = - WithProps.Update.partialById tableName docId partial (fromDataSource ()) +/// Commands to patch (partially update) documents +[] +module Patch = - /// Update partial documents using a JSON field comparison query in the WHERE clause (->> =) - [] - let partialByField tableName fieldName op (value: obj) (partial: 'TPartial) = - WithProps.Update.partialByField tableName fieldName op value partial (fromDataSource ()) + /// Patch a document by its ID + [] + let byId tableName (docId: 'TKey) (patch: 'TPatch) = + WithProps.Patch.byId tableName docId patch (fromDataSource ()) - /// Update partial documents using a JSON containment query in the WHERE clause (@>) - [] - let partialByContains tableName (criteria: 'TCriteria) (partial: 'TPartial) = - WithProps.Update.partialByContains tableName criteria partial (fromDataSource ()) + /// Patch documents using a JSON field comparison query in the WHERE clause (->> =) + [] + let byField tableName fieldName op (value: obj) (patch: 'TPatch) = + WithProps.Patch.byField tableName fieldName op value patch (fromDataSource ()) - /// Update partial documents using a JSON Path match query in the WHERE clause (@?) - [] - let partialByJsonPath tableName jsonPath (partial: 'TPartial) = - WithProps.Update.partialByJsonPath tableName jsonPath partial (fromDataSource ()) + /// Patch documents using a JSON containment query in the WHERE clause (@>) + [] + let byContains tableName (criteria: 'TCriteria) (patch: 'TPatch) = + WithProps.Patch.byContains tableName criteria patch (fromDataSource ()) + + /// Patch documents using a JSON Path match query in the WHERE clause (@?) + [] + let byJsonPath tableName jsonPath (patch: 'TPatch) = + WithProps.Patch.byJsonPath tableName jsonPath patch (fromDataSource ()) /// Commands to delete documents diff --git a/src/Sqlite/Library.fs b/src/Sqlite/Library.fs index 21e82f2..9920d15 100644 --- a/src/Sqlite/Library.fs +++ b/src/Sqlite/Library.fs @@ -298,7 +298,7 @@ module WithConn = /// Update an entire document [] let full tableName (docId: 'TKey) (document: 'TDoc) conn = - Custom.nonQuery (Query.Update.full tableName) [ idParam docId; jsonParam "@data" document ] conn + Custom.nonQuery (Query.update tableName) [ idParam docId; jsonParam "@data" document ] conn /// Update an entire document [] diff --git a/src/Tests.CSharp/CommonCSharpTests.cs b/src/Tests.CSharp/CommonCSharpTests.cs index ecfb9f9..c75d2ba 100644 --- a/src/Tests.CSharp/CommonCSharpTests.cs +++ b/src/Tests.CSharp/CommonCSharpTests.cs @@ -172,6 +172,11 @@ public static class CommonCSharpTests $"INSERT INTO tbl VALUES (@data) ON CONFLICT ((data ->> 'Id')) DO UPDATE SET data = EXCLUDED.data", "INSERT ON CONFLICT UPDATE statement not correct"); }), + TestCase("Update succeeds", () => + { + Expect.equal(Query.Update("tbl"), "UPDATE tbl SET data = @data WHERE data ->> 'Id' = @id", + "UPDATE full statement not correct"); + }), TestList("Count", new[] { TestCase("All succeeds", () => @@ -214,11 +219,6 @@ public static class CommonCSharpTests "SELECT by JSON comparison query not correct"); }) }), - TestCase("Update.Full succeeds", () => - { - Expect.equal(Query.Update.Full("tbl"), "UPDATE tbl SET data = @data WHERE data ->> 'Id' = @id", - "UPDATE full statement not correct"); - }), TestList("Delete", new[] { TestCase("ById succeeds", () => diff --git a/src/Tests.CSharp/PostgresCSharpExtensionTests.cs b/src/Tests.CSharp/PostgresCSharpExtensionTests.cs index 103e890..4f0ee63 100644 --- a/src/Tests.CSharp/PostgresCSharpExtensionTests.cs +++ b/src/Tests.CSharp/PostgresCSharpExtensionTests.cs @@ -558,7 +558,7 @@ public class PostgresCSharpExtensionTests Expect.isNull(doc, "There should not have been a document returned"); }) }), - TestList("UpdateFull", new[] + TestList("UpdateById", new[] { TestCase("succeeds when a document is updated", async () => { @@ -566,7 +566,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - await conn.UpdateFull(PostgresDb.TableName, "one", + await conn.UpdateById(PostgresDb.TableName, "one", new JsonDocument { Id = "one", Sub = new() { Foo = "blue", Bar = "red" } }); var after = await conn.FindById(PostgresDb.TableName, "one"); Expect.isNotNull(after, "There should have been a document returned post-update"); @@ -585,11 +585,11 @@ public class PostgresCSharpExtensionTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await conn.UpdateFull(PostgresDb.TableName, "test", + await conn.UpdateById(PostgresDb.TableName, "test", new JsonDocument { Id = "x", Sub = new() { Foo = "blue", Bar = "red" } }); }) }), - TestList("UpdateFullFunc", new[] + TestList("UpdateByFunc", new[] { TestCase("succeeds when a document is updated", async () => { @@ -597,7 +597,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - await conn.UpdateFullFunc(PostgresDb.TableName, doc => doc.Id, + await conn.UpdateByFunc(PostgresDb.TableName, doc => doc.Id, new JsonDocument { Id = "one", Value = "le un", NumValue = 1 }); var after = await conn.FindById(PostgresDb.TableName, "one"); Expect.isNotNull(after, "There should have been a document returned post-update"); @@ -614,11 +614,11 @@ public class PostgresCSharpExtensionTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await conn.UpdateFullFunc(PostgresDb.TableName, doc => doc.Id, + await conn.UpdateByFunc(PostgresDb.TableName, doc => doc.Id, new JsonDocument { Id = "one", Value = "le un", NumValue = 1 }); }) }), - TestList("UpdatePartialById", new[] + TestList("PatchById", new[] { TestCase("succeeds when a document is updated", async () => { @@ -626,7 +626,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - await conn.UpdatePartialById(PostgresDb.TableName, "one", new { NumValue = 44 }); + await conn.PatchById(PostgresDb.TableName, "one", new { NumValue = 44 }); var after = await conn.FindById(PostgresDb.TableName, "one"); Expect.isNotNull(after, "There should have been a document returned post-update"); Expect.equal(after.NumValue, 44, "The updated document is not correct"); @@ -639,10 +639,10 @@ public class PostgresCSharpExtensionTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await conn.UpdatePartialById(PostgresDb.TableName, "test", new { Foo = "green" }); + await conn.PatchById(PostgresDb.TableName, "test", new { Foo = "green" }); }) }), - TestList("UpdatePartialByField", new[] + TestList("PatchByField", new[] { TestCase("succeeds when a document is updated", async () => { @@ -650,7 +650,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - await conn.UpdatePartialByField(PostgresDb.TableName, "Value", Op.EQ, "purple", new { NumValue = 77 }); + await conn.PatchByField(PostgresDb.TableName, "Value", Op.EQ, "purple", new { NumValue = 77 }); var after = await conn.CountByField(PostgresDb.TableName, "NumValue", Op.EQ, "77"); Expect.equal(after, 2, "There should have been 2 documents returned"); }), @@ -662,11 +662,10 @@ public class PostgresCSharpExtensionTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await conn.UpdatePartialByField(PostgresDb.TableName, "Value", Op.EQ, "burgundy", - new { Foo = "green" }); + await conn.PatchByField(PostgresDb.TableName, "Value", Op.EQ, "burgundy", new { Foo = "green" }); }) }), - TestList("UpdatePartialByContains", new[] + TestList("PatchByContains", new[] { TestCase("succeeds when a document is updated", async () => { @@ -674,8 +673,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - await conn.UpdatePartialByContains(PostgresDb.TableName, new { Value = "purple" }, - new { NumValue = 77 }); + await conn.PatchByContains(PostgresDb.TableName, new { Value = "purple" }, new { NumValue = 77 }); var after = await conn.CountByContains(PostgresDb.TableName, new { NumValue = 77 }); Expect.equal(after, 2, "There should have been 2 documents returned"); }), @@ -687,11 +685,10 @@ public class PostgresCSharpExtensionTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await conn.UpdatePartialByContains(PostgresDb.TableName, new { Value = "burgundy" }, - new { Foo = "green" }); + await conn.PatchByContains(PostgresDb.TableName, new { Value = "burgundy" }, new { Foo = "green" }); }) }), - TestList("UpdatePartialByJsonPath", new[] + TestList("PatchByJsonPath", new[] { TestCase("succeeds when a document is updated", async () => { @@ -699,8 +696,7 @@ public class PostgresCSharpExtensionTests await using var conn = MkConn(db); await LoadDocs(); - await conn.UpdatePartialByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 10)", - new { NumValue = 1000 }); + await conn.PatchByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 10)", new { NumValue = 1000 }); var after = await conn.CountByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 999)"); Expect.equal(after, 2, "There should have been 2 documents returned"); }), @@ -712,7 +708,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.UpdatePartialByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)", new { Foo = "green" }); + await conn.PatchByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)", new { Foo = "green" }); }) }), TestList("DeleteById", new[] diff --git a/src/Tests.CSharp/PostgresCSharpTests.cs b/src/Tests.CSharp/PostgresCSharpTests.cs index 72af8cb..a4713c7 100644 --- a/src/Tests.CSharp/PostgresCSharpTests.cs +++ b/src/Tests.CSharp/PostgresCSharpTests.cs @@ -124,29 +124,29 @@ public class PostgresCSharpTests "SELECT by JSON Path match query not correct"); }) }), - TestList("Update", new[] + TestList("Patch", new[] { - TestCase("partialById succeeds", () => + TestCase("ById succeeds", () => { - Expect.equal(Postgres.Query.Update.PartialById(PostgresDb.TableName), + Expect.equal(Postgres.Query.Patch.ById(PostgresDb.TableName), $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data ->> 'Id' = @id", "UPDATE partial by ID statement not correct"); }), - TestCase("partialByField succeeds", () => + TestCase("ByField succeeds", () => { - Expect.equal(Postgres.Query.Update.PartialByField(PostgresDb.TableName, "Snail", Op.LT), + Expect.equal(Postgres.Query.Patch.ByField(PostgresDb.TableName, "Snail", Op.LT), $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data ->> 'Snail' < @field", "UPDATE partial by ID statement not correct"); }), - TestCase("partialByContains succeeds", () => + TestCase("ByContains succeeds", () => { - Expect.equal(Postgres.Query.Update.PartialByContains(PostgresDb.TableName), + Expect.equal(Postgres.Query.Patch.ByContains(PostgresDb.TableName), $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data @> @criteria", "UPDATE partial by JSON containment statement not correct"); }), - TestCase("partialByJsonPath succeeds", () => + TestCase("ByJsonPath succeeds", () => { - Expect.equal(Postgres.Query.Update.PartialByJsonPath(PostgresDb.TableName), + Expect.equal(Postgres.Query.Patch.ByJsonPath(PostgresDb.TableName), $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data @? @path::jsonpath", "UPDATE partial by JSON Path statement not correct"); }) @@ -722,14 +722,14 @@ public class PostgresCSharpTests }), TestList("Update", new[] { - TestList("Full", new[] + TestList("ById", new[] { TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - await Update.Full(PostgresDb.TableName, "one", + await Update.ById(PostgresDb.TableName, "one", new JsonDocument { Id = "one", Sub = new() { Foo = "blue", Bar = "red" } }); var after = await Find.ById(PostgresDb.TableName, "one"); Expect.isNotNull(after, "There should have been a document returned post-update"); @@ -748,18 +748,18 @@ public class PostgresCSharpTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await Update.Full(PostgresDb.TableName, "test", + await Update.ById(PostgresDb.TableName, "test", new JsonDocument { Id = "x", Sub = new() { Foo = "blue", Bar = "red" } }); }) }), - TestList("FullFunc", new[] + TestList("ByFunc", new[] { TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - await Update.FullFunc(PostgresDb.TableName, doc => doc.Id, + await Update.ByFunc(PostgresDb.TableName, doc => doc.Id, new JsonDocument { Id = "one", Value = "le un", NumValue = 1 }); var after = await Find.ById(PostgresDb.TableName, "one"); Expect.isNotNull(after, "There should have been a document returned post-update"); @@ -776,18 +776,21 @@ public class PostgresCSharpTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await Update.FullFunc(PostgresDb.TableName, doc => doc.Id, + await Update.ByFunc(PostgresDb.TableName, doc => doc.Id, new JsonDocument { Id = "one", Value = "le un", NumValue = 1 }); }) - }), - TestList("PartialById", new[] + }) + }), + TestList("Patch", new[] + { + TestList("ById", new[] { TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - await Update.PartialById(PostgresDb.TableName, "one", new { NumValue = 44 }); + await Patch.ById(PostgresDb.TableName, "one", new { NumValue = 44 }); var after = await Find.ById(PostgresDb.TableName, "one"); Expect.isNotNull(after, "There should have been a document returned post-update"); Expect.equal(after.NumValue, 44, "The updated document is not correct"); @@ -800,17 +803,17 @@ public class PostgresCSharpTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await Update.PartialById(PostgresDb.TableName, "test", new { Foo = "green" }); + await Patch.ById(PostgresDb.TableName, "test", new { Foo = "green" }); }) }), - TestList("PartialByField", new[] + TestList("ByField", new[] { TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - await Update.PartialByField(PostgresDb.TableName, "Value", Op.EQ, "purple", new { NumValue = 77 }); + await Patch.ByField(PostgresDb.TableName, "Value", Op.EQ, "purple", new { NumValue = 77 }); var after = await Count.ByField(PostgresDb.TableName, "NumValue", Op.EQ, "77"); Expect.equal(after, 2, "There should have been 2 documents returned"); }), @@ -822,19 +825,17 @@ public class PostgresCSharpTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await Update.PartialByField(PostgresDb.TableName, "Value", Op.EQ, "burgundy", - new { Foo = "green" }); + await Patch.ByField(PostgresDb.TableName, "Value", Op.EQ, "burgundy", new { Foo = "green" }); }) }), - TestList("PartialByContains", new[] + TestList("ByContains", new[] { TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - await Update.PartialByContains(PostgresDb.TableName, new { Value = "purple" }, - new { NumValue = 77 }); + await Patch.ByContains(PostgresDb.TableName, new { Value = "purple" }, new { NumValue = 77 }); var after = await Count.ByContains(PostgresDb.TableName, new { NumValue = 77 }); Expect.equal(after, 2, "There should have been 2 documents returned"); }), @@ -846,19 +847,17 @@ public class PostgresCSharpTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await Update.PartialByContains(PostgresDb.TableName, new { Value = "burgundy" }, - new { Foo = "green" }); + await Patch.ByContains(PostgresDb.TableName, new { Value = "burgundy" }, new { Foo = "green" }); }) }), - TestList("PartialByJsonPath", new[] + TestList("ByJsonPath", new[] { TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); await LoadDocs(); - await Update.PartialByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 10)", - new { NumValue = 1000 }); + await Patch.ByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 10)", new { NumValue = 1000 }); var after = await Count.ByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 999)"); Expect.equal(after, 2, "There should have been 2 documents returned"); }), @@ -870,7 +869,7 @@ public class PostgresCSharpTests Expect.equal(before, 0, "There should have been no documents returned"); // This not raising an exception is the test - await Update.PartialByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)", new { Foo = "green" }); + await Patch.ByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)", new { Foo = "green" }); }) }) }), diff --git a/src/Tests/CommonTests.fs b/src/Tests/CommonTests.fs index a0ce0d7..b7fcc4a 100644 --- a/src/Tests/CommonTests.fs +++ b/src/Tests/CommonTests.fs @@ -95,6 +95,12 @@ let all = $"INSERT INTO {tbl} VALUES (@data) ON CONFLICT ((data ->> 'Id')) DO UPDATE SET data = EXCLUDED.data" "INSERT ON CONFLICT UPDATE statement not correct" } + test "update succeeds" { + Expect.equal + (Query.update tbl) + $"UPDATE {tbl} SET data = @data WHERE data ->> 'Id' = @id" + "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" @@ -134,14 +140,6 @@ let all = "SELECT by JSON comparison query not correct" } ] - testList "Update" [ - test "full succeeds" { - Expect.equal - (Query.Update.full tbl) - $"UPDATE {tbl} SET data = @data WHERE data ->> 'Id' = @id" - "UPDATE full statement not correct" - } - ] testList "Delete" [ test "byId succeeds" { Expect.equal diff --git a/src/Tests/PostgresExtensionTests.fs b/src/Tests/PostgresExtensionTests.fs index 220463a..4d215b2 100644 --- a/src/Tests/PostgresExtensionTests.fs +++ b/src/Tests/PostgresExtensionTests.fs @@ -486,14 +486,14 @@ let integrationTests = Expect.isNone doc "There should not have been a document returned" } ] - testList "updateFull" [ + testList "updateById" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn let testDoc = { emptyDoc with Id = "one"; Sub = Some { Foo = "blue"; Bar = "red" } } - do! conn.updateFull PostgresDb.TableName "one" testDoc + do! conn.updateById PostgresDb.TableName "one" testDoc let! after = conn.findById PostgresDb.TableName "one" Expect.isSome after "There should have been a document returned post-update" Expect.equal after.Value testDoc "The updated document is not correct" @@ -505,17 +505,17 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! conn.updateFull + do! conn.updateById PostgresDb.TableName "test" { emptyDoc with Id = "x"; Sub = Some { Foo = "blue"; Bar = "red" } } } ] - testList "updateFullFunc" [ + testList "updateByFunc" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - do! conn.updateFullFunc + do! conn.updateByFunc PostgresDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None } let! after = conn.findById PostgresDb.TableName "one" Expect.isSome after "There should have been a document returned post-update" @@ -531,17 +531,17 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! conn.updateFullFunc + do! conn.updateByFunc PostgresDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None } } ] - testList "updatePartialById" [ + testList "patchById" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - do! conn.updatePartialById PostgresDb.TableName "one" {| NumValue = 44 |} + do! conn.patchById PostgresDb.TableName "one" {| NumValue = 44 |} let! after = conn.findById PostgresDb.TableName "one" Expect.isSome after "There should have been a document returned post-update" Expect.equal after.Value.NumValue 44 "The updated document is not correct" @@ -553,16 +553,16 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! conn.updatePartialById PostgresDb.TableName "test" {| Foo = "green" |} + do! conn.patchById PostgresDb.TableName "test" {| Foo = "green" |} } ] - testList "updatePartialByField" [ + testList "patchByField" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - do! conn.updatePartialByField PostgresDb.TableName "Value" EQ "purple" {| NumValue = 77 |} + do! conn.patchByField PostgresDb.TableName "Value" EQ "purple" {| NumValue = 77 |} let! after = conn.countByField PostgresDb.TableName "NumValue" EQ "77" Expect.equal after 2 "There should have been 2 documents returned" } @@ -573,16 +573,16 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! conn.updatePartialByField PostgresDb.TableName "Value" EQ "burgundy" {| Foo = "green" |} + do! conn.patchByField PostgresDb.TableName "Value" EQ "burgundy" {| Foo = "green" |} } ] - testList "updatePartialByContains" [ + testList "patchByContains" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - do! conn.updatePartialByContains PostgresDb.TableName {| Value = "purple" |} {| NumValue = 77 |} + do! conn.patchByContains PostgresDb.TableName {| Value = "purple" |} {| NumValue = 77 |} let! after = conn.countByContains PostgresDb.TableName {| NumValue = 77 |} Expect.equal after 2 "There should have been 2 documents returned" } @@ -593,16 +593,16 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! conn.updatePartialByContains PostgresDb.TableName {| Value = "burgundy" |} {| Foo = "green" |} + do! conn.patchByContains PostgresDb.TableName {| Value = "burgundy" |} {| Foo = "green" |} } ] - testList "updatePartialByJsonPath" [ + testList "patchByJsonPath" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() use conn = mkConn db do! loadDocs conn - do! conn.updatePartialByJsonPath PostgresDb.TableName "$.NumValue ? (@ > 10)" {| NumValue = 1000 |} + do! conn.patchByJsonPath PostgresDb.TableName "$.NumValue ? (@ > 10)" {| NumValue = 1000 |} let! after = conn.countByJsonPath PostgresDb.TableName "$.NumValue ? (@ > 999)" Expect.equal after 2 "There should have been 2 documents returned" } @@ -613,7 +613,7 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! conn.updatePartialByJsonPath PostgresDb.TableName "$.NumValue ? (@ < 0)" {| Foo = "green" |} + do! conn.patchByJsonPath PostgresDb.TableName "$.NumValue ? (@ < 0)" {| Foo = "green" |} } ] testList "deleteById" [ diff --git a/src/Tests/PostgresTests.fs b/src/Tests/PostgresTests.fs index 494c896..66938f6 100644 --- a/src/Tests/PostgresTests.fs +++ b/src/Tests/PostgresTests.fs @@ -101,28 +101,28 @@ let unitTests = "SELECT by JSON Path match query not correct" } ] - testList "Update" [ - test "partialById succeeds" { + testList "Patch" [ + test "byId succeeds" { Expect.equal - (Query.Update.partialById PostgresDb.TableName) + (Query.Patch.byId PostgresDb.TableName) $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data ->> 'Id' = @id" "UPDATE partial by ID statement not correct" } - test "partialByField succeeds" { + test "byField succeeds" { Expect.equal - (Query.Update.partialByField PostgresDb.TableName "Snail" LT) + (Query.Patch.byField PostgresDb.TableName "Snail" LT) $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data ->> 'Snail' < @field" "UPDATE partial by ID statement not correct" } - test "partialByContains succeeds" { + test "byContains succeeds" { Expect.equal - (Query.Update.partialByContains PostgresDb.TableName) + (Query.Patch.byContains PostgresDb.TableName) $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data @> @criteria" "UPDATE partial by JSON containment statement not correct" } - test "partialByJsonPath succeeds" { + test "byJsonPath succeeds" { Expect.equal - (Query.Update.partialByJsonPath PostgresDb.TableName) + (Query.Patch.byJsonPath PostgresDb.TableName) $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data @? @path::jsonpath" "UPDATE partial by JSON Path statement not correct" } @@ -606,13 +606,13 @@ let integrationTests = ] ] testList "Update" [ - testList "full" [ + testList "byId" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() do! loadDocs () let testDoc = { emptyDoc with Id = "one"; Sub = Some { Foo = "blue"; Bar = "red" } } - do! Update.full PostgresDb.TableName "one" testDoc + do! Update.byId PostgresDb.TableName "one" testDoc let! after = Find.byId PostgresDb.TableName "one" Expect.isSome after "There should have been a document returned post-update" Expect.equal after.Value testDoc "The updated document is not correct" @@ -624,18 +624,18 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! Update.full + do! Update.byId PostgresDb.TableName "test" { emptyDoc with Id = "x"; Sub = Some { Foo = "blue"; Bar = "red" } } } ] - testList "fullFunc" [ + testList "byFunc" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() do! loadDocs () - do! Update.fullFunc PostgresDb.TableName (_.Id) + do! Update.byFunc PostgresDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None } let! after = Find.byId PostgresDb.TableName "one" Expect.isSome after "There should have been a document returned post-update" @@ -651,16 +651,18 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! Update.fullFunc + do! Update.byFunc PostgresDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None } } ] - testList "partialById" [ + ] + testList "Patch" [ + testList "byId" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() do! loadDocs () - do! Update.partialById PostgresDb.TableName "one" {| NumValue = 44 |} + do! Patch.byId PostgresDb.TableName "one" {| NumValue = 44 |} let! after = Find.byId PostgresDb.TableName "one" Expect.isSome after "There should have been a document returned post-update" Expect.equal after.Value.NumValue 44 "The updated document is not correct" @@ -672,15 +674,15 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! Update.partialById PostgresDb.TableName "test" {| Foo = "green" |} + do! Patch.byId PostgresDb.TableName "test" {| Foo = "green" |} } ] - testList "partialByField" [ + testList "byField" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() do! loadDocs () - do! Update.partialByField PostgresDb.TableName "Value" EQ "purple" {| NumValue = 77 |} + do! Patch.byField PostgresDb.TableName "Value" EQ "purple" {| NumValue = 77 |} let! after = Count.byField PostgresDb.TableName "NumValue" EQ "77" Expect.equal after 2 "There should have been 2 documents returned" } @@ -691,15 +693,15 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! Update.partialByField PostgresDb.TableName "Value" EQ "burgundy" {| Foo = "green" |} + do! Patch.byField PostgresDb.TableName "Value" EQ "burgundy" {| Foo = "green" |} } ] - testList "partialByContains" [ + testList "byContains" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() do! loadDocs () - do! Update.partialByContains PostgresDb.TableName {| Value = "purple" |} {| NumValue = 77 |} + do! Patch.byContains PostgresDb.TableName {| Value = "purple" |} {| NumValue = 77 |} let! after = Count.byContains PostgresDb.TableName {| NumValue = 77 |} Expect.equal after 2 "There should have been 2 documents returned" } @@ -710,15 +712,15 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! Update.partialByContains PostgresDb.TableName {| Value = "burgundy" |} {| Foo = "green" |} + do! Patch.byContains PostgresDb.TableName {| Value = "burgundy" |} {| Foo = "green" |} } ] - testList "partialByJsonPath" [ + testList "byJsonPath" [ testTask "succeeds when a document is updated" { use db = PostgresDb.BuildDb() do! loadDocs () - do! Update.partialByJsonPath PostgresDb.TableName "$.NumValue ? (@ > 10)" {| NumValue = 1000 |} + do! Patch.byJsonPath PostgresDb.TableName "$.NumValue ? (@ > 10)" {| NumValue = 1000 |} let! after = Count.byJsonPath PostgresDb.TableName "$.NumValue ? (@ > 999)" Expect.equal after 2 "There should have been 2 documents returned" } @@ -729,7 +731,7 @@ let integrationTests = Expect.equal before 0 "There should have been no documents returned" // This not raising an exception is the test - do! Update.partialByJsonPath PostgresDb.TableName "$.NumValue ? (@ < 0)" {| Foo = "green" |} + do! Patch.byJsonPath PostgresDb.TableName "$.NumValue ? (@ < 0)" {| Foo = "green" |} } ] ]