Add byFields to SQLite implementation

- Add fieldNameParams/FieldNames to Postgres
(syncs names between both implementations)
This commit is contained in:
Daniel J. Summers 2024-08-08 19:45:25 -04:00
parent 202fca272e
commit d8f64417e5
8 changed files with 461 additions and 258 deletions

View File

@ -1,5 +1,6 @@
namespace BitBadger.Documents.Postgres namespace BitBadger.Documents.Postgres
open BitBadger.Documents
open Npgsql open Npgsql
open Npgsql.FSharp open Npgsql.FSharp
@ -56,7 +57,7 @@ module Extensions =
/// Count matching documents using a JSON field comparison query (->> =) /// Count matching documents using a JSON field comparison query (->> =)
[<System.Obsolete "Use countByFields instead; will be removed in v4">] [<System.Obsolete "Use countByFields instead; will be removed in v4">]
member conn.countByField tableName field = member conn.countByField tableName field =
WithProps.Count.byField tableName field (Sql.existingConnection conn) conn.countByFields tableName Any [ field ]
/// Count matching documents using a JSON containment query (@>) /// Count matching documents using a JSON containment query (@>)
member conn.countByContains tableName criteria = member conn.countByContains tableName criteria =
@ -77,7 +78,7 @@ module Extensions =
/// Determine if documents exist using a JSON field comparison query (->> =) /// Determine if documents exist using a JSON field comparison query (->> =)
[<System.Obsolete "Use existsByFields instead; will be removed in v4">] [<System.Obsolete "Use existsByFields instead; will be removed in v4">]
member conn.existsByField tableName field = member conn.existsByField tableName field =
WithProps.Exists.byField tableName field (Sql.existingConnection conn) conn.existsByFields tableName Any [ field ]
/// Determine if documents exist using a JSON containment query (@>) /// Determine if documents exist using a JSON containment query (@>)
member conn.existsByContains tableName criteria = member conn.existsByContains tableName criteria =
@ -102,7 +103,7 @@ module Extensions =
/// Retrieve documents matching a JSON field comparison query (->> =) /// Retrieve documents matching a JSON field comparison query (->> =)
[<System.Obsolete "Use findByFields instead; will be removed in v4">] [<System.Obsolete "Use findByFields instead; will be removed in v4">]
member conn.findByField<'TDoc> tableName field = member conn.findByField<'TDoc> tableName field =
WithProps.Find.byField<'TDoc> tableName field (Sql.existingConnection conn) conn.findByFields<'TDoc> tableName Any [ field ]
/// Retrieve documents matching a JSON containment query (@>) /// Retrieve documents matching a JSON containment query (@>)
member conn.findByContains<'TDoc> tableName (criteria: obj) = member conn.findByContains<'TDoc> tableName (criteria: obj) =
@ -119,7 +120,7 @@ module Extensions =
/// Retrieve the first document matching a JSON field comparison query (->> =); returns None if not found /// Retrieve the first document matching a JSON field comparison query (->> =); returns None if not found
[<System.Obsolete "Use findFirstByFields instead; will be removed in v4">] [<System.Obsolete "Use findFirstByFields instead; will be removed in v4">]
member conn.findFirstByField<'TDoc> tableName field = member conn.findFirstByField<'TDoc> tableName field =
WithProps.Find.firstByField<'TDoc> tableName field (Sql.existingConnection conn) conn.findFirstByFields<'TDoc> tableName Any [ field ]
/// Retrieve the first document matching a JSON containment query (@>); returns None if not found /// Retrieve the first document matching a JSON containment query (@>); returns None if not found
member conn.findFirstByContains<'TDoc> tableName (criteria: obj) = member conn.findFirstByContains<'TDoc> tableName (criteria: obj) =
@ -148,7 +149,7 @@ module Extensions =
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =) /// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
[<System.Obsolete "Use patchByFields instead; will be removed in v4">] [<System.Obsolete "Use patchByFields instead; will be removed in v4">]
member conn.patchByField tableName field (patch: 'TPatch) = member conn.patchByField tableName field (patch: 'TPatch) =
WithProps.Patch.byField tableName field patch (Sql.existingConnection conn) conn.patchByFields tableName Any [ field ] patch
/// Patch documents using a JSON containment query in the WHERE clause (@>) /// Patch documents using a JSON containment query in the WHERE clause (@>)
member conn.patchByContains tableName (criteria: 'TCriteria) (patch: 'TPatch) = member conn.patchByContains tableName (criteria: 'TCriteria) (patch: 'TPatch) =
@ -169,7 +170,7 @@ module Extensions =
/// Remove fields from documents via a comparison on a JSON field in the document /// Remove fields from documents via a comparison on a JSON field in the document
[<System.Obsolete "Use removeFieldsByFields instead; will be removed in v4">] [<System.Obsolete "Use removeFieldsByFields instead; will be removed in v4">]
member conn.removeFieldsByField tableName field fieldNames = member conn.removeFieldsByField tableName field fieldNames =
WithProps.RemoveFields.byField tableName field fieldNames (Sql.existingConnection conn) conn.removeFieldsByFields tableName Any [ field ] fieldNames
/// Remove fields from documents via a JSON containment query (@>) /// Remove fields from documents via a JSON containment query (@>)
member conn.removeFieldsByContains tableName (criteria: 'TContains) fieldNames = member conn.removeFieldsByContains tableName (criteria: 'TContains) fieldNames =
@ -189,7 +190,7 @@ module Extensions =
/// Delete documents by matching a JSON field comparison query (->> =) /// Delete documents by matching a JSON field comparison query (->> =)
[<System.Obsolete "Use deleteByFields instead; will be removed in v4">] [<System.Obsolete "Use deleteByFields instead; will be removed in v4">]
member conn.deleteByField tableName field = member conn.deleteByField tableName field =
WithProps.Delete.byField tableName field (Sql.existingConnection conn) conn.deleteByFields tableName Any [ field ]
/// Delete documents by matching a JSON containment query (@>) /// Delete documents by matching a JSON containment query (@>)
member conn.deleteByContains tableName (criteria: 'TContains) = member conn.deleteByContains tableName (criteria: 'TContains) =
@ -266,7 +267,7 @@ type NpgsqlConnectionCSharpExtensions =
[<Extension>] [<Extension>]
[<System.Obsolete "Use CountByFields instead; will be removed in v4">] [<System.Obsolete "Use CountByFields instead; will be removed in v4">]
static member inline CountByField(conn, tableName, field) = static member inline CountByField(conn, tableName, field) =
WithProps.Count.byField tableName field (Sql.existingConnection conn) conn.CountByFields(tableName, Any, [ field ])
/// Count matching documents using a JSON containment query (@>) /// Count matching documents using a JSON containment query (@>)
[<Extension>] [<Extension>]
@ -292,7 +293,7 @@ type NpgsqlConnectionCSharpExtensions =
[<Extension>] [<Extension>]
[<System.Obsolete "Use ExistsByFields instead; will be removed in v4">] [<System.Obsolete "Use ExistsByFields instead; will be removed in v4">]
static member inline ExistsByField(conn, tableName, field) = static member inline ExistsByField(conn, tableName, field) =
WithProps.Exists.byField tableName field (Sql.existingConnection conn) conn.ExistsByFields(tableName, Any, [ field ])
/// Determine if documents exist using a JSON containment query (@>) /// Determine if documents exist using a JSON containment query (@>)
[<Extension>] [<Extension>]
@ -323,7 +324,7 @@ type NpgsqlConnectionCSharpExtensions =
[<Extension>] [<Extension>]
[<System.Obsolete "Use FindByFields instead; will be removed in v4">] [<System.Obsolete "Use FindByFields instead; will be removed in v4">]
static member inline FindByField<'TDoc>(conn, tableName, field) = static member inline FindByField<'TDoc>(conn, tableName, field) =
WithProps.Find.ByField<'TDoc>(tableName, field, Sql.existingConnection conn) conn.FindByFields<'TDoc>(tableName, Any, [ field ])
/// Retrieve documents matching a JSON containment query (@>) /// Retrieve documents matching a JSON containment query (@>)
[<Extension>] [<Extension>]
@ -344,7 +345,7 @@ type NpgsqlConnectionCSharpExtensions =
[<Extension>] [<Extension>]
[<System.Obsolete "Use FindFirstByFields instead; will be removed in v4">] [<System.Obsolete "Use FindFirstByFields instead; will be removed in v4">]
static member inline FindFirstByField<'TDoc when 'TDoc: null>(conn, tableName, field) = static member inline FindFirstByField<'TDoc when 'TDoc: null>(conn, tableName, field) =
WithProps.Find.FirstByField<'TDoc>(tableName, field, Sql.existingConnection conn) conn.FindFirstByFields<'TDoc>(tableName, Any, [ field ])
/// Retrieve the first document matching a JSON containment query (@>); returns None if not found /// Retrieve the first document matching a JSON containment query (@>); returns None if not found
[<Extension>] [<Extension>]
@ -380,7 +381,7 @@ type NpgsqlConnectionCSharpExtensions =
[<Extension>] [<Extension>]
[<System.Obsolete "Use PatchByFields instead; will be removed in v4">] [<System.Obsolete "Use PatchByFields instead; will be removed in v4">]
static member inline PatchByField(conn, tableName, field, patch: 'TPatch) = static member inline PatchByField(conn, tableName, field, patch: 'TPatch) =
WithProps.Patch.byField tableName field patch (Sql.existingConnection conn) conn.PatchByFields(tableName, Any, [ field ], patch)
/// Patch documents using a JSON containment query in the WHERE clause (@>) /// Patch documents using a JSON containment query in the WHERE clause (@>)
[<Extension>] [<Extension>]
@ -406,7 +407,7 @@ type NpgsqlConnectionCSharpExtensions =
[<Extension>] [<Extension>]
[<System.Obsolete "Use RemoveFieldsByFields instead; will be removed in v4">] [<System.Obsolete "Use RemoveFieldsByFields instead; will be removed in v4">]
static member inline RemoveFieldsByField(conn, tableName, field, fieldNames) = static member inline RemoveFieldsByField(conn, tableName, field, fieldNames) =
WithProps.RemoveFields.byField tableName field fieldNames (Sql.existingConnection conn) conn.RemoveFieldsByFields(tableName, Any, [ field ], fieldNames)
/// Remove fields from documents via a JSON containment query (@>) /// Remove fields from documents via a JSON containment query (@>)
[<Extension>] [<Extension>]
@ -432,7 +433,7 @@ type NpgsqlConnectionCSharpExtensions =
[<Extension>] [<Extension>]
[<System.Obsolete "Use DeleteByFields instead; will be removed in v4">] [<System.Obsolete "Use DeleteByFields instead; will be removed in v4">]
static member inline DeleteByField(conn, tableName, field) = static member inline DeleteByField(conn, tableName, field) =
WithProps.Delete.byField tableName field (Sql.existingConnection conn) conn.DeleteByFields(tableName, Any, [ field ])
/// Delete documents by matching a JSON containment query (@>) /// Delete documents by matching a JSON containment query (@>)
[<Extension>] [<Extension>]

View File

