V3 rc2 #2
|
@ -53,6 +53,21 @@ module Query =
|
||||||
sprintf
|
sprintf
|
||||||
"UPDATE %s SET data = json_patch(data, json(@data)) WHERE %s"
|
"UPDATE %s SET data = json_patch(data, json(@data)) WHERE %s"
|
||||||
tableName (Query.whereByField fieldName op "@field")
|
tableName (Query.whereByField fieldName op "@field")
|
||||||
|
|
||||||
|
/// Queries to remove a field from a document
|
||||||
|
module RemoveField =
|
||||||
|
|
||||||
|
/// Query to remove a field from a document by the document's ID
|
||||||
|
[<CompiledName "ById">]
|
||||||
|
let byId tableName =
|
||||||
|
$"""UPDATE %s{tableName} SET data = json_remove(data, @name) WHERE {Query.whereById "@id"}"""
|
||||||
|
|
||||||
|
/// Query to remove a field from a document via a comparison on a JSON field within the document
|
||||||
|
[<CompiledName "ByField">]
|
||||||
|
let byField tableName fieldName op =
|
||||||
|
sprintf
|
||||||
|
"UPDATE %s SET data = json_remove(data, @name) WHERE %s"
|
||||||
|
tableName (Query.whereByField fieldName op "@field")
|
||||||
|
|
||||||
|
|
||||||
/// Parameter handling helpers
|
/// Parameter handling helpers
|
||||||
|
@ -74,6 +89,11 @@ module Parameters =
|
||||||
let fieldParam (value: obj) =
|
let fieldParam (value: obj) =
|
||||||
SqliteParameter("@field", value)
|
SqliteParameter("@field", value)
|
||||||
|
|
||||||
|
/// Create a JSON field name parameter (name "@name")
|
||||||
|
[<CompiledName "FieldName">]
|
||||||
|
let fieldNameParam name =
|
||||||
|
SqliteParameter("@name", $"$.%s{name}")
|
||||||
|
|
||||||
/// An empty parameter sequence
|
/// An empty parameter sequence
|
||||||
[<CompiledName "None">]
|
[<CompiledName "None">]
|
||||||
let noParams =
|
let noParams =
|
||||||
|
@ -315,6 +335,23 @@ module WithConn =
|
||||||
Custom.nonQuery
|
Custom.nonQuery
|
||||||
(Query.Patch.byField tableName fieldName op) [ fieldParam value; jsonParam "@data" patch ] conn
|
(Query.Patch.byField tableName fieldName op) [ fieldParam value; jsonParam "@data" patch ] conn
|
||||||
|
|
||||||
|
/// Commands to remove fields from documents
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module RemoveField =
|
||||||
|
|
||||||
|
/// Remove a field from a document by the document's ID
|
||||||
|
[<CompiledName "ById">]
|
||||||
|
let byId tableName (docId: 'TKey) fieldName conn =
|
||||||
|
Custom.nonQuery (Query.RemoveField.byId tableName) [ idParam docId; fieldNameParam fieldName ] conn
|
||||||
|
|
||||||
|
/// Remove a field from a document via a comparison on a JSON field in the document
|
||||||
|
[<CompiledName "ByField">]
|
||||||
|
let byField tableName whereFieldName op (value: obj) removeFieldName conn =
|
||||||
|
Custom.nonQuery
|
||||||
|
(Query.RemoveField.byField tableName whereFieldName op)
|
||||||
|
[ fieldParam value; fieldNameParam removeFieldName ]
|
||||||
|
conn
|
||||||
|
|
||||||
/// Commands to delete documents
|
/// Commands to delete documents
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module Delete =
|
module Delete =
|
||||||
|
@ -522,6 +559,22 @@ module Patch =
|
||||||
use conn = Configuration.dbConn ()
|
use conn = Configuration.dbConn ()
|
||||||
WithConn.Patch.byField tableName fieldName op value patch conn
|
WithConn.Patch.byField tableName fieldName op value patch conn
|
||||||
|
|
||||||
|
/// Commands to remove fields from documents
|
||||||
|
[<RequireQualifiedAccess>]
|
||||||
|
module RemoveField =
|
||||||
|
|
||||||
|
/// Remove a field from a document by the document's ID
|
||||||
|
[<CompiledName "ById">]
|
||||||
|
let byId tableName (docId: 'TKey) fieldName =
|
||||||
|
use conn = Configuration.dbConn ()
|
||||||
|
WithConn.RemoveField.byId tableName docId fieldName conn
|
||||||
|
|
||||||
|
/// Remove a field from a document via a comparison on a JSON field in the document
|
||||||
|
[<CompiledName "ByField">]
|
||||||
|
let byField tableName whereFieldName op (value: obj) removeFieldName =
|
||||||
|
use conn = Configuration.dbConn ()
|
||||||
|
WithConn.RemoveField.byField tableName whereFieldName op value removeFieldName conn
|
||||||
|
|
||||||
/// Commands to delete documents
|
/// Commands to delete documents
|
||||||
[<RequireQualifiedAccess>]
|
[<RequireQualifiedAccess>]
|
||||||
module Delete =
|
module Delete =
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using Expecto.CSharp;
|
using System.Text.Json;
|
||||||
|
using Expecto.CSharp;
|
||||||
using Expecto;
|
using Expecto;
|
||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Data.Sqlite;
|
||||||
using Microsoft.FSharp.Core;
|
using Microsoft.FSharp.Core;
|
||||||
|
@ -40,6 +41,21 @@ public static class SqliteCSharpTests
|
||||||
"UPDATE partial by JSON comparison query not correct");
|
"UPDATE partial by JSON comparison query not correct");
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
TestList("RemoveField", new[]
|
||||||
|
{
|
||||||
|
TestCase("ById succeeds", () =>
|
||||||
|
{
|
||||||
|
Expect.equal(Sqlite.Query.RemoveField.ById("tbl"),
|
||||||
|
"UPDATE tbl SET data = json_remove(data, @name) WHERE data ->> 'Id' = @id",
|
||||||
|
"Remove field by ID query not correct");
|
||||||
|
}),
|
||||||
|
TestCase("ByField succeeds", () =>
|
||||||
|
{
|
||||||
|
Expect.equal(Sqlite.Query.RemoveField.ByField("tbl", "Fly", Op.LT),
|
||||||
|
"UPDATE tbl SET data = json_remove(data, @name) WHERE data ->> 'Fly' < @field",
|
||||||
|
"Remove field by field query not correct");
|
||||||
|
})
|
||||||
|
})
|
||||||
}),
|
}),
|
||||||
TestList("Parameters", new[]
|
TestList("Parameters", new[]
|
||||||
{
|
{
|
||||||
|
@ -540,6 +556,37 @@ public static class SqliteCSharpTests
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
TestList("RemoveField", new[]
|
||||||
|
{
|
||||||
|
TestList("ById", new[]
|
||||||
|
{
|
||||||
|
TestCase("succeeds when a field is removed", async () =>
|
||||||
|
{
|
||||||
|
await using var db = await SqliteDb.BuildDb();
|
||||||
|
await LoadDocs();
|
||||||
|
|
||||||
|
await RemoveField.ById(SqliteDb.TableName, "two", "Sub");
|
||||||
|
var updated = await Find.ById<string, JsonDocument>(SqliteDb.TableName, "two");
|
||||||
|
Expect.isNotNull(updated, "The updated document should have been retrieved");
|
||||||
|
Expect.isNull(updated.Sub, "The sub-document should have been removed");
|
||||||
|
}),
|
||||||
|
TestCase("succeeds when a field is not removed", async () =>
|
||||||
|
{
|
||||||
|
await using var db = await SqliteDb.BuildDb();
|
||||||
|
await LoadDocs();
|
||||||
|
|
||||||
|
// This not raising an exception is the test
|
||||||
|
await RemoveField.ById(SqliteDb.TableName, "two", "AFieldThatIsNotThere");
|
||||||
|
}),
|
||||||
|
TestCase("succeeds when no document is matched", async () =>
|
||||||
|
{
|
||||||
|
await using var db = await SqliteDb.BuildDb();
|
||||||
|
|
||||||
|
// This not raising an exception is the test
|
||||||
|
await RemoveField.ById(SqliteDb.TableName, "two", "Value");
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}),
|
||||||
TestList("Delete", new[]
|
TestList("Delete", new[]
|
||||||
{
|
{
|
||||||
TestList("ById", new[]
|
TestList("ById", new[]
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
module SqliteTests
|
module SqliteTests
|
||||||
|
|
||||||
|
open System.Text.Json
|
||||||
open BitBadger.Documents
|
open BitBadger.Documents
|
||||||
open BitBadger.Documents.Sqlite
|
open BitBadger.Documents.Sqlite
|
||||||
open BitBadger.Documents.Tests
|
open BitBadger.Documents.Tests
|
||||||
|
@ -31,6 +32,20 @@ let unitTests =
|
||||||
"UPDATE partial by JSON comparison query not correct"
|
"UPDATE partial by JSON comparison query not correct"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
testList "RemoveField" [
|
||||||
|
test "byId succeeds" {
|
||||||
|
Expect.equal
|
||||||
|
(Query.RemoveField.byId "tbl")
|
||||||
|
"UPDATE tbl SET data = json_remove(data, @name) WHERE data ->> 'Id' = @id"
|
||||||
|
"Remove field by ID query not correct"
|
||||||
|
}
|
||||||
|
test "byField succeeds" {
|
||||||
|
Expect.equal
|
||||||
|
(Query.RemoveField.byField "tbl" "Fly" GT)
|
||||||
|
"UPDATE tbl SET data = json_remove(data, @name) WHERE data ->> 'Fly' > @field"
|
||||||
|
"Remove field by field query not correct"
|
||||||
|
}
|
||||||
|
]
|
||||||
]
|
]
|
||||||
testList "Parameters" [
|
testList "Parameters" [
|
||||||
test "idParam succeeds" {
|
test "idParam succeeds" {
|
||||||
|
@ -489,6 +504,35 @@ let integrationTests =
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
|
testList "RemoveField" [
|
||||||
|
testList "byId" [
|
||||||
|
testTask "succeeds when a field is removed" {
|
||||||
|
use! db = SqliteDb.BuildDb()
|
||||||
|
do! loadDocs ()
|
||||||
|
|
||||||
|
do! RemoveField.byId SqliteDb.TableName "two" "Sub"
|
||||||
|
try
|
||||||
|
let! _ = Find.byId<string, JsonDocument> SqliteDb.TableName "two"
|
||||||
|
Expect.isTrue false "The updated document should have failed to parse"
|
||||||
|
with
|
||||||
|
| :? JsonException -> ()
|
||||||
|
| exn as ex -> Expect.isTrue false $"Threw {ex.GetType().Name} ({ex.Message})"
|
||||||
|
}
|
||||||
|
testTask "succeeds when a field is not removed" {
|
||||||
|
use! db = SqliteDb.BuildDb()
|
||||||
|
do! loadDocs ()
|
||||||
|
|
||||||
|
// This not raising an exception is the test
|
||||||
|
do! RemoveField.byId SqliteDb.TableName "two" "AFieldThatIsNotThere"
|
||||||
|
}
|
||||||
|
testTask "succeeds when no document is matched" {
|
||||||
|
use! db = SqliteDb.BuildDb()
|
||||||
|
|
||||||
|
// This not raising an exception is the test
|
||||||
|
do! RemoveField.byId SqliteDb.TableName "two" "Value"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
testList "Delete" [
|
testList "Delete" [
|
||||||
testList "byId" [
|
testList "byId" [
|
||||||
testTask "succeeds when a document is deleted" {
|
testTask "succeeds when a document is deleted" {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user