@ -90,12 +90,18 @@ module Parameters =
[<System.Obsolete "Use addFieldParams (F#) / AddFields (C#) instead; will be removed in v4">] [<System.Obsolete "Use addFieldParams (F#) / AddFields (C#) instead; will be removed in v4">]
let addFieldParam name field parameters = let addFieldParam name field parameters =
addFieldParams [ { field with ParameterName = Some name } ] parameters addFieldParams [ { field with ParameterName = Some name } ] parameters
/// Append JSON field name parameters for the given field names to the given parameters /// Append JSON field name parameters for the given field names to the given parameters
[<CompiledName "FieldName">] [<CompiledName "FieldNames">]
let fieldNameParam (fieldNames: string seq) = let fieldNameParams (fieldNames: string seq) =
if Seq.length fieldNames = 1 then "@name", Sql.string (Seq.head fieldNames) if Seq.length fieldNames = 1 then "@name", Sql.string (Seq.head fieldNames)
else "@name", Sql.stringArray (Array.ofSeq fieldNames) else "@name", Sql.stringArray (Array.ofSeq fieldNames)
/// Append JSON field name parameters for the given field names to the given parameters
[<CompiledName "FieldName">]
[<System.Obsolete "Use fieldNameParams (F#) / FieldNames (C#) instead; will be removed in v4">]
let fieldNameParam fieldNames =
fieldNameParams fieldNames
/// An empty parameter sequence /// An empty parameter sequence
[<CompiledName "None">] [<CompiledName "None">]
@ -707,7 +713,7 @@ module WithProps =
/// Remove fields from a document by the document's ID /// Remove fields from a document by the document's ID
[<CompiledName "FSharpById">] [<CompiledName "FSharpById">]
let byId tableName (docId: 'TKey) fieldNames sqlProps = let byId tableName (docId: 'TKey) fieldNames sqlProps =
Custom.nonQuery (Query.RemoveFields.byId tableName) [ idParam docId; fieldNameParam fieldNames ] sqlProps Custom.nonQuery (Query.RemoveFields.byId tableName) [ idParam docId; fieldNameParams fieldNames ] sqlProps
/// Remove fields from a document by the document's ID /// Remove fields from a document by the document's ID
let ById(tableName, docId: 'TKey, fieldNames, sqlProps) = let ById(tableName, docId: 'TKey, fieldNames, sqlProps) =
@ -718,7 +724,7 @@ module WithProps =
let byFields tableName howMatched fields fieldNames sqlProps = let byFields tableName howMatched fields fieldNames sqlProps =
Custom.nonQuery Custom.nonQuery
(Query.RemoveFields.byFields tableName howMatched fields) (Query.RemoveFields.byFields tableName howMatched fields)
(addFieldParams fields [ fieldNameParam fieldNames ]) (addFieldParams fields [ fieldNameParams fieldNames ])
sqlProps sqlProps
/// Remove fields from documents via a comparison on a JSON field in the document /// Remove fields from documents via a comparison on a JSON field in the document
@ -732,7 +738,7 @@ module WithProps =
let byContains tableName (criteria: 'TContains) fieldNames sqlProps = let byContains tableName (criteria: 'TContains) fieldNames sqlProps =
Custom.nonQuery Custom.nonQuery
(Query.RemoveFields.byContains tableName) (Query.RemoveFields.byContains tableName)
[ jsonParam "@criteria" criteria; fieldNameParam fieldNames ] [ jsonParam "@criteria" criteria; fieldNameParams fieldNames ]
sqlProps sqlProps
/// Remove fields from documents via a JSON containment query (@>) /// Remove fields from documents via a JSON containment query (@>)
@ -744,7 +750,7 @@ module WithProps =
let byJsonPath tableName jsonPath fieldNames sqlProps = let byJsonPath tableName jsonPath fieldNames sqlProps =
Custom.nonQuery Custom.nonQuery
(Query.RemoveFields.byJsonPath tableName) (Query.RemoveFields.byJsonPath tableName)
[ "@path", Sql.string jsonPath; fieldNameParam fieldNames ] [ "@path", Sql.string jsonPath; fieldNameParams fieldNames ]
sqlProps sqlProps
/// Remove fields from documents via a JSON Path match query (@?) /// Remove fields from documents via a JSON Path match query (@?)

View File

@ -1,5 +1,6 @@
namespace BitBadger.Documents.Sqlite namespace BitBadger.Documents.Sqlite
open BitBadger.Documents
open Microsoft.Data.Sqlite open Microsoft.Data.Sqlite
/// F# extensions for the SqliteConnection type /// F# extensions for the SqliteConnection type
@ -44,17 +45,27 @@ module Extensions =
member conn.countAll tableName = member conn.countAll tableName =
WithConn.Count.all tableName conn WithConn.Count.all tableName conn
/// Count matching documents using a comparison on JSON fields
member conn.countByFields tableName howMatched fields =
WithConn.Count.byFields tableName howMatched fields conn
/// Count matching documents using a comparison on a JSON field /// Count matching documents using a comparison on a JSON field
[<System.Obsolete "Use countByFields instead; will be removed in v4">]
member conn.countByField tableName field = member conn.countByField tableName field =
WithConn.Count.byField tableName field conn conn.countByFields tableName Any [ field ]
/// Determine if a document exists for the given ID /// Determine if a document exists for the given ID
member conn.existsById tableName (docId: 'TKey) = member conn.existsById tableName (docId: 'TKey) =
WithConn.Exists.byId tableName docId conn WithConn.Exists.byId tableName docId conn
/// Determine if a document exists using a comparison on JSON fields
member conn.existsByFields tableName howMatched fields =
WithConn.Exists.byFields tableName howMatched fields conn
/// Determine if a document exists using a comparison on a JSON field /// Determine if a document exists using a comparison on a JSON field
[<System.Obsolete "Use existsByFields instead; will be removed in v4">]
member conn.existsByField tableName field = member conn.existsByField tableName field =
WithConn.Exists.byField tableName field conn conn.existsByFields tableName Any [ field ]
/// Retrieve all documents in the given table /// Retrieve all documents in the given table
member conn.findAll<'TDoc> tableName = member conn.findAll<'TDoc> tableName =
@ -63,14 +74,24 @@ module Extensions =
/// Retrieve a document by its ID /// Retrieve a document by its ID
member conn.findById<'TKey, 'TDoc> tableName (docId: 'TKey) = member conn.findById<'TKey, 'TDoc> tableName (docId: 'TKey) =
WithConn.Find.byId<'TKey, 'TDoc> tableName docId conn WithConn.Find.byId<'TKey, 'TDoc> tableName docId conn
/// Retrieve documents via a comparison on JSON fields
member conn.findByFields<'TDoc> tableName howMatched fields =
WithConn.Find.byFields<'TDoc> tableName howMatched fields conn
/// Retrieve documents via a comparison on a JSON field /// Retrieve documents via a comparison on a JSON field
[<System.Obsolete "Use findByFields instead; will be removed in v4">]
member conn.findByField<'TDoc> tableName field = member conn.findByField<'TDoc> tableName field =
WithConn.Find.byField<'TDoc> tableName field conn conn.findByFields<'TDoc> tableName Any [ field ]
/// Retrieve documents via a comparison on JSON fields, returning only the first result
member conn.findFirstByFields<'TDoc> tableName howMatched fields =
WithConn.Find.firstByFields<'TDoc> tableName howMatched fields conn
/// Retrieve documents via a comparison on a JSON field, returning only the first result /// Retrieve documents via a comparison on a JSON field, returning only the first result
[<System.Obsolete "Use findFirstByFields instead; will be removed in v4">]
member conn.findFirstByField<'TDoc> tableName field = member conn.findFirstByField<'TDoc> tableName field =
WithConn.Find.firstByField<'TDoc> tableName field conn conn.findFirstByFields<'TDoc> tableName Any [ field ]
/// Update an entire document by its ID /// Update an entire document by its ID
member conn.updateById tableName (docId: 'TKey) (document: 'TDoc) = member conn.updateById tableName (docId: 'TKey) (document: 'TDoc) =
@ -84,25 +105,40 @@ module Extensions =
member conn.patchById tableName (docId: 'TKey) (patch: 'TPatch) = member conn.patchById tableName (docId: 'TKey) (patch: 'TPatch) =
WithConn.Patch.byId tableName docId patch conn WithConn.Patch.byId tableName docId patch conn
/// Patch documents using a comparison on JSON fields
member conn.patchByFields tableName howMatched fields (patch: 'TPatch) =
WithConn.Patch.byFields tableName howMatched fields patch conn
/// Patch documents using a comparison on a JSON field /// Patch documents using a comparison on a JSON field
[<System.Obsolete "Use patchByFields instead; will be removed in v4">]
member conn.patchByField tableName field (patch: 'TPatch) = member conn.patchByField tableName field (patch: 'TPatch) =
WithConn.Patch.byField tableName field patch conn conn.patchByFields tableName Any [ field ] patch
/// Remove fields from a document by the document's ID /// Remove fields from a document by the document's ID
member conn.removeFieldsById tableName (docId: 'TKey) fieldNames = member conn.removeFieldsById tableName (docId: 'TKey) fieldNames =
WithConn.RemoveFields.byId tableName docId fieldNames conn WithConn.RemoveFields.byId tableName docId fieldNames conn
/// Remove a field from a document via a comparison on JSON fields in the document
member conn.removeFieldsByFields tableName howMatched fields fieldNames =
WithConn.RemoveFields.byFields tableName howMatched fields fieldNames conn
/// Remove a field from a document via a comparison on a JSON field in the document /// Remove a field from a document via a comparison on a JSON field in the document
[<System.Obsolete "Use removeFieldsByFields instead; will be removed in v4">]
member conn.removeFieldsByField tableName field fieldNames = member conn.removeFieldsByField tableName field fieldNames =
WithConn.RemoveFields.byField tableName field fieldNames conn conn.removeFieldsByFields tableName Any [ field ] fieldNames
/// Delete a document by its ID /// Delete a document by its ID
member conn.deleteById tableName (docId: 'TKey) = member conn.deleteById tableName (docId: 'TKey) =
WithConn.Delete.byId tableName docId conn WithConn.Delete.byId tableName docId conn
/// Delete documents by matching a comparison on JSON fields
member conn.deleteByFields tableName howMatched fields =
WithConn.Delete.byFields tableName howMatched fields conn
/// Delete documents by matching a comparison on a JSON field /// Delete documents by matching a comparison on a JSON field
[<System.Obsolete "Use deleteByFields instead; will be removed in v4">]
member conn.deleteByField tableName field = member conn.deleteByField tableName field =
WithConn.Delete.byField tableName field conn conn.deleteByFields tableName Any [ field ]
open System.Runtime.CompilerServices open System.Runtime.CompilerServices
@ -157,20 +193,32 @@ type SqliteConnectionCSharpExtensions =
static member inline CountAll(conn, tableName) = static member inline CountAll(conn, tableName) =
WithConn.Count.all tableName conn WithConn.Count.all tableName conn
/// Count matching documents using a comparison on JSON fields
[<Extension>]
static member inline CountByFields(conn, tableName, howMatched, fields) =
WithConn.Count.byFields tableName howMatched fields conn
/// Count matching documents using a comparison on a JSON field /// Count matching documents using a comparison on a JSON field
[<Extension>] [<Extension>]
[<System.Obsolete "Use CountByFields instead; will be removed in v4">]
static member inline CountByField(conn, tableName, field) = static member inline CountByField(conn, tableName, field) =
WithConn.Count.byField tableName field conn conn.CountByFields(tableName, Any, [ field ])
/// Determine if a document exists for the given ID /// Determine if a document exists for the given ID
[<Extension>] [<Extension>]
static member inline ExistsById<'TKey>(conn, tableName, docId: 'TKey) = static member inline ExistsById<'TKey>(conn, tableName, docId: 'TKey) =
WithConn.Exists.byId tableName docId conn WithConn.Exists.byId tableName docId conn
/// Determine if a document exists using a comparison on JSON fields
[<Extension>]
static member inline ExistsByFields(conn, tableName, howMatched, fields) =
WithConn.Exists.byFields tableName howMatched fields conn
/// Determine if a document exists using a comparison on a JSON field /// Determine if a document exists using a comparison on a JSON field
[<Extension>] [<Extension>]
[<System.Obsolete "Use ExistsByFields instead; will be removed in v4">]
static member inline ExistsByField(conn, tableName, field) = static member inline ExistsByField(conn, tableName, field) =
WithConn.Exists.byField tableName field conn conn.ExistsByFields(tableName, Any, [ field ])
/// Retrieve all documents in the given table /// Retrieve all documents in the given table
[<Extension>] [<Extension>]
@ -182,15 +230,27 @@ type SqliteConnectionCSharpExtensions =
static member inline FindById<'TKey, 'TDoc when 'TDoc: null>(conn, tableName, docId: 'TKey) = static member inline FindById<'TKey, 'TDoc when 'TDoc: null>(conn, tableName, docId: 'TKey) =
WithConn.Find.ById<'TKey, 'TDoc>(tableName, docId, conn) WithConn.Find.ById<'TKey, 'TDoc>(tableName, docId, conn)
/// Retrieve documents via a comparison on JSON fields
[<Extension>]
static member inline FindByFields<'TDoc>(conn, tableName, howMatched, fields) =
WithConn.Find.ByFields<'TDoc>(tableName, howMatched, fields, conn)
/// Retrieve documents via a comparison on a JSON field /// Retrieve documents via a comparison on a JSON field
[<Extension>] [<Extension>]
[<System.Obsolete "Use FindByFields instead; will be removed in v4">]
static member inline FindByField<'TDoc>(conn, tableName, field) = static member inline FindByField<'TDoc>(conn, tableName, field) =
WithConn.Find.ByField<'TDoc>(tableName, field, conn) conn.FindByFields<'TDoc>(tableName, Any, [ field ])
/// Retrieve documents via a comparison on JSON fields, returning only the first result
[<Extension>]
static member inline FindFirstByFields<'TDoc when 'TDoc: null>(conn, tableName, howMatched, fields) =
WithConn.Find.FirstByFields<'TDoc>(tableName, howMatched, fields, conn)
/// Retrieve documents via a comparison on a JSON field, returning only the first result /// Retrieve documents via a comparison on a JSON field, returning only the first result
[<Extension>] [<Extension>]
[<System.Obsolete "Use FindFirstByFields instead; will be removed in v4">]
static member inline FindFirstByField<'TDoc when 'TDoc: null>(conn, tableName, field) = static member inline FindFirstByField<'TDoc when 'TDoc: null>(conn, tableName, field) =
WithConn.Find.FirstByField<'TDoc>(tableName, field, conn) conn.FindFirstByFields<'TDoc>(tableName, Any, [ field ])
/// Update an entire document by its ID /// Update an entire document by its ID
[<Extension>] [<Extension>]
@ -207,27 +267,45 @@ type SqliteConnectionCSharpExtensions =
static member inline PatchById<'TKey, 'TPatch>(conn, tableName, docId: 'TKey, patch: 'TPatch) = static member inline PatchById<'TKey, 'TPatch>(conn, tableName, docId: 'TKey, patch: 'TPatch) =
WithConn.Patch.byId tableName docId patch conn WithConn.Patch.byId tableName docId patch conn
/// Patch documents using a comparison on JSON fields
[<Extension>]
static member inline PatchByFields<'TPatch>(conn, tableName, howMatched, fields, patch: 'TPatch) =
WithConn.Patch.byFields tableName howMatched fields patch conn
/// Patch documents using a comparison on a JSON field /// Patch documents using a comparison on a JSON field
[<Extension>] [<Extension>]
[<System.Obsolete "Use PatchByFields instead; will be removed in v4">]
static member inline PatchByField<'TPatch>(conn, tableName, field, patch: 'TPatch) = static member inline PatchByField<'TPatch>(conn, tableName, field, patch: 'TPatch) =
WithConn.Patch.byField tableName field patch conn conn.PatchByFields(tableName, Any, [ field ], patch)
/// Remove fields from a document by the document's ID /// Remove fields from a document by the document's ID
[<Extension>] [<Extension>]
static member inline RemoveFieldsById<'TKey>(conn, tableName, docId: 'TKey, fieldNames) = static member inline RemoveFieldsById<'TKey>(conn, tableName, docId: 'TKey, fieldNames) =
WithConn.RemoveFields.ById(tableName, docId, fieldNames, conn) WithConn.RemoveFields.byId tableName docId fieldNames conn
/// Remove fields from documents via a comparison on JSON fields in the document
[<Extension>]
static member inline RemoveFieldsByFields(conn, tableName, howMatched, fields, fieldNames) =
WithConn.RemoveFields.byFields tableName howMatched fields fieldNames conn
/// Remove fields from documents via a comparison on a JSON field in the document /// Remove fields from documents via a comparison on a JSON field in the document
[<Extension>] [<Extension>]
[<System.Obsolete "Use RemoveFieldsByFields instead; will be removed in v4">]
static member inline RemoveFieldsByField(conn, tableName, field, fieldNames) = static member inline RemoveFieldsByField(conn, tableName, field, fieldNames) =
WithConn.RemoveFields.ByField(tableName, field, fieldNames, conn) conn.RemoveFieldsByFields(tableName, Any, [ field ], fieldNames)
/// Delete a document by its ID /// Delete a document by its ID
[<Extension>] [<Extension>]
static member inline DeleteById<'TKey>(conn, tableName, docId: 'TKey) = static member inline DeleteById<'TKey>(conn, tableName, docId: 'TKey) =
WithConn.Delete.byId tableName docId conn WithConn.Delete.byId tableName docId conn
/// Delete documents by matching a comparison on JSON fields
[<Extension>]
static member inline DeleteByFields(conn, tableName, howMatched, fields) =
WithConn.Delete.byFields tableName howMatched fields conn
/// Delete documents by matching a comparison on a JSON field /// Delete documents by matching a comparison on a JSON field
[<Extension>] [<Extension>]
[<System.Obsolete "Use DeleteByFields instead; will be removed in v4">]
static member inline DeleteByField(conn, tableName, field) = static member inline DeleteByField(conn, tableName, field) =
WithConn.Delete.byField tableName field conn conn.DeleteByFields(tableName, Any, [ field ])

View File

@ -32,11 +32,11 @@ module Configuration =
module Query = module Query =
/// Create a WHERE clause fragment to implement a comparison on fields in a JSON document /// Create a WHERE clause fragment to implement a comparison on fields in a JSON document
[<CompiledName "FSharpWhereByFields">] [<CompiledName "WhereByFields">]
let whereByFields howMatched fields = let whereByFields howMatched fields =
let name = ParameterName() let name = ParameterName()
fields fields
|> List.map (fun it -> |> Seq.map (fun it ->
match it.Op with match it.Op with
| EX | NEX -> $"{it.SqlitePath} {it.Op}" | EX | NEX -> $"{it.SqlitePath} {it.Op}"
| BT -> | BT ->
@ -45,10 +45,6 @@ module Query =
| _ -> $"{it.SqlitePath} {it.Op} {name.Derive it.ParameterName}") | _ -> $"{it.SqlitePath} {it.Op} {name.Derive it.ParameterName}")
|> String.concat (match howMatched with Any -> " OR " | All -> " AND ") |> String.concat (match howMatched with Any -> " OR " | All -> " AND ")
/// Create a WHERE clause fragment to implement a comparison on fields in a JSON document
let WhereByFields(howMatched, fields: Field seq) =
whereByFields howMatched (List.ofSeq fields)
/// Create a WHERE clause fragment to implement a comparison on a field in a JSON document /// Create a WHERE clause fragment to implement a comparison on a field in a JSON document
[<CompiledName "WhereByField">] [<CompiledName "WhereByField">]
[<System.Obsolete "Use WhereByFields instead; will be removed in v4">] [<System.Obsolete "Use WhereByFields instead; will be removed in v4">]
@ -81,11 +77,16 @@ module Query =
let all tableName = let all tableName =
$"SELECT COUNT(*) AS it FROM %s{tableName}" $"SELECT COUNT(*) AS it FROM %s{tableName}"
/// Query to count matching documents using a text comparison on JSON fields
[<CompiledName "ByFields">]
let byFields tableName howMatched fields =
$"SELECT COUNT(*) AS it FROM %s{tableName} WHERE {whereByFields howMatched fields}"
/// Query to count matching documents using a text comparison on a JSON field /// Query to count matching documents using a text comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field = let byField tableName field =
whereByFields Any [ { field with ParameterName = Some "@field" } ] byFields tableName Any [ field ]
|> sprintf "SELECT COUNT(*) AS it FROM %s WHERE %s" tableName
/// Queries for determining document existence /// Queries for determining document existence
module Exists = module Exists =
@ -94,12 +95,17 @@ module Query =
[<CompiledName "ById">] [<CompiledName "ById">]
let byId tableName = let byId tableName =
$"""SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE {whereById "@id"}) AS it""" $"""SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE {whereById "@id"}) AS it"""
/// Query to determine if documents exist using a comparison on JSON fields
[<CompiledName "ByFields">]
let byFields tableName howMatched fields =
$"SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE {whereByFields howMatched fields}) AS it"
/// Query to determine if documents exist using a comparison on a JSON field /// Query to determine if documents exist using a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field = let byField tableName field =
whereByFields Any [ { field with ParameterName = Some "@field" } ] byFields tableName Any [ field ]
|> sprintf "SELECT EXISTS (SELECT 1 FROM %s WHERE %s) AS it" tableName
/// Queries for retrieving documents /// Queries for retrieving documents
module Find = module Find =
@ -109,12 +115,17 @@ module Query =
let byId tableName = let byId tableName =
$"""{Query.selectFromTable tableName} WHERE {whereById "@id"}""" $"""{Query.selectFromTable tableName} WHERE {whereById "@id"}"""
/// Query to retrieve documents using a comparison on JSON fields
[<CompiledName "ByField">]
let byFields tableName howMatched fields =
$"{Query.selectFromTable tableName} WHERE {whereByFields howMatched fields}"
/// Query to retrieve documents using a comparison on a JSON field /// Query to retrieve documents using a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field = let byField tableName field =
whereByFields Any [ { field with ParameterName = Some "@field" } ] byFields tableName Any [ field ]
|> sprintf "%s WHERE %s" (Query.selectFromTable tableName)
/// Document patching (partial update) queries /// Document patching (partial update) queries
module Patch = module Patch =
@ -126,37 +137,41 @@ module Query =
[<CompiledName "ById">] [<CompiledName "ById">]
let byId tableName = let byId tableName =
whereById "@id" |> update tableName whereById "@id" |> update tableName
/// Query to patch (partially update) a document via a comparison on JSON fields
[<CompiledName "ByFields">]
let byFields tableName howMatched fields =
whereByFields howMatched fields |> update tableName
/// Query to patch (partially update) a document via a comparison on a JSON field /// Query to patch (partially update) a document via a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field = let byField tableName field =
whereByFields Any [ { field with ParameterName = Some "@field" } ] |> update tableName byFields tableName Any [ field ]
/// Queries to remove fields from documents /// Queries to remove fields from documents
module RemoveFields = module RemoveFields =
/// Create an UPDATE statement to remove parameters /// Create an UPDATE statement to remove parameters
let internal update tableName (parameters: SqliteParameter list) whereClause = let internal update tableName (parameters: SqliteParameter seq) whereClause =
let paramNames = parameters |> List.map _.ParameterName |> String.concat ", " let paramNames = parameters |> Seq.map _.ParameterName |> String.concat ", "
$"UPDATE %s{tableName} SET data = json_remove(data, {paramNames}) WHERE {whereClause}" $"UPDATE %s{tableName} SET data = json_remove(data, {paramNames}) WHERE %s{whereClause}"
/// Query to remove fields from a document by the document's ID /// Query to remove fields from a document by the document's ID
[<CompiledName "FSharpById">] [<CompiledName "ById">]
let byId tableName parameters = let byId tableName parameters =
whereById "@id" |> update tableName parameters whereById "@id" |> update tableName parameters
/// Query to remove fields from a document by the document's ID /// Query to remove fields from documents via a comparison on JSON fields within the document
let ById(tableName, parameters) = [<CompiledName "ByFields">]
byId tableName (List.ofSeq parameters) let byFields tableName howMatched fields parameters =
whereByFields howMatched fields |> update tableName parameters
/// Query to remove fields from documents via a comparison on a JSON field within the document /// Query to remove fields from documents via a comparison on a JSON field within the document
[<CompiledName "FSharpByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field parameters = let byField tableName field parameters =
whereByFields Any [ { field with ParameterName = Some "@field" } ] |> update tableName parameters byFields tableName Any [ field ] parameters
/// Query to remove fields from documents via a comparison on a JSON field within the document
let ByField(tableName, field, parameters) =
byField tableName field (List.ofSeq parameters)
/// Queries to delete documents /// Queries to delete documents
module Delete = module Delete =
@ -165,12 +180,17 @@ module Query =
[<CompiledName "ById">] [<CompiledName "ById">]
let byId tableName = let byId tableName =
$"""DELETE FROM %s{tableName} WHERE {whereById "@id"}""" $"""DELETE FROM %s{tableName} WHERE {whereById "@id"}"""
/// Query to delete documents using a comparison on JSON fields
[<CompiledName "ByFields">]
let byFields tableName howMatched fields =
$"DELETE FROM %s{tableName} WHERE {whereByFields howMatched fields}"
/// Query to delete documents using a comparison on a JSON field /// Query to delete documents using a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field = let byField tableName field =
whereByFields Any [ { field with ParameterName = Some "@field" } ] byFields tableName Any [ field ]
|> sprintf "DELETE FROM %s WHERE %s" tableName
/// Parameter handling helpers /// Parameter handling helpers
@ -187,8 +207,9 @@ module Parameters =
let jsonParam name (it: 'TJson) = let jsonParam name (it: 'TJson) =
SqliteParameter(name, Configuration.serializer().Serialize it) SqliteParameter(name, Configuration.serializer().Serialize it)
/// Convert the fields to their parameters /// Create JSON field parameters
let private convertFieldsToParameters fields = [<CompiledName "AddFields">]
let addFieldParams fields parameters =
let name = ParameterName() let name = ParameterName()
fields fields
|> Seq.map (fun it -> |> Seq.map (fun it ->
@ -202,38 +223,23 @@ module Parameters =
yield SqliteParameter($"{p}max", List.last values) yield SqliteParameter($"{p}max", List.last values)
| _ -> yield SqliteParameter(name.Derive it.ParameterName, it.Value) }) | _ -> yield SqliteParameter(name.Derive it.ParameterName, it.Value) })
|> Seq.collect id |> Seq.collect id
/// Create JSON field parameters
[<CompiledName "FSharpAddFields">]
let addFieldParams (fields: Field list) parameters =
convertFieldsToParameters fields
|> Seq.toList
|> List.append parameters
/// Create JSON field parameters
let AddFields fields parameters =
convertFieldsToParameters fields
|> Seq.append parameters |> Seq.append parameters
|> Seq.toList
|> Seq.ofList
/// Create a JSON field parameter (name "@field") /// Create a JSON field parameter (name "@field")
[<CompiledName "FSharpAddField">] [<CompiledName "AddField">]
[<System.Obsolete "Use addFieldParams instead; will be removed in v4">] [<System.Obsolete "Use addFieldParams instead; will be removed in v4">]
let addFieldParam name field parameters = let addFieldParam name field parameters =
addFieldParams [ { field with ParameterName = Some name } ] parameters addFieldParams [ { field with ParameterName = Some name } ] parameters
/// Create a JSON field parameter (name "@field")
[<System.Obsolete "Use AddFields instead; will be removed in v4">]
let AddField(name, field, parameters) =
AddFields [ { field with ParameterName = Some name } ] parameters
/// Append JSON field name parameters for the given field names to the given parameters /// Append JSON field name parameters for the given field names to the given parameters
[<CompiledName "FSharpFieldNames">] [<CompiledName "FieldNames">]
let fieldNameParams paramName (fieldNames: string list) = let fieldNameParams paramName fieldNames =
fieldNames |> List.mapi (fun idx name -> SqliteParameter($"%s{paramName}{idx}", $"$.{name}")) fieldNames
|> Seq.mapi (fun idx name -> SqliteParameter($"%s{paramName}{idx}", $"$.%s{name}"))
/// Append JSON field name parameters for the given field names to the given parameters |> Seq.toList
let FieldNames(paramName, fieldNames: string seq) = |> Seq.ofList
fieldNames |> Seq.mapi (fun idx name -> SqliteParameter($"%s{paramName}{idx}", $"$.{name}"))
/// An empty parameter sequence /// An empty parameter sequence
[<CompiledName "None">] [<CompiledName "None">]
@ -382,14 +388,16 @@ module WithConn =
let all tableName conn = let all tableName conn =
Custom.scalar (Query.Count.all tableName) [] toCount conn Custom.scalar (Query.Count.all tableName) [] toCount conn
/// Count matching documents using a comparison on JSON fields
[<CompiledName "ByFields">]
let byFields tableName howMatched fields conn =
Custom.scalar (Query.Count.byFields tableName howMatched fields) (addFieldParams fields []) toCount conn
/// Count matching documents using a comparison on a JSON field /// Count matching documents using a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field conn = let byField tableName field conn =
Custom.scalar byFields tableName Any [ field ] conn
(Query.Count.byField tableName field)
(addFieldParams [ { field with ParameterName = Some "@field" } ] [])
toCount
conn
/// Commands to determine if documents exist /// Commands to determine if documents exist
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -399,15 +407,17 @@ module WithConn =
[<CompiledName "ById">] [<CompiledName "ById">]
let byId tableName (docId: 'TKey) conn = let byId tableName (docId: 'TKey) conn =
Custom.scalar (Query.Exists.byId tableName) [ idParam docId ] toExists conn Custom.scalar (Query.Exists.byId tableName) [ idParam docId ] toExists conn
/// Determine if a document exists using a comparison on JSON fields
[<CompiledName "ByFields">]
let byFields tableName howMatched fields conn =
Custom.scalar (Query.Exists.byFields tableName howMatched fields) (addFieldParams fields []) toExists conn
/// Determine if a document exists using a comparison on a JSON field /// Determine if a document exists using a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field conn = let byField tableName field conn =
Custom.scalar byFields tableName Any [ field ] conn
(Query.Exists.byField tableName field)
(addFieldParams [ { field with ParameterName = Some "@field" } ] [])
toExists
conn
/// Commands to retrieve documents /// Commands to retrieve documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -430,40 +440,56 @@ module WithConn =
/// Retrieve a document by its ID (returns null if not found) /// Retrieve a document by its ID (returns null if not found)
let ById<'TKey, 'TDoc when 'TDoc: null>(tableName, docId: 'TKey, conn) = let ById<'TKey, 'TDoc when 'TDoc: null>(tableName, docId: 'TKey, conn) =
Custom.Single<'TDoc>(Query.Find.byId tableName, [ idParam docId ], fromData<'TDoc>, conn) Custom.Single<'TDoc>(Query.Find.byId tableName, [ idParam docId ], fromData<'TDoc>, conn)
/// Retrieve documents via a comparison on JSON fields
[<CompiledName "FSharpByFields">]
let byFields<'TDoc> tableName howMatched fields conn =
Custom.list<'TDoc>
(Query.Find.byFields tableName howMatched fields) (addFieldParams fields []) fromData<'TDoc> conn
/// Retrieve documents via a comparison on a JSON field /// Retrieve documents via a comparison on a JSON field
[<CompiledName "FSharpByField">] [<CompiledName "FSharpByField">]
[<System.Obsolete "Use byFields instead; will be removed in v4">]
let byField<'TDoc> tableName field conn = let byField<'TDoc> tableName field conn =
Custom.list<'TDoc> byFields<'TDoc> tableName Any [ field ] conn
(Query.Find.byField tableName field)
(addFieldParams [ { field with ParameterName = Some "@field" } ] [])
fromData<'TDoc>
conn
/// Retrieve documents via a comparison on a JSON field /// Retrieve documents via a comparison on JSON fields
let ByField<'TDoc>(tableName, field, conn) = let ByFields<'TDoc>(tableName, howMatched, fields, conn) =
Custom.List<'TDoc>( Custom.List<'TDoc>(
Query.Find.byField tableName field, Query.Find.byFields tableName howMatched fields, addFieldParams fields [], fromData<'TDoc>, conn)
addFieldParams [ { field with ParameterName = Some "@field" } ] [],
fromData<'TDoc>, /// Retrieve documents via a comparison on a JSON field
conn) [<System.Obsolete "Use ByFields instead; will be removed in v4">]
let ByField<'TDoc>(tableName, field, conn) =
ByFields<'TDoc>(tableName, Any, [ field ], conn)
/// Retrieve documents via a comparison on a JSON field, returning only the first result /// Retrieve documents via a comparison on JSON fields, returning only the first result
[<CompiledName "FSharpFirstByField">] [<CompiledName "FSharpFirstByFields">]
let firstByField<'TDoc> tableName field conn = let firstByFields<'TDoc> tableName howMatched fields conn =
Custom.single Custom.single
$"{Query.Find.byField tableName field} LIMIT 1" $"{Query.Find.byFields tableName howMatched fields} LIMIT 1"
(addFieldParams [ { field with ParameterName = Some "@field" } ] []) (addFieldParams fields [])
fromData<'TDoc> fromData<'TDoc>
conn conn
/// Retrieve documents via a comparison on a JSON field, returning only the first result /// Retrieve documents via a comparison on a JSON field, returning only the first result
let FirstByField<'TDoc when 'TDoc: null>(tableName, field, conn) = [<CompiledName "FSharpFirstByField">]
[<System.Obsolete "Use firstByFields instead; will be removed in v4">]
let firstByField<'TDoc> tableName field conn =
firstByFields<'TDoc> tableName Any [ field ] conn
/// Retrieve documents via a comparison on JSON fields, returning only the first result
let FirstByFields<'TDoc when 'TDoc: null>(tableName, howMatched, fields, conn) =
Custom.Single( Custom.Single(
$"{Query.Find.byField tableName field} LIMIT 1", $"{Query.Find.byFields tableName howMatched fields} LIMIT 1",
addFieldParams [ { field with ParameterName = Some "@field" } ] [], addFieldParams fields [],
fromData<'TDoc>, fromData<'TDoc>,
conn) conn)
/// Retrieve documents via a comparison on a JSON field, returning only the first result
[<System.Obsolete "Use FirstByFields instead; will be removed in v4">]
let FirstByField<'TDoc when 'TDoc: null>(tableName, field, conn) =
FirstByFields(tableName, Any, [ field ], conn)
/// Commands to update documents /// Commands to update documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -492,40 +518,47 @@ module WithConn =
let byId tableName (docId: 'TKey) (patch: 'TPatch) conn = let byId tableName (docId: 'TKey) (patch: 'TPatch) conn =
Custom.nonQuery (Query.Patch.byId tableName) [ idParam docId; jsonParam "@data" patch ] conn Custom.nonQuery (Query.Patch.byId tableName) [ idParam docId; jsonParam "@data" patch ] conn
/// Patch documents using a comparison on JSON fields
[<CompiledName "ByFields">]
let byFields tableName howMatched fields (patch: 'TPatch) conn =
Custom.nonQuery
(Query.Patch.byFields tableName howMatched fields)
(addFieldParams fields [ jsonParam "@data" patch ])
conn
/// Patch documents using a comparison on a JSON field /// Patch documents using a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName field (patch: 'TPatch) (conn: SqliteConnection) = [<System.Obsolete "Use ByFields instead; will be removed in v4">]
Custom.nonQuery let byField tableName field (patch: 'TPatch) conn =
(Query.Patch.byField tableName field) byFields tableName Any [ field ] patch conn
(addFieldParams [ { field with ParameterName = Some "@field" } ] [ jsonParam "@data" patch ])
conn
/// Commands to remove fields from documents /// Commands to remove fields from documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
module RemoveFields = module RemoveFields =
/// Remove fields from a document by the document's ID /// Remove fields from a document by the document's ID
[<CompiledName "FSharpById">] [<CompiledName "ById">]
let byId tableName (docId: 'TKey) fieldNames conn = let byId tableName (docId: 'TKey) fieldNames conn =
let nameParams = fieldNameParams "@name" fieldNames
Custom.nonQuery (Query.RemoveFields.byId tableName nameParams) (idParam docId :: nameParams) conn
/// Remove fields from a document by the document's ID
let ById(tableName, docId: 'TKey, fieldNames, conn) =
byId tableName docId (List.ofSeq fieldNames) conn
/// Remove fields from documents via a comparison on a JSON field in the document
[<CompiledName "FSharpByField">]
let byField tableName field fieldNames conn =
let nameParams = fieldNameParams "@name" fieldNames let nameParams = fieldNameParams "@name" fieldNames
Custom.nonQuery Custom.nonQuery
(Query.RemoveFields.byField tableName field nameParams) (Query.RemoveFields.byId tableName nameParams)
(addFieldParams [ { field with ParameterName = Some "@field" } ] nameParams) (idParam docId |> Seq.singleton |> Seq.append nameParams)
conn conn
/// Remove fields from documents via a comparison on JSON fields in the document
[<CompiledName "ByFields">]
let byFields tableName howMatched fields fieldNames conn =
let nameParams = fieldNameParams "@name" fieldNames
Custom.nonQuery
(Query.RemoveFields.byFields tableName howMatched fields nameParams)
(addFieldParams fields nameParams)
conn
/// Remove fields from documents via a comparison on a JSON field in the document /// Remove fields from documents via a comparison on a JSON field in the document
let ByField(tableName, field, fieldNames, conn) = [<CompiledName "ByField">]
byField tableName field (List.ofSeq fieldNames) conn [<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field fieldNames conn =
byFields tableName Any [ field ] fieldNames conn
/// Commands to delete documents /// Commands to delete documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -535,14 +568,17 @@ module WithConn =
[<CompiledName "ById">] [<CompiledName "ById">]
let byId tableName (docId: 'TKey) conn = let byId tableName (docId: 'TKey) conn =
Custom.nonQuery (Query.Delete.byId tableName) [ idParam docId ] conn Custom.nonQuery (Query.Delete.byId tableName) [ idParam docId ] conn
/// Delete documents by matching a comparison on JSON fields
[<CompiledName "ByFields">]
let byFields tableName howMatched fields conn =
Custom.nonQuery (Query.Delete.byFields tableName howMatched fields) (addFieldParams fields []) conn
/// Delete documents by matching a comparison on a JSON field /// Delete documents by matching a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field conn = let byField tableName field conn =
Custom.nonQuery byFields tableName Any [ field ] conn
(Query.Delete.byField tableName field)
(addFieldParams [ { field with ParameterName = Some "@field" } ] [])
conn
/// Commands to execute custom SQL queries /// Commands to execute custom SQL queries
@ -630,11 +666,17 @@ module Count =
use conn = Configuration.dbConn () use conn = Configuration.dbConn ()
WithConn.Count.all tableName conn WithConn.Count.all tableName conn
/// Count matching documents using a comparison on JSON fields
[<CompiledName "ByFields">]
let byFields tableName howMatched fields =
use conn = Configuration.dbConn ()
WithConn.Count.byFields tableName howMatched fields conn
/// Count matching documents using a comparison on a JSON field /// Count matching documents using a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field = let byField tableName field =
use conn = Configuration.dbConn () byFields tableName Any [ field ]
WithConn.Count.byField tableName field conn
/// Commands to determine if documents exist /// Commands to determine if documents exist
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -645,12 +687,18 @@ module Exists =
let byId tableName (docId: 'TKey) = let byId tableName (docId: 'TKey) =
use conn = Configuration.dbConn () use conn = Configuration.dbConn ()
WithConn.Exists.byId tableName docId conn WithConn.Exists.byId tableName docId conn
/// Determine if a document exists using a comparison on JSON fields
[<CompiledName "ByFields">]
let byFields tableName howMatched fields =
use conn = Configuration.dbConn ()
WithConn.Exists.byFields tableName howMatched fields conn
/// Determine if a document exists using a comparison on a JSON field /// Determine if a document exists using a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field = let byField tableName field =
use conn = Configuration.dbConn () byFields tableName Any [ field ]
WithConn.Exists.byField tableName field conn
/// Commands to determine if documents exist /// Commands to determine if documents exist
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -678,27 +726,49 @@ module Find =
use conn = Configuration.dbConn () use conn = Configuration.dbConn ()
WithConn.Find.ById<'TKey, 'TDoc>(tableName, docId, conn) WithConn.Find.ById<'TKey, 'TDoc>(tableName, docId, conn)
/// Retrieve documents via a comparison on JSON fields
[<CompiledName "FSharpByFields">]
let byFields<'TDoc> tableName howMatched fields =
use conn = Configuration.dbConn ()
WithConn.Find.byFields<'TDoc> tableName howMatched fields conn
/// Retrieve documents via a comparison on a JSON field /// Retrieve documents via a comparison on a JSON field
[<CompiledName "FSharpByField">] [<CompiledName "FSharpByField">]
[<System.Obsolete "Use byFields instead; will be removed in v4">]
let byField<'TDoc> tableName field = let byField<'TDoc> tableName field =
byFields tableName Any [ field ]
/// Retrieve documents via a comparison on JSON fields
let ByFields<'TDoc>(tableName, howMatched, fields) =
use conn = Configuration.dbConn () use conn = Configuration.dbConn ()
WithConn.Find.byField<'TDoc> tableName field conn WithConn.Find.ByFields<'TDoc>(tableName, howMatched, fields, conn)
/// Retrieve documents via a comparison on a JSON field /// Retrieve documents via a comparison on a JSON field
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let ByField<'TDoc>(tableName, field) = let ByField<'TDoc>(tableName, field) =
use conn = Configuration.dbConn () ByFields<'TDoc>(tableName, Any, [ field ])
WithConn.Find.ByField<'TDoc>(tableName, field, conn)
/// Retrieve documents via a comparison on JSON fields, returning only the first result
[<CompiledName "FSharpFirstByFields">]
let firstByFields<'TDoc> tableName howMatched fields =
use conn = Configuration.dbConn ()
WithConn.Find.firstByFields<'TDoc> tableName howMatched fields conn
/// Retrieve documents via a comparison on a JSON field, returning only the first result /// Retrieve documents via a comparison on a JSON field, returning only the first result
[<CompiledName "FSharpFirstByField">] [<CompiledName "FSharpFirstByField">]
[<System.Obsolete "Use firstByFields instead; will be removed in v4">]
let firstByField<'TDoc> tableName field = let firstByField<'TDoc> tableName field =
firstByFields<'TDoc> tableName Any [ field ]
/// Retrieve documents via a comparison on JSON fields, returning only the first result
let FirstByFields<'TDoc when 'TDoc: null>(tableName, howMatched, fields) =
use conn = Configuration.dbConn () use conn = Configuration.dbConn ()
WithConn.Find.firstByField<'TDoc> tableName field conn WithConn.Find.FirstByFields<'TDoc>(tableName, howMatched, fields, conn)
/// Retrieve documents via a comparison on a JSON field, returning only the first result /// Retrieve documents via a comparison on a JSON field, returning only the first result
[<System.Obsolete "Use FirstByFields instead; will be removed in v4">]
let FirstByField<'TDoc when 'TDoc: null>(tableName, field) = let FirstByField<'TDoc when 'TDoc: null>(tableName, field) =
use conn = Configuration.dbConn () FirstByFields<'TDoc>(tableName, Any, [ field ])
WithConn.Find.FirstByField<'TDoc>(tableName, field, conn)
/// Commands to update documents /// Commands to update documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -731,37 +801,39 @@ module Patch =
use conn = Configuration.dbConn () use conn = Configuration.dbConn ()
WithConn.Patch.byId tableName docId patch conn WithConn.Patch.byId tableName docId patch conn
/// Patch documents using a comparison on JSON fields in the WHERE clause
[<CompiledName "ByFields">]
let byFields tableName howMatched fields (patch: 'TPatch) =
use conn = Configuration.dbConn ()
WithConn.Patch.byFields tableName howMatched fields patch conn
/// Patch documents using a comparison on a JSON field in the WHERE clause /// Patch documents using a comparison on a JSON field in the WHERE clause
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field (patch: 'TPatch) = let byField tableName field (patch: 'TPatch) =
use conn = Configuration.dbConn () byFields tableName Any [ field ] patch
WithConn.Patch.byField tableName field patch conn
/// Commands to remove fields from documents /// Commands to remove fields from documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
module RemoveFields = module RemoveFields =
/// Remove fields from a document by the document's ID /// Remove fields from a document by the document's ID
[<CompiledName "FSharpById">] [<CompiledName "ById">]
let byId tableName (docId: 'TKey) fieldNames = let byId tableName (docId: 'TKey) fieldNames =
use conn = Configuration.dbConn () use conn = Configuration.dbConn ()
WithConn.RemoveFields.byId tableName docId fieldNames conn WithConn.RemoveFields.byId tableName docId fieldNames conn
/// Remove fields from a document by the document's ID /// Remove field from documents via a comparison on JSON fields in the document
let ById(tableName, docId: 'TKey, fieldNames) = [<CompiledName "ByFields">]
let byFields tableName howMatched fields fieldNames =
use conn = Configuration.dbConn () use conn = Configuration.dbConn ()
WithConn.RemoveFields.ById(tableName, docId, fieldNames, conn) WithConn.RemoveFields.byFields tableName howMatched fields fieldNames conn
/// Remove field from documents via a comparison on a JSON field in the document /// Remove field from documents via a comparison on a JSON field in the document
[<CompiledName "FSharpByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field fieldNames = let byField tableName field fieldNames =
use conn = Configuration.dbConn () byFields tableName Any [ field ] fieldNames
WithConn.RemoveFields.byField tableName field fieldNames conn
/// Remove field from documents via a comparison on a JSON field in the document
let ByField(tableName, field, fieldNames) =
use conn = Configuration.dbConn ()
WithConn.RemoveFields.ByField(tableName, field, fieldNames, conn)
/// Commands to delete documents /// Commands to delete documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -772,9 +844,15 @@ module Delete =
let byId tableName (docId: 'TKey) = let byId tableName (docId: 'TKey) =
use conn = Configuration.dbConn () use conn = Configuration.dbConn ()
WithConn.Delete.byId tableName docId conn WithConn.Delete.byId tableName docId conn
/// Delete documents by matching a comparison on JSON fields
[<CompiledName "ByFields">]
let byFields tableName howMatched fields =
use conn = Configuration.dbConn ()
WithConn.Delete.byFields tableName howMatched fields conn
/// Delete documents by matching a comparison on a JSON field /// Delete documents by matching a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
[<System.Obsolete "Use ByFields instead; will be removed in v4">]
let byField tableName field = let byField tableName field =
use conn = Configuration.dbConn () byFields tableName Any [ field ]
WithConn.Delete.byField tableName field conn

View File

@ -118,7 +118,6 @@ public static class PostgresCSharpTests
Expect.isTrue(it[1].Item2.IsParameter, "Maximum field parameter value incorrect"); Expect.isTrue(it[1].Item2.IsParameter, "Maximum field parameter value incorrect");
}) })
]), ]),
#pragma warning restore CS0618
TestList("FieldName", TestList("FieldName",
[ [
TestCase("succeeds for one name", () => TestCase("succeeds for one name", () =>
@ -140,6 +139,7 @@ public static class PostgresCSharpTests
} }
}) })
]) ])
#pragma warning restore CS0618
]), ]),
TestList("Query", TestList("Query",
[ [

View File

@ -18,10 +18,10 @@ public static class SqliteCSharpExtensionTests
/// Integration tests for the SQLite extension methods /// Integration tests for the SQLite extension methods
/// </summary> /// </summary>
[Tests] [Tests]
public static readonly Test Integration = TestList("Sqlite.C#.Extensions", new[] public static readonly Test Integration = TestList("Sqlite.C#.Extensions",
{ [
TestList("CustomSingle", new[] TestList("CustomSingle",
{ [
TestCase("succeeds when a row is found", async () => TestCase("succeeds when a row is found", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -43,9 +43,9 @@ public static class SqliteCSharpExtensionTests
new[] { Parameters.Id("eighty") }, Results.FromData<JsonDocument>); new[] { Parameters.Id("eighty") }, Results.FromData<JsonDocument>);
Expect.isNull(doc, "There should not have been a document returned"); Expect.isNull(doc, "There should not have been a document returned");
}) })
}), ]),
TestList("CustomList", new[] TestList("CustomList",
{ [
TestCase("succeeds when data is found", async () => TestCase("succeeds when data is found", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -67,9 +67,9 @@ public static class SqliteCSharpExtensionTests
new[] { new SqliteParameter("@value", 100) }, Results.FromData<JsonDocument>); new[] { new SqliteParameter("@value", 100) }, Results.FromData<JsonDocument>);
Expect.isEmpty(docs, "There should have been no documents returned"); Expect.isEmpty(docs, "There should have been no documents returned");
}) })
}), ]),
TestList("CustomNonQuery", new[] TestList("CustomNonQuery",
{ [
TestCase("succeeds when operating on data", async () => TestCase("succeeds when operating on data", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -93,7 +93,7 @@ public static class SqliteCSharpExtensionTests
var remaining = await conn.CountAll(SqliteDb.TableName); var remaining = await conn.CountAll(SqliteDb.TableName);
Expect.equal(remaining, 5L, "There should be 5 documents remaining in the table"); Expect.equal(remaining, 5L, "There should be 5 documents remaining in the table");
}) })
}), ]),
TestCase("CustomScalar succeeds", async () => TestCase("CustomScalar succeeds", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -140,8 +140,8 @@ public static class SqliteCSharpExtensionTests
exists = await indexExists(); exists = await indexExists();
Expect.isTrue(exists, "The index should now exist"); Expect.isTrue(exists, "The index should now exist");
}), }),
TestList("Insert", new[] TestList("Insert",
{ [
TestCase("succeeds", async () => TestCase("succeeds", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -168,9 +168,9 @@ public static class SqliteCSharpExtensionTests
// This is what is supposed to happen // This is what is supposed to happen
} }
}) })
}), ]),
TestList("Save", new[] TestList("Save",
{ [
TestCase("succeeds when a document is inserted", async () => TestCase("succeeds when a document is inserted", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -203,7 +203,7 @@ public static class SqliteCSharpExtensionTests
Expect.equal(after!.Id, "test", "The updated document is not correct"); Expect.equal(after!.Id, "test", "The updated document is not correct");
Expect.isNull(after.Sub, "There should not have been a sub-document in the updated document"); Expect.isNull(after.Sub, "There should not have been a sub-document in the updated document");
}) })
}), ]),
TestCase("CountAll succeeds", async () => TestCase("CountAll succeeds", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -213,6 +213,7 @@ public static class SqliteCSharpExtensionTests
var theCount = await conn.CountAll(SqliteDb.TableName); var theCount = await conn.CountAll(SqliteDb.TableName);
Expect.equal(theCount, 5L, "There should have been 5 matching documents"); Expect.equal(theCount, 5L, "There should have been 5 matching documents");
}), }),
#pragma warning disable CS0618
TestCase("CountByField succeeds", async () => TestCase("CountByField succeeds", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -222,8 +223,9 @@ public static class SqliteCSharpExtensionTests
var theCount = await conn.CountByField(SqliteDb.TableName, Field.EQ("Value", "purple")); var theCount = await conn.CountByField(SqliteDb.TableName, Field.EQ("Value", "purple"));
Expect.equal(theCount, 2L, "There should have been 2 matching documents"); Expect.equal(theCount, 2L, "There should have been 2 matching documents");
}), }),
TestList("ExistsById", new[] #pragma warning restore CS0618
{ TestList("ExistsById",
[
TestCase("succeeds when a document exists", async () => TestCase("succeeds when a document exists", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -242,9 +244,10 @@ public static class SqliteCSharpExtensionTests
var exists = await conn.ExistsById(SqliteDb.TableName, "seven"); var exists = await conn.ExistsById(SqliteDb.TableName, "seven");
Expect.isFalse(exists, "There should not have been an existing document"); Expect.isFalse(exists, "There should not have been an existing document");
}) })
}), ]),
TestList("ExistsByField", new[] #pragma warning disable CS0618
{ TestList("ExistsByField",
[
TestCase("succeeds when documents exist", async () => TestCase("succeeds when documents exist", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -263,9 +266,10 @@ public static class SqliteCSharpExtensionTests
var exists = await conn.ExistsByField(SqliteDb.TableName, Field.EQ("Nothing", "none")); var exists = await conn.ExistsByField(SqliteDb.TableName, Field.EQ("Nothing", "none"));
Expect.isFalse(exists, "There should not have been any existing documents"); Expect.isFalse(exists, "There should not have been any existing documents");
}) })
}), ]),
TestList("FindAll", new[] #pragma warning restore CS0618
{ TestList("FindAll",
[
TestCase("succeeds when there is data", async () => TestCase("succeeds when there is data", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -285,9 +289,9 @@ public static class SqliteCSharpExtensionTests
var results = await conn.FindAll<JsonDocument>(SqliteDb.TableName); var results = await conn.FindAll<JsonDocument>(SqliteDb.TableName);
Expect.isEmpty(results, "There should have been no documents returned"); Expect.isEmpty(results, "There should have been no documents returned");
}) })
}), ]),
TestList("FindById", new[] TestList("FindById",
{ [
TestCase("succeeds when a document is found", async () => TestCase("succeeds when a document is found", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -307,9 +311,10 @@ public static class SqliteCSharpExtensionTests
var doc = await conn.FindById<string, JsonDocument>(SqliteDb.TableName, "eighty-seven"); var doc = await conn.FindById<string, JsonDocument>(SqliteDb.TableName, "eighty-seven");
Expect.isNull(doc, "There should not have been a document returned"); Expect.isNull(doc, "There should not have been a document returned");
}) })
}), ]),
TestList("FindByField", new[] #pragma warning disable CS0618
{ TestList("FindByField",
[
TestCase("succeeds when documents are found", async () => TestCase("succeeds when documents are found", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -328,9 +333,9 @@ public static class SqliteCSharpExtensionTests
var docs = await conn.FindByField<JsonDocument>(SqliteDb.TableName, Field.EQ("Value", "mauve")); var docs = await conn.FindByField<JsonDocument>(SqliteDb.TableName, Field.EQ("Value", "mauve"));
Expect.isEmpty(docs, "There should have been no documents returned"); Expect.isEmpty(docs, "There should have been no documents returned");
}) })
}), ]),
TestList("FindFirstByField", new[] TestList("FindFirstByField",
{ [
TestCase("succeeds when a document is found", async () => TestCase("succeeds when a document is found", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -360,9 +365,10 @@ public static class SqliteCSharpExtensionTests
var doc = await conn.FindFirstByField<JsonDocument>(SqliteDb.TableName, Field.EQ("Value", "absent")); var doc = await conn.FindFirstByField<JsonDocument>(SqliteDb.TableName, Field.EQ("Value", "absent"));
Expect.isNull(doc, "There should not have been a document returned"); Expect.isNull(doc, "There should not have been a document returned");
}) })
}), ]),
TestList("UpdateById", new[] #pragma warning restore CS0618
{ TestList("UpdateById",
[
TestCase("succeeds when a document is updated", async () => TestCase("succeeds when a document is updated", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -389,9 +395,9 @@ public static class SqliteCSharpExtensionTests
await conn.UpdateById(SqliteDb.TableName, "test", await conn.UpdateById(SqliteDb.TableName, "test",
new JsonDocument { Id = "x", Sub = new() { Foo = "blue", Bar = "red" } }); new JsonDocument { Id = "x", Sub = new() { Foo = "blue", Bar = "red" } });
}) })
}), ]),
TestList("UpdateByFunc", new[] TestList("UpdateByFunc",
{ [
TestCase("succeeds when a document is updated", async () => TestCase("succeeds when a document is updated", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -418,9 +424,9 @@ public static class SqliteCSharpExtensionTests
await conn.UpdateByFunc(SqliteDb.TableName, doc => doc.Id, await conn.UpdateByFunc(SqliteDb.TableName, doc => doc.Id,
new JsonDocument { Id = "one", Value = "le un", NumValue = 1 }); new JsonDocument { Id = "one", Value = "le un", NumValue = 1 });
}) })
}), ]),
TestList("PatchById", new[] TestList("PatchById",
{ [
TestCase("succeeds when a document is updated", async () => TestCase("succeeds when a document is updated", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -443,9 +449,10 @@ public static class SqliteCSharpExtensionTests
// This not raising an exception is the test // This not raising an exception is the test
await conn.PatchById(SqliteDb.TableName, "test", new { Foo = "green" }); await conn.PatchById(SqliteDb.TableName, "test", new { Foo = "green" });
}) })
}), ]),
TestList("PatchByField", new[] #pragma warning disable CS0618
{ TestList("PatchByField",
[
TestCase("succeeds when a document is updated", async () => TestCase("succeeds when a document is updated", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -466,9 +473,10 @@ public static class SqliteCSharpExtensionTests
// This not raising an exception is the test // This not raising an exception is the test
await conn.PatchByField(SqliteDb.TableName, Field.EQ("Value", "burgundy"), new { Foo = "green" }); await conn.PatchByField(SqliteDb.TableName, Field.EQ("Value", "burgundy"), new { Foo = "green" });
}) })
}), ]),
TestList("RemoveFieldsById", new[] #pragma warning restore CS0618
{ TestList("RemoveFieldsById",
[
TestCase("succeeds when fields are removed", async () => TestCase("succeeds when fields are removed", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -498,9 +506,10 @@ public static class SqliteCSharpExtensionTests
// This not raising an exception is the test // This not raising an exception is the test
await conn.RemoveFieldsById(SqliteDb.TableName, "two", new[] { "Value" }); await conn.RemoveFieldsById(SqliteDb.TableName, "two", new[] { "Value" });
}) })
}), ]),
TestList("RemoveFieldsByField", new[] #pragma warning disable CS0618
{ TestList("RemoveFieldsByField",
[
TestCase("succeeds when a field is removed", async () => TestCase("succeeds when a field is removed", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -529,9 +538,10 @@ public static class SqliteCSharpExtensionTests
// This not raising an exception is the test // This not raising an exception is the test
await conn.RemoveFieldsByField(SqliteDb.TableName, Field.NE("Abracadabra", "apple"), new[] { "Value" }); await conn.RemoveFieldsByField(SqliteDb.TableName, Field.NE("Abracadabra", "apple"), new[] { "Value" });
}) })
}), ]),
TestList("DeleteById", new[] #pragma warning restore CS0618
{ TestList("DeleteById",
[
TestCase("succeeds when a document is deleted", async () => TestCase("succeeds when a document is deleted", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -552,9 +562,10 @@ public static class SqliteCSharpExtensionTests
var remaining = await conn.CountAll(SqliteDb.TableName); var remaining = await conn.CountAll(SqliteDb.TableName);
Expect.equal(remaining, 5L, "There should have been 5 documents remaining"); Expect.equal(remaining, 5L, "There should have been 5 documents remaining");
}) })
}), ]),
TestList("DeleteByField", new[] #pragma warning disable CS0618
{ TestList("DeleteByField",
[
TestCase("succeeds when documents are deleted", async () => TestCase("succeeds when documents are deleted", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -575,7 +586,8 @@ public static class SqliteCSharpExtensionTests
var remaining = await conn.CountAll(SqliteDb.TableName); var remaining = await conn.CountAll(SqliteDb.TableName);
Expect.equal(remaining, 5L, "There should have been 5 documents remaining"); Expect.equal(remaining, 5L, "There should have been 5 documents remaining");
}) })
}), ]),
#pragma warning restore CS0618
TestCase("Clean up database", () => Sqlite.Configuration.UseConnectionString("data source=:memory:")) TestCase("Clean up database", () => Sqlite.Configuration.UseConnectionString("data source=:memory:"))
}); ]);
} }

View File

@ -63,6 +63,7 @@ public static class SqliteCSharpTests
"WHERE clause not correct"); "WHERE clause not correct");
}) })
]), ]),
#pragma warning disable CS0618
TestList("WhereByField", TestList("WhereByField",
[ [
TestCase("succeeds when a logical operator is passed", () => TestCase("succeeds when a logical operator is passed", () =>
@ -81,6 +82,7 @@ public static class SqliteCSharpTests
"data->>'aField' BETWEEN @rangemin AND @rangemax", "WHERE clause not correct"); "data->>'aField' BETWEEN @rangemin AND @rangemax", "WHERE clause not correct");
}) })
]), ]),
#pragma warning restore CS0618
TestCase("WhereById succeeds", () => TestCase("WhereById succeeds", () =>
{ {
Expect.equal(Sqlite.Query.WhereById("@id"), "data->>'Id' = @id", "WHERE clause not correct"); Expect.equal(Sqlite.Query.WhereById("@id"), "data->>'Id' = @id", "WHERE clause not correct");
@ -102,12 +104,14 @@ public static class SqliteCSharpTests
Expect.equal(Sqlite.Query.Count.All("tbl"), "SELECT COUNT(*) AS it FROM tbl", Expect.equal(Sqlite.Query.Count.All("tbl"), "SELECT COUNT(*) AS it FROM tbl",
"Count query not correct"); "Count query not correct");
}), }),
#pragma warning disable CS0618
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Sqlite.Query.Count.ByField("tbl", Field.EQ("thatField", 0)), Expect.equal(Sqlite.Query.Count.ByField("tbl", Field.EQ("thatField", 0)),
"SELECT COUNT(*) AS it FROM tbl WHERE data->>'thatField' = @field", "SELECT COUNT(*) AS it FROM tbl WHERE data->>'thatField' = @field0",
"JSON field text comparison count query not correct"); "JSON field text comparison count query not correct");
}) })
#pragma warning restore CS0618
]), ]),
TestList("Exists", TestList("Exists",
[ [
@ -117,12 +121,14 @@ public static class SqliteCSharpTests
"SELECT EXISTS (SELECT 1 FROM tbl WHERE data->>'Id' = @id) AS it", "SELECT EXISTS (SELECT 1 FROM tbl WHERE data->>'Id' = @id) AS it",
"ID existence query not correct"); "ID existence query not correct");
}), }),
#pragma warning disable CS0618
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Sqlite.Query.Exists.ByField("tbl", Field.LT("Test", 0)), Expect.equal(Sqlite.Query.Exists.ByField("tbl", Field.LT("Test", 0)),
"SELECT EXISTS (SELECT 1 FROM tbl WHERE data->>'Test' < @field) AS it", "SELECT EXISTS (SELECT 1 FROM tbl WHERE data->>'Test' < @field0) AS it",
"JSON field text comparison exists query not correct"); "JSON field text comparison exists query not correct");
}) })
#pragma warning restore CS0618
]), ]),
TestList("Find", TestList("Find",
[ [
@ -131,12 +137,14 @@ public static class SqliteCSharpTests
Expect.equal(Sqlite.Query.Find.ById("tbl"), "SELECT data FROM tbl WHERE data->>'Id' = @id", Expect.equal(Sqlite.Query.Find.ById("tbl"), "SELECT data FROM tbl WHERE data->>'Id' = @id",
"SELECT by ID query not correct"); "SELECT by ID query not correct");
}), }),
#pragma warning disable CS0618
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Sqlite.Query.Find.ByField("tbl", Field.GE("Golf", 0)), Expect.equal(Sqlite.Query.Find.ByField("tbl", Field.GE("Golf", 0)),
"SELECT data FROM tbl WHERE data->>'Golf' >= @field", "SELECT data FROM tbl WHERE data->>'Golf' >= @field0",
"SELECT by JSON comparison query not correct"); "SELECT by JSON comparison query not correct");
}) })
#pragma warning restore CS0618
]), ]),
TestList("Patch", TestList("Patch",
[ [
@ -146,12 +154,14 @@ public static class SqliteCSharpTests
"UPDATE tbl SET data = json_patch(data, json(@data)) WHERE data->>'Id' = @id", "UPDATE tbl SET data = json_patch(data, json(@data)) WHERE data->>'Id' = @id",
"UPDATE partial by ID statement not correct"); "UPDATE partial by ID statement not correct");
}), }),
#pragma warning disable CS0618
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Sqlite.Query.Patch.ByField("tbl", Field.NE("Part", 0)), Expect.equal(Sqlite.Query.Patch.ByField("tbl", Field.NE("Part", 0)),
"UPDATE tbl SET data = json_patch(data, json(@data)) WHERE data->>'Part' <> @field", "UPDATE tbl SET data = json_patch(data, json(@data)) WHERE data->>'Part' <> @field0",
"UPDATE partial by JSON comparison query not correct"); "UPDATE partial by JSON comparison query not correct");
}) })
#pragma warning restore CS0618
]), ]),
TestList("RemoveFields", TestList("RemoveFields",
[ [
@ -161,13 +171,15 @@ public static class SqliteCSharpTests
"UPDATE tbl SET data = json_remove(data, @name) WHERE data->>'Id' = @id", "UPDATE tbl SET data = json_remove(data, @name) WHERE data->>'Id' = @id",
"Remove field by ID query not correct"); "Remove field by ID query not correct");
}), }),
#pragma warning disable CS0618
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Sqlite.Query.RemoveFields.ByField("tbl", Field.LT("Fly", 0), Expect.equal(Sqlite.Query.RemoveFields.ByField("tbl", Field.LT("Fly", 0),
new[] { new SqliteParameter("@name0", "one"), new SqliteParameter("@name1", "two") }), new[] { new SqliteParameter("@name0", "one"), new SqliteParameter("@name1", "two") }),
"UPDATE tbl SET data = json_remove(data, @name0, @name1) WHERE data->>'Fly' < @field", "UPDATE tbl SET data = json_remove(data, @name0, @name1) WHERE data->>'Fly' < @field0",
"Remove field by field query not correct"); "Remove field by field query not correct");
}) })
#pragma warning restore CS0618
]), ]),
TestList("Delete", TestList("Delete",
[ [
@ -176,11 +188,13 @@ public static class SqliteCSharpTests
Expect.equal(Sqlite.Query.Delete.ById("tbl"), "DELETE FROM tbl WHERE data->>'Id' = @id", Expect.equal(Sqlite.Query.Delete.ById("tbl"), "DELETE FROM tbl WHERE data->>'Id' = @id",
"DELETE by ID query not correct"); "DELETE by ID query not correct");
}), }),
#pragma warning disable CS0618
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Sqlite.Query.Delete.ByField("tbl", Field.NEX("gone")), Expect.equal(Sqlite.Query.Delete.ByField("tbl", Field.NEX("gone")),
"DELETE FROM tbl WHERE data->>'gone' IS NULL", "DELETE by JSON comparison query not correct"); "DELETE FROM tbl WHERE data->>'gone' IS NULL", "DELETE by JSON comparison query not correct");
}) })
#pragma warning restore CS0618
]) ])
]), ]),
TestList("Parameters", TestList("Parameters",
@ -197,6 +211,7 @@ public static class SqliteCSharpTests
Expect.equal(theParam.ParameterName, "@test", "The parameter name is incorrect"); Expect.equal(theParam.ParameterName, "@test", "The parameter name is incorrect");
Expect.equal(theParam.Value, "{\"Nice\":\"job\"}", "The parameter value is incorrect"); Expect.equal(theParam.Value, "{\"Nice\":\"job\"}", "The parameter value is incorrect");
}), }),
#pragma warning disable CS0618
TestCase("AddField succeeds when adding a parameter", () => TestCase("AddField succeeds when adding a parameter", () =>
{ {
var paramList = Parameters.AddField("@field", Field.EQ("it", 99), []).ToList(); var paramList = Parameters.AddField("@field", Field.EQ("it", 99), []).ToList();
@ -210,6 +225,7 @@ public static class SqliteCSharpTests
var paramSeq = Parameters.AddField("@it", Field.EX("Coffee"), []); var paramSeq = Parameters.AddField("@it", Field.EX("Coffee"), []);
Expect.isEmpty(paramSeq, "There should not have been any parameters added"); Expect.isEmpty(paramSeq, "There should not have been any parameters added");
}), }),
#pragma warning restore CS0618
TestCase("None succeeds", () => TestCase("None succeeds", () =>
{ {
Expect.isEmpty(Parameters.None, "The parameter list should have been empty"); Expect.isEmpty(Parameters.None, "The parameter list should have been empty");
@ -442,6 +458,7 @@ public static class SqliteCSharpTests
var theCount = await Count.All(SqliteDb.TableName); var theCount = await Count.All(SqliteDb.TableName);
Expect.equal(theCount, 5L, "There should have been 5 matching documents"); Expect.equal(theCount, 5L, "There should have been 5 matching documents");
}), }),
#pragma warning disable CS0618
TestCase("ByField succeeds for numeric range", async () => TestCase("ByField succeeds for numeric range", async () =>
{ {
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
@ -458,6 +475,7 @@ public static class SqliteCSharpTests
var theCount = await Count.ByField(SqliteDb.TableName, Field.BT("Value", "aardvark", "apple")); var theCount = await Count.ByField(SqliteDb.TableName, Field.BT("Value", "aardvark", "apple"));
Expect.equal(theCount, 1L, "There should have been 1 matching document"); Expect.equal(theCount, 1L, "There should have been 1 matching document");
}) })
#pragma warning restore CS0618
]), ]),
TestList("Exists", TestList("Exists",
[ [
@ -480,6 +498,7 @@ public static class SqliteCSharpTests
Expect.isFalse(exists, "There should not have been an existing document"); Expect.isFalse(exists, "There should not have been an existing document");
}) })
]), ]),
#pragma warning disable CS0618
TestList("ByField", TestList("ByField",
[ [
TestCase("succeeds when documents exist", async () => TestCase("succeeds when documents exist", async () =>
@ -499,6 +518,7 @@ public static class SqliteCSharpTests
Expect.isFalse(exists, "There should not have been any existing documents"); Expect.isFalse(exists, "There should not have been any existing documents");
}) })
]) ])
#pragma warning restore CS0618
]), ]),
TestList("Find", TestList("Find",
[ [
@ -542,6 +562,7 @@ public static class SqliteCSharpTests
Expect.isNull(doc, "There should not have been a document returned"); Expect.isNull(doc, "There should not have been a document returned");
}) })
]), ]),
#pragma warning disable CS0618
TestList("ByField", TestList("ByField",
[ [
TestCase("succeeds when documents are found", async () => TestCase("succeeds when documents are found", async () =>
@ -590,6 +611,7 @@ public static class SqliteCSharpTests
Expect.isNull(doc, "There should not have been a document returned"); Expect.isNull(doc, "There should not have been a document returned");
}) })
]) ])
#pragma warning restore CS0618
]), ]),
TestList("Update", TestList("Update",
[ [
@ -676,6 +698,7 @@ public static class SqliteCSharpTests
await Patch.ById(SqliteDb.TableName, "test", new { Foo = "green" }); await Patch.ById(SqliteDb.TableName, "test", new { Foo = "green" });
}) })
]), ]),
#pragma warning disable CS0618
TestList("ByField", TestList("ByField",
[ [
TestCase("succeeds when a document is updated", async () => TestCase("succeeds when a document is updated", async () =>
@ -698,6 +721,7 @@ public static class SqliteCSharpTests
await Patch.ByField(SqliteDb.TableName, Field.EQ("Value", "burgundy"), new { Foo = "green" }); await Patch.ByField(SqliteDb.TableName, Field.EQ("Value", "burgundy"), new { Foo = "green" });
}) })
]) ])
#pragma warning restore CS0618
]), ]),
TestList("RemoveFields", TestList("RemoveFields",
[ [
@ -730,6 +754,7 @@ public static class SqliteCSharpTests
await RemoveFields.ById(SqliteDb.TableName, "two", new[] { "Value" }); await RemoveFields.ById(SqliteDb.TableName, "two", new[] { "Value" });
}) })
]), ]),
#pragma warning disable CS0618
TestList("ByField", TestList("ByField",
[ [
TestCase("succeeds when a field is removed", async () => TestCase("succeeds when a field is removed", async () =>
@ -758,6 +783,7 @@ public static class SqliteCSharpTests
await RemoveFields.ByField(SqliteDb.TableName, Field.NE("Abracadabra", "apple"), new[] { "Value" }); await RemoveFields.ByField(SqliteDb.TableName, Field.NE("Abracadabra", "apple"), new[] { "Value" });
}) })
]) ])
#pragma warning restore CS0618
]), ]),
TestList("Delete", TestList("Delete",
[ [
@ -782,6 +808,7 @@ public static class SqliteCSharpTests
Expect.equal(remaining, 5L, "There should have been 5 documents remaining"); Expect.equal(remaining, 5L, "There should have been 5 documents remaining");
}) })
]), ]),
#pragma warning disable CS0618
TestList("ByField", TestList("ByField",
[ [
TestCase("succeeds when documents are deleted", async () => TestCase("succeeds when documents are deleted", async () =>
@ -803,6 +830,7 @@ public static class SqliteCSharpTests
Expect.equal(remaining, 5L, "There should have been 5 documents remaining"); Expect.equal(remaining, 5L, "There should have been 5 documents remaining");
}) })
]) ])
#pragma warning restore CS0618
]), ]),
TestCase("Clean up database", () => Sqlite.Configuration.UseConnectionString("data source=:memory:")) TestCase("Clean up database", () => Sqlite.Configuration.UseConnectionString("data source=:memory:"))
]); ]);

View File

@ -94,7 +94,7 @@ let unitTests =
test "byField succeeds" { test "byField succeeds" {
Expect.equal Expect.equal
(Query.Count.byField "tbl" (Field.EQ "thatField" 0)) (Query.Count.byField "tbl" (Field.EQ "thatField" 0))
"SELECT COUNT(*) AS it FROM tbl WHERE data->>'thatField' = @field" "SELECT COUNT(*) AS it FROM tbl WHERE data->>'thatField' = @field0"
"JSON field text comparison count query not correct" "JSON field text comparison count query not correct"
} }
] ]
@ -108,7 +108,7 @@ let unitTests =
test "byField succeeds" { test "byField succeeds" {
Expect.equal Expect.equal
(Query.Exists.byField "tbl" (Field.LT "Test" 0)) (Query.Exists.byField "tbl" (Field.LT "Test" 0))
"SELECT EXISTS (SELECT 1 FROM tbl WHERE data->>'Test' < @field) AS it" "SELECT EXISTS (SELECT 1 FROM tbl WHERE data->>'Test' < @field0) AS it"
"JSON field text comparison exists query not correct" "JSON field text comparison exists query not correct"
} }
] ]
@ -122,7 +122,7 @@ let unitTests =
test "byField succeeds" { test "byField succeeds" {
Expect.equal Expect.equal
(Query.Find.byField "tbl" (Field.GE "Golf" 0)) (Query.Find.byField "tbl" (Field.GE "Golf" 0))
"SELECT data FROM tbl WHERE data->>'Golf' >= @field" "SELECT data FROM tbl WHERE data->>'Golf' >= @field0"
"SELECT by JSON comparison query not correct" "SELECT by JSON comparison query not correct"
} }
] ]
@ -136,7 +136,7 @@ let unitTests =
test "byField succeeds" { test "byField succeeds" {
Expect.equal Expect.equal
(Query.Patch.byField "tbl" (Field.NE "Part" 0)) (Query.Patch.byField "tbl" (Field.NE "Part" 0))
"UPDATE tbl SET data = json_patch(data, json(@data)) WHERE data->>'Part' <> @field" "UPDATE tbl SET data = json_patch(data, json(@data)) WHERE data->>'Part' <> @field0"
"UPDATE partial by JSON comparison query not correct" "UPDATE partial by JSON comparison query not correct"
} }
] ]
@ -153,7 +153,7 @@ let unitTests =
"tbl" "tbl"
(Field.GT "Fly" 0) (Field.GT "Fly" 0)
[ SqliteParameter("@name0", "one"); SqliteParameter("@name1", "two") ]) [ SqliteParameter("@name0", "one"); SqliteParameter("@name1", "two") ])
"UPDATE tbl SET data = json_remove(data, @name0, @name1) WHERE data->>'Fly' > @field" "UPDATE tbl SET data = json_remove(data, @name0, @name1) WHERE data->>'Fly' > @field0"
"Remove field by field query not correct" "Remove field by field query not correct"
} }
] ]
@ -187,7 +187,7 @@ let unitTests =
test "succeeds when adding a parameter" { test "succeeds when adding a parameter" {
let paramList = addFieldParam "@field" (Field.EQ "it" 99) [] let paramList = addFieldParam "@field" (Field.EQ "it" 99) []
Expect.hasLength paramList 1 "There should have been a parameter added" Expect.hasLength paramList 1 "There should have been a parameter added"
let theParam = paramList[0] let theParam = Seq.head paramList
Expect.equal theParam.ParameterName "@field" "The parameter name is incorrect" Expect.equal theParam.ParameterName "@field" "The parameter name is incorrect"
Expect.equal theParam.Value 99 "The parameter value is incorrect" Expect.equal theParam.Value 99 "The parameter value is incorrect"
} }