Implement Field throughout

- Do not add a parameter for EX/NEX
This commit is contained in:
Daniel J. Summers 2024-01-23 12:03:01 -05:00
parent 097208139d
commit f2836bd759
12 changed files with 237 additions and 207 deletions

View File

@ -44,35 +44,35 @@ type Field = {
Value: obj Value: obj
} with } with
/// Create an equals (=) field criteria /// Create an equals (=) field criterion
static member EQ name (value: obj) = static member EQ name (value: obj) =
{ Name = name; Op = EQ; Value = value } { Name = name; Op = EQ; Value = value }
/// Create a greater than (>) field criteria /// Create a greater than (>) field criterion
static member GT name (value: obj) = static member GT name (value: obj) =
{ Name = name; Op = GT; Value = value } { Name = name; Op = GT; Value = value }
/// Create a greater than or equal to (>=) field criteria /// Create a greater than or equal to (>=) field criterion
static member GE name (value: obj) = static member GE name (value: obj) =
{ Name = name; Op = GE; Value = value } { Name = name; Op = GE; Value = value }
/// Create a less than (<) field criteria /// Create a less than (<) field criterion
static member LT name (value: obj) = static member LT name (value: obj) =
{ Name = name; Op = LT; Value = value } { Name = name; Op = LT; Value = value }
/// Create a less than or equal to (<=) field criteria /// Create a less than or equal to (<=) field criterion
static member LE name (value: obj) = static member LE name (value: obj) =
{ Name = name; Op = LE; Value = value } { Name = name; Op = LE; Value = value }
/// Create a not equals (<>) field criteria /// Create a not equals (<>) field criterion
static member NE name (value: obj) = static member NE name (value: obj) =
{ Name = name; Op = NE; Value = value } { Name = name; Op = NE; Value = value }
/// Create an exists (IS NOT NULL) field criteria /// Create an exists (IS NOT NULL) field criterion
static member EX name = static member EX name =
{ Name = name; Op = EX; Value = obj () } { Name = name; Op = EX; Value = obj () }
/// Create an not exists (IS NULL) field criteria /// Create an not exists (IS NULL) field criterion
static member NEX name = static member NEX name =
{ Name = name; Op = NEX; Value = obj () } { Name = name; Op = NEX; Value = obj () }
@ -152,17 +152,14 @@ module Query =
/// 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">]
let whereByField fieldName op paramName = let whereByField field paramName =
let theRest = let theRest = match field.Op with EX | NEX -> string field.Op | _ -> $"{field.Op} %s{paramName}"
match op with $"data ->> '%s{field.Name}' {theRest}"
| EX | NEX -> string op
| _ -> $"{op} %s{paramName}"
$"data ->> '%s{fieldName}' {theRest}"
/// Create a WHERE clause fragment to implement an ID-based query /// Create a WHERE clause fragment to implement an ID-based query
[<CompiledName "WhereById">] [<CompiledName "WhereById">]
let whereById paramName = let whereById paramName =
whereByField (Configuration.idField ()) EQ paramName whereByField (Field.EQ (Configuration.idField ()) 0) paramName
/// Queries to define tables and indexes /// Queries to define tables and indexes
module Definition = module Definition =
@ -223,8 +220,8 @@ module Query =
/// 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">]
let byField tableName fieldName op = let byField tableName field =
$"""SELECT COUNT(*) AS it FROM %s{tableName} WHERE {whereByField fieldName op "@field"}""" $"""SELECT COUNT(*) AS it FROM %s{tableName} WHERE {whereByField field "@field"}"""
/// Queries for determining document existence /// Queries for determining document existence
module Exists = module Exists =
@ -236,8 +233,8 @@ module Query =
/// 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">]
let byField tableName fieldName op = let byField tableName field =
$"""SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE {whereByField fieldName op "@field"}) AS it""" $"""SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE {whereByField field "@field"}) AS it"""
/// Queries for retrieving documents /// Queries for retrieving documents
module Find = module Find =
@ -249,8 +246,8 @@ module Query =
/// 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">]
let byField tableName fieldName op = let byField tableName field =
$"""{selectFromTable tableName} WHERE {whereByField fieldName op "@field"}""" $"""{selectFromTable tableName} WHERE {whereByField field "@field"}"""
/// Queries to delete documents /// Queries to delete documents
module Delete = module Delete =
@ -262,5 +259,5 @@ module Query =
/// 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">]
let byField tableName fieldName op = let byField tableName field =
$"""DELETE FROM %s{tableName} WHERE {whereByField fieldName op "@field"}""" $"""DELETE FROM %s{tableName} WHERE {whereByField field "@field"}"""

View File

@ -50,8 +50,8 @@ module Extensions =
WithProps.Count.all tableName (Sql.existingConnection conn) WithProps.Count.all tableName (Sql.existingConnection conn)
/// Count matching documents using a JSON field comparison query (->> =) /// Count matching documents using a JSON field comparison query (->> =)
member conn.countByField tableName fieldName op (value: obj) = member conn.countByField tableName field =
WithProps.Count.byField tableName fieldName op value (Sql.existingConnection conn) WithProps.Count.byField tableName field (Sql.existingConnection conn)
/// 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 =
@ -66,8 +66,8 @@ module Extensions =
WithProps.Exists.byId tableName docId (Sql.existingConnection conn) WithProps.Exists.byId tableName docId (Sql.existingConnection conn)
/// Determine if documents exist using a JSON field comparison query (->> =) /// Determine if documents exist using a JSON field comparison query (->> =)
member conn.existsByField tableName fieldName op (value: obj) = member conn.existsByField tableName field =
WithProps.Exists.byField tableName fieldName op value (Sql.existingConnection conn) WithProps.Exists.byField tableName field (Sql.existingConnection conn)
/// 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 =
@ -86,8 +86,8 @@ module Extensions =
WithProps.Find.byId<'TKey, 'TDoc> tableName docId (Sql.existingConnection conn) WithProps.Find.byId<'TKey, 'TDoc> tableName docId (Sql.existingConnection conn)
/// Retrieve documents matching a JSON field comparison query (->> =) /// Retrieve documents matching a JSON field comparison query (->> =)
member conn.findByField<'TDoc> tableName fieldName op (value: obj) = member conn.findByField<'TDoc> tableName field =
WithProps.Find.byField<'TDoc> tableName fieldName op value (Sql.existingConnection conn) WithProps.Find.byField<'TDoc> tableName field (Sql.existingConnection conn)
/// 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) =
@ -98,8 +98,8 @@ module Extensions =
WithProps.Find.byJsonPath<'TDoc> tableName jsonPath (Sql.existingConnection conn) WithProps.Find.byJsonPath<'TDoc> tableName jsonPath (Sql.existingConnection conn)
/// 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
member conn.findFirstByField<'TDoc> tableName fieldName op (value: obj) = member conn.findFirstByField<'TDoc> tableName field =
WithProps.Find.firstByField<'TDoc> tableName fieldName op value (Sql.existingConnection conn) WithProps.Find.firstByField<'TDoc> tableName field (Sql.existingConnection conn)
/// 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) =
@ -122,8 +122,8 @@ module Extensions =
WithProps.Patch.byId tableName docId patch (Sql.existingConnection conn) WithProps.Patch.byId tableName docId patch (Sql.existingConnection conn)
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =) /// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
member conn.patchByField tableName fieldName op (value: obj) (patch: 'TPatch) = member conn.patchByField tableName field (patch: 'TPatch) =
WithProps.Patch.byField tableName fieldName op value patch (Sql.existingConnection conn) WithProps.Patch.byField tableName field patch (Sql.existingConnection conn)
/// 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) =
@ -138,8 +138,8 @@ module Extensions =
WithProps.Delete.byId tableName docId (Sql.existingConnection conn) WithProps.Delete.byId tableName docId (Sql.existingConnection conn)
/// Delete documents by matching a JSON field comparison query (->> =) /// Delete documents by matching a JSON field comparison query (->> =)
member conn.deleteByField tableName fieldName op (value: obj) = member conn.deleteByField tableName field =
WithProps.Delete.byField tableName fieldName op value (Sql.existingConnection conn) WithProps.Delete.byField tableName field (Sql.existingConnection conn)
/// 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) =
@ -209,8 +209,8 @@ type NpgsqlConnectionCSharpExtensions =
/// Count matching documents using a JSON field comparison query (->> =) /// Count matching documents using a JSON field comparison query (->> =)
[<Extension>] [<Extension>]
static member inline CountByField(conn, tableName, fieldName, op, value: obj) = static member inline CountByField(conn, tableName, field) =
WithProps.Count.byField tableName fieldName op value (Sql.existingConnection conn) WithProps.Count.byField tableName field (Sql.existingConnection conn)
/// Count matching documents using a JSON containment query (@>) /// Count matching documents using a JSON containment query (@>)
[<Extension>] [<Extension>]
@ -229,8 +229,8 @@ type NpgsqlConnectionCSharpExtensions =
/// Determine if documents exist using a JSON field comparison query (->> =) /// Determine if documents exist using a JSON field comparison query (->> =)
[<Extension>] [<Extension>]
static member inline ExistsByField(conn, tableName, fieldName, op, value: obj) = static member inline ExistsByField(conn, tableName, field) =
WithProps.Exists.byField tableName fieldName op value (Sql.existingConnection conn) WithProps.Exists.byField tableName field (Sql.existingConnection conn)
/// Determine if documents exist using a JSON containment query (@>) /// Determine if documents exist using a JSON containment query (@>)
[<Extension>] [<Extension>]
@ -254,8 +254,8 @@ type NpgsqlConnectionCSharpExtensions =
/// Retrieve documents matching a JSON field comparison query (->> =) /// Retrieve documents matching a JSON field comparison query (->> =)
[<Extension>] [<Extension>]
static member inline FindByField<'TDoc>(conn, tableName, fieldName, op, value: obj) = static member inline FindByField<'TDoc>(conn, tableName, field) =
WithProps.Find.ByField<'TDoc>(tableName, fieldName, op, value, Sql.existingConnection conn) WithProps.Find.ByField<'TDoc>(tableName, field, Sql.existingConnection conn)
/// Retrieve documents matching a JSON containment query (@>) /// Retrieve documents matching a JSON containment query (@>)
[<Extension>] [<Extension>]
@ -269,8 +269,8 @@ type NpgsqlConnectionCSharpExtensions =
/// 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
[<Extension>] [<Extension>]
static member inline FindFirstByField<'TDoc when 'TDoc: null>(conn, tableName, fieldName, op, value: obj) = static member inline FindFirstByField<'TDoc when 'TDoc: null>(conn, tableName, field) =
WithProps.Find.FirstByField<'TDoc>(tableName, fieldName, op, value, Sql.existingConnection conn) WithProps.Find.FirstByField<'TDoc>(tableName, field, Sql.existingConnection conn)
/// 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>]
@ -299,8 +299,8 @@ type NpgsqlConnectionCSharpExtensions =
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =) /// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
[<Extension>] [<Extension>]
static member inline PatchByField(conn, tableName, fieldName, op, value: obj, patch: 'TPatch) = static member inline PatchByField(conn, tableName, field, patch: 'TPatch) =
WithProps.Patch.byField tableName fieldName op value patch (Sql.existingConnection conn) WithProps.Patch.byField tableName field patch (Sql.existingConnection conn)
/// Patch documents using a JSON containment query in the WHERE clause (@>) /// Patch documents using a JSON containment query in the WHERE clause (@>)
[<Extension>] [<Extension>]
@ -319,8 +319,8 @@ type NpgsqlConnectionCSharpExtensions =
/// Delete documents by matching a JSON field comparison query (->> =) /// Delete documents by matching a JSON field comparison query (->> =)
[<Extension>] [<Extension>]
static member inline DeleteByField(conn, tableName, fieldName, op, value: obj) = static member inline DeleteByField(conn, tableName, field) =
WithProps.Delete.byField tableName fieldName op value (Sql.existingConnection conn) WithProps.Delete.byField tableName field (Sql.existingConnection conn)
/// Delete documents by matching a JSON containment query (@>) /// Delete documents by matching a JSON containment query (@>)
[<Extension>] [<Extension>]

View File

@ -64,9 +64,18 @@ module Parameters =
name, Sql.jsonb (Configuration.serializer().Serialize it) name, Sql.jsonb (Configuration.serializer().Serialize it)
/// Create a JSON field parameter (name "@field") /// Create a JSON field parameter (name "@field")
[<CompiledName "Field">] [<CompiledName "FSharpAddField">]
let fieldParam (value: obj) = let addFieldParam field parameters =
"@field", Sql.parameter (NpgsqlParameter("@field", value)) match field.Op with
| EX | NEX -> parameters
| _ -> ("@field", Sql.parameter (NpgsqlParameter("@field", field.Value))) :: parameters
/// Create a JSON field parameter (name "@field")
let AddField field parameters =
match field.Op with
| EX | NEX -> parameters
| _ ->
("@field", Sql.parameter (NpgsqlParameter("@field", field.Value))) |> Seq.singleton |> Seq.append parameters
/// An empty parameter sequence /// An empty parameter sequence
[<CompiledName "None">] [<CompiledName "None">]
@ -152,8 +161,8 @@ module Query =
/// Query to patch documents match a JSON field comparison (->> =) /// Query to patch documents match a JSON field comparison (->> =)
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op = let byField tableName field =
$"""UPDATE %s{tableName} SET data = data || @data WHERE {Query.whereByField fieldName op "@field"}""" $"""UPDATE %s{tableName} SET data = data || @data WHERE {Query.whereByField field "@field"}"""
/// Query to patch documents matching a JSON containment query (@>) /// Query to patch documents matching a JSON containment query (@>)
[<CompiledName "ByContains">] [<CompiledName "ByContains">]
@ -302,8 +311,8 @@ module WithProps =
/// Count matching documents using a JSON field comparison (->> =) /// Count matching documents using a JSON field comparison (->> =)
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op (value: obj) sqlProps = let byField tableName field sqlProps =
Custom.scalar (Query.Count.byField tableName fieldName op) [ fieldParam value ] toCount sqlProps Custom.scalar (Query.Count.byField tableName field) (addFieldParam field []) toCount sqlProps
/// Count matching documents using a JSON containment query (@>) /// Count matching documents using a JSON containment query (@>)
[<CompiledName "ByContains">] [<CompiledName "ByContains">]
@ -326,8 +335,8 @@ module WithProps =
/// Determine if a document exists using a JSON field comparison (->> =) /// Determine if a document exists using a JSON field comparison (->> =)
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op (value: obj) sqlProps = let byField tableName field sqlProps =
Custom.scalar (Query.Exists.byField tableName fieldName op) [ fieldParam value ] toExists sqlProps Custom.scalar (Query.Exists.byField tableName field) (addFieldParam field []) toExists sqlProps
/// Determine if a document exists using a JSON containment query (@>) /// Determine if a document exists using a JSON containment query (@>)
[<CompiledName "ByContains">] [<CompiledName "ByContains">]
@ -363,13 +372,12 @@ module WithProps =
/// Retrieve documents matching a JSON field comparison (->> =) /// Retrieve documents matching a JSON field comparison (->> =)
[<CompiledName "FSharpByField">] [<CompiledName "FSharpByField">]
let byField<'TDoc> tableName fieldName op (value: obj) sqlProps = let byField<'TDoc> tableName field sqlProps =
Custom.list<'TDoc> (Query.Find.byField tableName fieldName op) [ fieldParam value ] fromData<'TDoc> sqlProps Custom.list<'TDoc> (Query.Find.byField tableName field) (addFieldParam field []) fromData<'TDoc> sqlProps
/// Retrieve documents matching a JSON field comparison (->> =) /// Retrieve documents matching a JSON field comparison (->> =)
let ByField<'TDoc>(tableName, fieldName, op, value: obj, sqlProps) = let ByField<'TDoc>(tableName, field, sqlProps) =
Custom.List<'TDoc>( Custom.List<'TDoc>(Query.Find.byField tableName field, addFieldParam field [], fromData<'TDoc>, sqlProps)
Query.Find.byField tableName fieldName op, [ fieldParam value ], fromData<'TDoc>, sqlProps)
/// Retrieve documents matching a JSON containment query (@>) /// Retrieve documents matching a JSON containment query (@>)
[<CompiledName "FSharpByContains">] [<CompiledName "FSharpByContains">]
@ -395,14 +403,14 @@ module WithProps =
/// Retrieve the first document matching a JSON field comparison (->> =); returns None if not found /// Retrieve the first document matching a JSON field comparison (->> =); returns None if not found
[<CompiledName "FSharpFirstByField">] [<CompiledName "FSharpFirstByField">]
let firstByField<'TDoc> tableName fieldName op (value: obj) sqlProps = let firstByField<'TDoc> tableName field sqlProps =
Custom.single<'TDoc> Custom.single<'TDoc>
$"{Query.Find.byField tableName fieldName op} LIMIT 1" [ fieldParam value ] fromData<'TDoc> sqlProps $"{Query.Find.byField tableName field} LIMIT 1" (addFieldParam field []) fromData<'TDoc> sqlProps
/// Retrieve the first document matching a JSON field comparison (->> =); returns null if not found /// Retrieve the first document matching a JSON field comparison (->> =); returns null if not found
let FirstByField<'TDoc when 'TDoc: null>(tableName, fieldName, op, value: obj, sqlProps) = let FirstByField<'TDoc when 'TDoc: null>(tableName, field, sqlProps) =
Custom.Single<'TDoc>( Custom.Single<'TDoc>(
$"{Query.Find.byField tableName fieldName op} LIMIT 1", [ fieldParam value ], fromData<'TDoc>, sqlProps) $"{Query.Find.byField tableName field} LIMIT 1", addFieldParam field [], fromData<'TDoc>, sqlProps)
/// 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
[<CompiledName "FSharpFirstByContains">] [<CompiledName "FSharpFirstByContains">]
@ -461,9 +469,9 @@ module WithProps =
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =) /// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op (value: obj) (patch: 'TPatch) sqlProps = let byField tableName field (patch: 'TPatch) sqlProps =
Custom.nonQuery Custom.nonQuery
(Query.Patch.byField tableName fieldName op) [ jsonParam "@data" patch; fieldParam value ] sqlProps (Query.Patch.byField tableName field) (addFieldParam field [ jsonParam "@data" patch ]) sqlProps
/// Patch documents using a JSON containment query in the WHERE clause (@>) /// Patch documents using a JSON containment query in the WHERE clause (@>)
[<CompiledName "ByContains">] [<CompiledName "ByContains">]
@ -488,8 +496,8 @@ module WithProps =
/// Delete documents by matching a JSON field comparison query (->> =) /// Delete documents by matching a JSON field comparison query (->> =)
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op (value: obj) sqlProps = let byField tableName field sqlProps =
Custom.nonQuery (Query.Delete.byField tableName fieldName op) [ fieldParam value ] sqlProps Custom.nonQuery (Query.Delete.byField tableName field) (addFieldParam field []) sqlProps
/// Delete documents by matching a JSON contains query (@>) /// Delete documents by matching a JSON contains query (@>)
[<CompiledName "ByContains">] [<CompiledName "ByContains">]
@ -585,8 +593,8 @@ module Count =
/// Count matching documents using a JSON field comparison query (->> =) /// Count matching documents using a JSON field comparison query (->> =)
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op (value: obj) = let byField tableName field =
WithProps.Count.byField tableName fieldName op value (fromDataSource ()) WithProps.Count.byField tableName field (fromDataSource ())
/// Count matching documents using a JSON containment query (@>) /// Count matching documents using a JSON containment query (@>)
[<CompiledName "ByContains">] [<CompiledName "ByContains">]
@ -610,8 +618,8 @@ module Exists =
/// Determine if documents exist using a JSON field comparison query (->> =) /// Determine if documents exist using a JSON field comparison query (->> =)
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op (value: obj) = let byField tableName field =
WithProps.Exists.byField tableName fieldName op value (fromDataSource ()) WithProps.Exists.byField tableName field (fromDataSource ())
/// Determine if documents exist using a JSON containment query (@>) /// Determine if documents exist using a JSON containment query (@>)
[<CompiledName "ByContains">] [<CompiledName "ByContains">]
@ -648,12 +656,12 @@ module Find =
/// Retrieve documents matching a JSON field comparison query (->> =) /// Retrieve documents matching a JSON field comparison query (->> =)
[<CompiledName "FSharpByField">] [<CompiledName "FSharpByField">]
let byField<'TDoc> tableName fieldName op (value: obj) = let byField<'TDoc> tableName field =
WithProps.Find.byField<'TDoc> tableName fieldName op value (fromDataSource ()) WithProps.Find.byField<'TDoc> tableName field (fromDataSource ())
/// Retrieve documents matching a JSON field comparison query (->> =) /// Retrieve documents matching a JSON field comparison query (->> =)
let ByField<'TDoc>(tableName, fieldName, op, value: obj) = let ByField<'TDoc>(tableName, field) =
WithProps.Find.ByField<'TDoc>(tableName, fieldName, op, value, fromDataSource ()) WithProps.Find.ByField<'TDoc>(tableName, field, fromDataSource ())
/// Retrieve documents matching a JSON containment query (@>) /// Retrieve documents matching a JSON containment query (@>)
[<CompiledName "FSharpByContains">] [<CompiledName "FSharpByContains">]
@ -675,12 +683,12 @@ module Find =
/// 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
[<CompiledName "FSharpFirstByField">] [<CompiledName "FSharpFirstByField">]
let firstByField<'TDoc> tableName fieldName op (value: obj) = let firstByField<'TDoc> tableName field =
WithProps.Find.firstByField<'TDoc> tableName fieldName op value (fromDataSource ()) WithProps.Find.firstByField<'TDoc> tableName field (fromDataSource ())
/// Retrieve the first document matching a JSON field comparison query (->> =); returns null if not found /// Retrieve the first document matching a JSON field comparison query (->> =); returns null if not found
let FirstByField<'TDoc when 'TDoc: null>(tableName, fieldName, op, value: obj) = let FirstByField<'TDoc when 'TDoc: null>(tableName, field) =
WithProps.Find.FirstByField<'TDoc>(tableName, fieldName, op, value, fromDataSource ()) WithProps.Find.FirstByField<'TDoc>(tableName, field, fromDataSource ())
/// 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
[<CompiledName "FSharpFirstByContains">] [<CompiledName "FSharpFirstByContains">]
@ -731,8 +739,8 @@ module Patch =
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =) /// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op (value: obj) (patch: 'TPatch) = let byField tableName field (patch: 'TPatch) =
WithProps.Patch.byField tableName fieldName op value patch (fromDataSource ()) WithProps.Patch.byField tableName field patch (fromDataSource ())
/// Patch documents using a JSON containment query in the WHERE clause (@>) /// Patch documents using a JSON containment query in the WHERE clause (@>)
[<CompiledName "ByContains">] [<CompiledName "ByContains">]
@ -756,8 +764,8 @@ module Delete =
/// Delete documents by matching a JSON field comparison query (->> =) /// Delete documents by matching a JSON field comparison query (->> =)
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op (value: obj) = let byField tableName field =
WithProps.Delete.byField tableName fieldName op value (fromDataSource ()) WithProps.Delete.byField tableName field (fromDataSource ())
/// Delete documents by matching a JSON containment query (@>) /// Delete documents by matching a JSON containment query (@>)
[<CompiledName "ByContains">] [<CompiledName "ByContains">]

View File

@ -49,10 +49,10 @@ module Query =
/// 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">]
let byField tableName fieldName op = let byField tableName field =
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 field "@field")
/// Queries to remove a field from a document /// Queries to remove a field from a document
module RemoveField = module RemoveField =
@ -64,10 +64,8 @@ module Query =
/// Query to remove a field from a document via a comparison on a JSON field within the document /// Query to remove a field from a document via a comparison on a JSON field within the document
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op = let byField tableName field =
sprintf $"""UPDATE %s{tableName} SET data = json_remove(data, @name) WHERE {Query.whereByField field "@field"}"""
"UPDATE %s SET data = json_remove(data, @name) WHERE %s"
tableName (Query.whereByField fieldName op "@field")
/// Parameter handling helpers /// Parameter handling helpers
@ -85,9 +83,17 @@ module Parameters =
SqliteParameter(name, Configuration.serializer().Serialize it) SqliteParameter(name, Configuration.serializer().Serialize it)
/// Create a JSON field parameter (name "@field") /// Create a JSON field parameter (name "@field")
[<CompiledName "Field">] [<CompiledName "FSharpAddField">]
let fieldParam (value: obj) = let addFieldParam field parameters =
SqliteParameter("@field", value) match field.Op with
| EX | NEX -> parameters
| _ -> SqliteParameter("@field", field.Value) :: parameters
/// Create a JSON field parameter (name "@field")
let AddField field parameters =
match field.Op with
| EX | NEX -> parameters
| _ -> SqliteParameter("@field", field.Value) |> Seq.singleton |> Seq.append parameters
/// Create a JSON field name parameter (name "@name") /// Create a JSON field name parameter (name "@name")
[<CompiledName "FieldName">] [<CompiledName "FieldName">]
@ -244,7 +250,7 @@ module WithConn =
/// Count matching documents using a comparison on a JSON field /// Count matching documents using a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName field conn = let byField tableName field conn =
Custom.scalar (Query.Count.byField tableName field.Name field.Op) [ fieldParam field.Value ] toCount conn Custom.scalar (Query.Count.byField tableName field) (addFieldParam field []) toCount conn
/// Commands to determine if documents exist /// Commands to determine if documents exist
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -258,7 +264,7 @@ module WithConn =
/// 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">]
let byField tableName field conn = let byField tableName field conn =
Custom.scalar (Query.Exists.byField tableName field.Name field.Op) [ fieldParam field.Value ] toExists conn Custom.scalar (Query.Exists.byField tableName field) (addFieldParam field []) toExists conn
/// Commands to retrieve documents /// Commands to retrieve documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -285,30 +291,21 @@ module WithConn =
/// Retrieve documents via a comparison on a JSON field /// Retrieve documents via a comparison on a JSON field
[<CompiledName "FSharpByField">] [<CompiledName "FSharpByField">]
let byField<'TDoc> tableName field conn = let byField<'TDoc> tableName field conn =
Custom.list<'TDoc> Custom.list<'TDoc> (Query.Find.byField tableName field) (addFieldParam field []) fromData<'TDoc> conn
(Query.Find.byField tableName field.Name field.Op) [ fieldParam field.Value ] fromData<'TDoc> conn
/// Retrieve documents via a comparison on a JSON field /// Retrieve documents via a comparison on a JSON field
let ByField<'TDoc>(tableName, field, conn) = let ByField<'TDoc>(tableName, field, conn) =
Custom.List<'TDoc>( Custom.List<'TDoc>(Query.Find.byField tableName field, addFieldParam field [], fromData<'TDoc>, conn)
Query.Find.byField tableName field.Name field.Op, [ fieldParam field.Value ], fromData<'TDoc>, 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">]
let firstByField<'TDoc> tableName field conn = let firstByField<'TDoc> tableName field conn =
Custom.single Custom.single $"{Query.Find.byField tableName field} LIMIT 1" (addFieldParam field []) fromData<'TDoc> conn
$"{Query.Find.byField tableName field.Name field.Op} LIMIT 1"
[ fieldParam field.Value ]
fromData<'TDoc>
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) = let FirstByField<'TDoc when 'TDoc: null>(tableName, field, conn) =
Custom.Single( Custom.Single(
$"{Query.Find.byField tableName field.Name field.Op} LIMIT 1", $"{Query.Find.byField tableName field} LIMIT 1", addFieldParam field [], fromData<'TDoc>, conn)
[ fieldParam field.Value ],
fromData<'TDoc>,
conn)
/// Commands to update documents /// Commands to update documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -340,10 +337,7 @@ module WithConn =
/// 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) = let byField tableName field (patch: 'TPatch) (conn: SqliteConnection) =
Custom.nonQuery Custom.nonQuery (Query.Patch.byField tableName field) (addFieldParam field [ jsonParam "@data" patch ]) conn
(Query.Patch.byField tableName field.Name field.Op)
[ fieldParam field.Value; jsonParam "@data" patch ]
conn
/// Commands to remove fields from documents /// Commands to remove fields from documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -358,9 +352,7 @@ module WithConn =
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName field fieldName conn = let byField tableName field fieldName conn =
Custom.nonQuery Custom.nonQuery
(Query.RemoveField.byField tableName field.Name field.Op) (Query.RemoveField.byField tableName field) (addFieldParam field [ fieldNameParam fieldName ]) conn
[ fieldParam field.Value; fieldNameParam fieldName ]
conn
/// Commands to delete documents /// Commands to delete documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -374,7 +366,7 @@ module WithConn =
/// Delete documents by matching a comparison on a JSON field /// Delete documents by matching a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName field conn = let byField tableName field conn =
Custom.nonQuery (Query.Delete.byField tableName field.Name field.Op) [ fieldParam field.Value ] conn Custom.nonQuery (Query.Delete.byField tableName field) (addFieldParam field []) conn
/// Commands to execute custom SQL queries /// Commands to execute custom SQL queries

View File

@ -177,12 +177,12 @@ public static class CommonCSharpTests
{ {
TestCase("succeeds when a logical operator is passed", () => TestCase("succeeds when a logical operator is passed", () =>
{ {
Expect.equal(Query.WhereByField("theField", Op.GT, "@test"), "data ->> 'theField' > @test", Expect.equal(Query.WhereByField(Field.GT("theField", 0), "@test"), "data ->> 'theField' > @test",
"WHERE clause not correct"); "WHERE clause not correct");
}), }),
TestCase("succeeds when an existence operator is passed", () => TestCase("succeeds when an existence operator is passed", () =>
{ {
Expect.equal(Query.WhereByField("thatField", Op.NEX, ""), "data ->> 'thatField' IS NULL", Expect.equal(Query.WhereByField(Field.NEX("thatField"), ""), "data ->> 'thatField' IS NULL",
"WHERE clause not correct"); "WHERE clause not correct");
}) })
}), }),
@ -242,7 +242,7 @@ public static class CommonCSharpTests
}), }),
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Query.Count.ByField("tbl", "thatField", Op.EQ), Expect.equal(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' = @field",
"JSON field text comparison count query not correct"); "JSON field text comparison count query not correct");
}) })
@ -257,7 +257,7 @@ public static class CommonCSharpTests
}), }),
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Query.Exists.ByField("tbl", "Test", Op.LT), Expect.equal(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' < @field) AS it",
"JSON field text comparison exists query not correct"); "JSON field text comparison exists query not correct");
}) })
@ -271,7 +271,7 @@ public static class CommonCSharpTests
}), }),
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Query.Find.ByField("tbl", "Golf", Op.GE), Expect.equal(Query.Find.ByField("tbl", Field.GE("Golf", 0)),
"SELECT data FROM tbl WHERE data ->> 'Golf' >= @field", "SELECT data FROM tbl WHERE data ->> 'Golf' >= @field",
"SELECT by JSON comparison query not correct"); "SELECT by JSON comparison query not correct");
}) })
@ -285,7 +285,7 @@ public static class CommonCSharpTests
}), }),
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Query.Delete.ByField("tbl", "gone", Op.NEX), Expect.equal(Query.Delete.ByField("tbl", Field.NEX("gone")),
"DELETE FROM tbl WHERE data ->> 'gone' IS NULL", "DELETE FROM tbl WHERE data ->> 'gone' IS NULL",
"DELETE by JSON comparison query not correct"); "DELETE by JSON comparison query not correct");
}) })

View File

@ -246,7 +246,7 @@ public class PostgresCSharpExtensionTests
await using var conn = MkConn(db); await using var conn = MkConn(db);
await LoadDocs(); await LoadDocs();
var theCount = await conn.CountByField(PostgresDb.TableName, "Value", Op.EQ, "purple"); var theCount = await conn.CountByField(PostgresDb.TableName, Field.EQ("Value", "purple"));
Expect.equal(theCount, 2, "There should have been 2 matching documents"); Expect.equal(theCount, 2, "There should have been 2 matching documents");
}), }),
TestCase("CountByContains succeeds", async () => TestCase("CountByContains succeeds", async () =>
@ -296,7 +296,7 @@ public class PostgresCSharpExtensionTests
await using var conn = MkConn(db); await using var conn = MkConn(db);
await LoadDocs(); await LoadDocs();
var exists = await conn.ExistsByField(PostgresDb.TableName, "Sub", Op.EX, ""); var exists = await conn.ExistsByField(PostgresDb.TableName, Field.EX("Sub"));
Expect.isTrue(exists, "There should have been existing documents"); Expect.isTrue(exists, "There should have been existing documents");
}), }),
TestCase("succeeds when documents do not exist", async () => TestCase("succeeds when documents do not exist", async () =>
@ -305,7 +305,7 @@ public class PostgresCSharpExtensionTests
await using var conn = MkConn(db); await using var conn = MkConn(db);
await LoadDocs(); await LoadDocs();
var exists = await conn.ExistsByField(PostgresDb.TableName, "NumValue", Op.EQ, "six"); var exists = await conn.ExistsByField(PostgresDb.TableName, Field.EQ("NumValue", "six"));
Expect.isFalse(exists, "There should not have been existing documents"); Expect.isFalse(exists, "There should not have been existing documents");
}) })
}), }),
@ -403,7 +403,7 @@ public class PostgresCSharpExtensionTests
await using var conn = MkConn(db); await using var conn = MkConn(db);
await LoadDocs(); await LoadDocs();
var docs = await conn.FindByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "another"); var docs = await conn.FindByField<JsonDocument>(PostgresDb.TableName, Field.EQ("Value", "another"));
Expect.equal(docs.Count, 1, "There should have been one document returned"); Expect.equal(docs.Count, 1, "There should have been one document returned");
}), }),
TestCase("succeeds when documents are not found", async () => TestCase("succeeds when documents are not found", async () =>
@ -412,7 +412,7 @@ public class PostgresCSharpExtensionTests
await using var conn = MkConn(db); await using var conn = MkConn(db);
await LoadDocs(); await LoadDocs();
var docs = await conn.FindByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "mauve"); var docs = await conn.FindByField<JsonDocument>(PostgresDb.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");
}) })
}), }),
@ -467,7 +467,7 @@ public class PostgresCSharpExtensionTests
await using var conn = MkConn(db); await using var conn = MkConn(db);
await LoadDocs(); await LoadDocs();
var doc = await conn.FindFirstByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "another"); var doc = await conn.FindFirstByField<JsonDocument>(PostgresDb.TableName, Field.EQ("Value", "another"));
Expect.isNotNull(doc, "There should have been a document returned"); Expect.isNotNull(doc, "There should have been a document returned");
Expect.equal(doc.Id, "two", "The incorrect document was returned"); Expect.equal(doc.Id, "two", "The incorrect document was returned");
}), }),
@ -477,7 +477,7 @@ public class PostgresCSharpExtensionTests
await using var conn = MkConn(db); await using var conn = MkConn(db);
await LoadDocs(); await LoadDocs();
var doc = await conn.FindFirstByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "purple"); var doc = await conn.FindFirstByField<JsonDocument>(PostgresDb.TableName, Field.EQ("Value", "purple"));
Expect.isNotNull(doc, "There should have been a document returned"); Expect.isNotNull(doc, "There should have been a document returned");
Expect.contains(new[] { "five", "four" }, doc.Id, "An incorrect document was returned"); Expect.contains(new[] { "five", "four" }, doc.Id, "An incorrect document was returned");
}), }),
@ -487,7 +487,7 @@ public class PostgresCSharpExtensionTests
await using var conn = MkConn(db); await using var conn = MkConn(db);
await LoadDocs(); await LoadDocs();
var doc = await conn.FindFirstByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "absent"); var doc = await conn.FindFirstByField<JsonDocument>(PostgresDb.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");
}) })
}), }),
@ -650,8 +650,8 @@ public class PostgresCSharpExtensionTests
await using var conn = MkConn(db); await using var conn = MkConn(db);
await LoadDocs(); await LoadDocs();
await conn.PatchByField(PostgresDb.TableName, "Value", Op.EQ, "purple", new { NumValue = 77 }); await conn.PatchByField(PostgresDb.TableName, Field.EQ("Value", "purple"), new { NumValue = 77 });
var after = await conn.CountByField(PostgresDb.TableName, "NumValue", Op.EQ, "77"); var after = await conn.CountByField(PostgresDb.TableName, Field.EQ("NumValue", "77"));
Expect.equal(after, 2, "There should have been 2 documents returned"); Expect.equal(after, 2, "There should have been 2 documents returned");
}), }),
TestCase("succeeds when no document is updated", async () => TestCase("succeeds when no document is updated", async () =>
@ -662,7 +662,7 @@ public class PostgresCSharpExtensionTests
Expect.equal(before, 0, "There should have been no documents returned"); Expect.equal(before, 0, "There should have been no documents returned");
// This not raising an exception is the test // This not raising an exception is the test
await conn.PatchByField(PostgresDb.TableName, "Value", Op.EQ, "burgundy", new { Foo = "green" }); await conn.PatchByField(PostgresDb.TableName, Field.EQ("Value", "burgundy"), new { Foo = "green" });
}) })
}), }),
TestList("PatchByContains", new[] TestList("PatchByContains", new[]
@ -742,7 +742,7 @@ public class PostgresCSharpExtensionTests
await using var conn = MkConn(db); await using var conn = MkConn(db);
await LoadDocs(); await LoadDocs();
await conn.DeleteByField(PostgresDb.TableName, "Value", Op.NE, "purple"); await conn.DeleteByField(PostgresDb.TableName, Field.NE("Value", "purple"));
var remaining = await conn.CountAll(PostgresDb.TableName); var remaining = await conn.CountAll(PostgresDb.TableName);
Expect.equal(remaining, 2, "There should have been 2 documents remaining"); Expect.equal(remaining, 2, "There should have been 2 documents remaining");
}), }),
@ -752,7 +752,7 @@ public class PostgresCSharpExtensionTests
await using var conn = MkConn(db); await using var conn = MkConn(db);
await LoadDocs(); await LoadDocs();
await conn.DeleteByField(PostgresDb.TableName, "Value", Op.EQ, "crimson"); await conn.DeleteByField(PostgresDb.TableName, Field.EQ("Value", "crimson"));
var remaining = await conn.CountAll(PostgresDb.TableName); var remaining = await conn.CountAll(PostgresDb.TableName);
Expect.equal(remaining, 5, "There should have been 5 documents remaining"); Expect.equal(remaining, 5, "There should have been 5 documents remaining");
}) })

View File

@ -32,11 +32,21 @@ public class PostgresCSharpTests
Expect.equal(it.Item1, "@test", "JSON parameter not constructed correctly"); Expect.equal(it.Item1, "@test", "JSON parameter not constructed correctly");
Expect.equal(it.Item2, Sql.jsonb("{\"Something\":\"good\"}"), "JSON parameter value incorrect"); Expect.equal(it.Item2, Sql.jsonb("{\"Something\":\"good\"}"), "JSON parameter value incorrect");
}), }),
TestCase("Field succeeds", () => TestList("AddField", new []
{ {
var it = Parameters.Field(242); TestCase("succeeds when a parameter is added", () =>
Expect.equal(it.Item1, "@field", "Field parameter not constructed correctly"); {
Expect.isTrue(it.Item2.IsParameter, "Field parameter value incorrect"); var it = Parameters.AddField(Field.EQ("it", "242"), Enumerable.Empty<Tuple<string, SqlValue>>())
.ToList();
Expect.hasLength(it, 1, "There should have been a parameter added");
Expect.equal(it[0].Item1, "@field", "Field parameter not constructed correctly");
Expect.isTrue(it[0].Item2.IsParameter, "Field parameter value incorrect");
}),
TestCase("succeeds when a parameter is not added", () =>
{
var it = Parameters.AddField(Field.EX("It"), Enumerable.Empty<Tuple<string, SqlValue>>());
Expect.isEmpty(it, "There should not have been any parameters added");
})
}), }),
TestCase("None succeeds", () => TestCase("None succeeds", () =>
{ {
@ -134,7 +144,7 @@ public class PostgresCSharpTests
}), }),
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Postgres.Query.Patch.ByField(PostgresDb.TableName, "Snail", Op.LT), Expect.equal(Postgres.Query.Patch.ByField(PostgresDb.TableName, Field.LT("Snail", 0)),
$"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data ->> 'Snail' < @field", $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data ->> 'Snail' < @field",
"UPDATE partial by ID statement not correct"); "UPDATE partial by ID statement not correct");
}), }),
@ -431,7 +441,7 @@ public class PostgresCSharpTests
await using var db = PostgresDb.BuildDb(); await using var db = PostgresDb.BuildDb();
await LoadDocs(); await LoadDocs();
var theCount = await Count.ByField(PostgresDb.TableName, "Value", Op.EQ, "purple"); var theCount = await Count.ByField(PostgresDb.TableName, Field.EQ("Value", "purple"));
Expect.equal(theCount, 2, "There should have been 2 matching documents"); Expect.equal(theCount, 2, "There should have been 2 matching documents");
}), }),
TestCase("ByContains succeeds", async () => TestCase("ByContains succeeds", async () =>
@ -479,7 +489,7 @@ public class PostgresCSharpTests
await using var db = PostgresDb.BuildDb(); await using var db = PostgresDb.BuildDb();
await LoadDocs(); await LoadDocs();
var exists = await Exists.ByField(PostgresDb.TableName, "Sub", Op.NEX, ""); var exists = await Exists.ByField(PostgresDb.TableName, Field.NEX("Sub"));
Expect.isTrue(exists, "There should have been existing documents"); Expect.isTrue(exists, "There should have been existing documents");
}), }),
TestCase("succeeds when documents do not exist", async () => TestCase("succeeds when documents do not exist", async () =>
@ -487,7 +497,7 @@ public class PostgresCSharpTests
await using var db = PostgresDb.BuildDb(); await using var db = PostgresDb.BuildDb();
await LoadDocs(); await LoadDocs();
var exists = await Exists.ByField(PostgresDb.TableName, "NumValue", Op.EQ, "six"); var exists = await Exists.ByField(PostgresDb.TableName, Field.EQ("NumValue", "six"));
Expect.isFalse(exists, "There should not have been existing documents"); Expect.isFalse(exists, "There should not have been existing documents");
}) })
}), }),
@ -578,7 +588,7 @@ public class PostgresCSharpTests
await using var db = PostgresDb.BuildDb(); await using var db = PostgresDb.BuildDb();
await LoadDocs(); await LoadDocs();
var docs = await Find.ByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "another"); var docs = await Find.ByField<JsonDocument>(PostgresDb.TableName, Field.EQ("Value", "another"));
Expect.equal(docs.Count, 1, "There should have been one document returned"); Expect.equal(docs.Count, 1, "There should have been one document returned");
}), }),
TestCase("succeeds when documents are not found", async () => TestCase("succeeds when documents are not found", async () =>
@ -586,7 +596,7 @@ public class PostgresCSharpTests
await using var db = PostgresDb.BuildDb(); await using var db = PostgresDb.BuildDb();
await LoadDocs(); await LoadDocs();
var docs = await Find.ByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "mauve"); var docs = await Find.ByField<JsonDocument>(PostgresDb.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");
}) })
}), }),
@ -636,7 +646,7 @@ public class PostgresCSharpTests
await using var db = PostgresDb.BuildDb(); await using var db = PostgresDb.BuildDb();
await LoadDocs(); await LoadDocs();
var doc = await Find.FirstByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "another"); var doc = await Find.FirstByField<JsonDocument>(PostgresDb.TableName, Field.EQ("Value", "another"));
Expect.isNotNull(doc, "There should have been a document returned"); Expect.isNotNull(doc, "There should have been a document returned");
Expect.equal(doc.Id, "two", "The incorrect document was returned"); Expect.equal(doc.Id, "two", "The incorrect document was returned");
}), }),
@ -645,7 +655,7 @@ public class PostgresCSharpTests
await using var db = PostgresDb.BuildDb(); await using var db = PostgresDb.BuildDb();
await LoadDocs(); await LoadDocs();
var doc = await Find.FirstByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "purple"); var doc = await Find.FirstByField<JsonDocument>(PostgresDb.TableName, Field.EQ("Value", "purple"));
Expect.isNotNull(doc, "There should have been a document returned"); Expect.isNotNull(doc, "There should have been a document returned");
Expect.contains(new[] { "five", "four" }, doc.Id, "An incorrect document was returned"); Expect.contains(new[] { "five", "four" }, doc.Id, "An incorrect document was returned");
}), }),
@ -654,7 +664,7 @@ public class PostgresCSharpTests
await using var db = PostgresDb.BuildDb(); await using var db = PostgresDb.BuildDb();
await LoadDocs(); await LoadDocs();
var doc = await Find.FirstByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "absent"); var doc = await Find.FirstByField<JsonDocument>(PostgresDb.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");
}) })
}), }),
@ -813,8 +823,8 @@ public class PostgresCSharpTests
await using var db = PostgresDb.BuildDb(); await using var db = PostgresDb.BuildDb();
await LoadDocs(); await LoadDocs();
await Patch.ByField(PostgresDb.TableName, "Value", Op.EQ, "purple", new { NumValue = 77 }); await Patch.ByField(PostgresDb.TableName, Field.EQ("Value", "purple"), new { NumValue = 77 });
var after = await Count.ByField(PostgresDb.TableName, "NumValue", Op.EQ, "77"); var after = await Count.ByField(PostgresDb.TableName, Field.EQ("NumValue", "77"));
Expect.equal(after, 2, "There should have been 2 documents returned"); Expect.equal(after, 2, "There should have been 2 documents returned");
}), }),
TestCase("succeeds when no document is updated", async () => TestCase("succeeds when no document is updated", async () =>
@ -825,7 +835,7 @@ public class PostgresCSharpTests
Expect.equal(before, 0, "There should have been no documents returned"); Expect.equal(before, 0, "There should have been no documents returned");
// This not raising an exception is the test // This not raising an exception is the test
await Patch.ByField(PostgresDb.TableName, "Value", Op.EQ, "burgundy", new { Foo = "green" }); await Patch.ByField(PostgresDb.TableName, Field.EQ("Value", "burgundy"), new { Foo = "green" });
}) })
}), }),
TestList("ByContains", new[] TestList("ByContains", new[]
@ -903,7 +913,7 @@ public class PostgresCSharpTests
await using var db = PostgresDb.BuildDb(); await using var db = PostgresDb.BuildDb();
await LoadDocs(); await LoadDocs();
await Delete.ByField(PostgresDb.TableName, "Value", Op.EQ, "purple"); await Delete.ByField(PostgresDb.TableName, Field.EQ("Value", "purple"));
var remaining = await Count.All(PostgresDb.TableName); var remaining = await Count.All(PostgresDb.TableName);
Expect.equal(remaining, 3, "There should have been 3 documents remaining"); Expect.equal(remaining, 3, "There should have been 3 documents remaining");
}), }),
@ -912,7 +922,7 @@ public class PostgresCSharpTests
await using var db = PostgresDb.BuildDb(); await using var db = PostgresDb.BuildDb();
await LoadDocs(); await LoadDocs();
await Delete.ByField(PostgresDb.TableName, "Value", Op.EQ, "crimson"); await Delete.ByField(PostgresDb.TableName, Field.EQ("Value", "crimson"));
var remaining = await Count.All(PostgresDb.TableName); var remaining = await Count.All(PostgresDb.TableName);
Expect.equal(remaining, 5, "There should have been 5 documents remaining"); Expect.equal(remaining, 5, "There should have been 5 documents remaining");
}) })

View File

@ -36,7 +36,7 @@ public static class SqliteCSharpTests
}), }),
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Sqlite.Query.Patch.ByField("tbl", "Part", Op.NE), 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' <> @field",
"UPDATE partial by JSON comparison query not correct"); "UPDATE partial by JSON comparison query not correct");
}) })
@ -51,7 +51,7 @@ public static class SqliteCSharpTests
}), }),
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {
Expect.equal(Sqlite.Query.RemoveField.ByField("tbl", "Fly", Op.LT), Expect.equal(Sqlite.Query.RemoveField.ByField("tbl", Field.LT("Fly", 0)),
"UPDATE tbl SET data = json_remove(data, @name) WHERE data ->> 'Fly' < @field", "UPDATE tbl SET data = json_remove(data, @name) WHERE data ->> 'Fly' < @field",
"Remove field by field query not correct"); "Remove field by field query not correct");
}) })
@ -71,12 +71,19 @@ 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");
}), }),
TestCase("Field succeeds", () => TestCase("AddField succeeds when adding a parameter", () =>
{ {
var theParam = Parameters.Field(99); var paramList = Parameters.AddField(Field.EQ("it", 99), Enumerable.Empty<SqliteParameter>()).ToList();
Expect.hasLength(paramList, 1, "There should have been a parameter added");
var theParam = paramList[0];
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");
}), }),
TestCase("AddField succeeds when not adding a parameter", () =>
{
var paramSeq = Parameters.AddField(Field.EX("Coffee"), Enumerable.Empty<SqliteParameter>());
Expect.isEmpty(paramSeq, "There should not have been any parameters added");
}),
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");

View File

@ -45,13 +45,13 @@ let all =
testList "whereByField" [ testList "whereByField" [
test "succeeds when a logical operator is passed" { test "succeeds when a logical operator is passed" {
Expect.equal Expect.equal
(Query.whereByField "theField" GT "@test") (Query.whereByField (Field.GT "theField" 0) "@test")
"data ->> 'theField' > @test" "data ->> 'theField' > @test"
"WHERE clause not correct" "WHERE clause not correct"
} }
test "succeeds when an existence operator is passed" { test "succeeds when an existence operator is passed" {
Expect.equal Expect.equal
(Query.whereByField "thatField" NEX "") (Query.whereByField (Field.NEX "thatField") "")
"data ->> 'thatField' IS NULL" "data ->> 'thatField' IS NULL"
"WHERE clause not correct" "WHERE clause not correct"
} }
@ -107,7 +107,7 @@ let all =
} }
test "byField succeeds" { test "byField succeeds" {
Expect.equal Expect.equal
(Query.Count.byField tbl "thatField" EQ) (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' = @field"
"JSON field text comparison count query not correct" "JSON field text comparison count query not correct"
} }
@ -121,7 +121,7 @@ let all =
} }
test "byField succeeds" { test "byField succeeds" {
Expect.equal Expect.equal
(Query.Exists.byField tbl "Test" LT) (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' < @field) AS it"
"JSON field text comparison exists query not correct" "JSON field text comparison exists query not correct"
} }
@ -135,7 +135,7 @@ let all =
} }
test "byField succeeds" { test "byField succeeds" {
Expect.equal Expect.equal
(Query.Find.byField tbl "Golf" GE) (Query.Find.byField tbl (Field.GE "Golf" 0))
$"SELECT data FROM {tbl} WHERE data ->> 'Golf' >= @field" $"SELECT data FROM {tbl} WHERE data ->> 'Golf' >= @field"
"SELECT by JSON comparison query not correct" "SELECT by JSON comparison query not correct"
} }
@ -149,7 +149,7 @@ let all =
} }
test "byField succeeds" { test "byField succeeds" {
Expect.equal Expect.equal
(Query.Delete.byField tbl "gone" NEX) (Query.Delete.byField tbl (Field.NEX "gone"))
$"DELETE FROM {tbl} WHERE data ->> 'gone' IS NULL" $"DELETE FROM {tbl} WHERE data ->> 'gone' IS NULL"
"DELETE by JSON comparison query not correct" "DELETE by JSON comparison query not correct"
} }

View File

@ -214,7 +214,7 @@ let integrationTests =
use conn = mkConn db use conn = mkConn db
do! loadDocs conn do! loadDocs conn
let! theCount = conn.countByField PostgresDb.TableName "Value" EQ "purple" let! theCount = conn.countByField PostgresDb.TableName (Field.EQ "Value" "purple")
Expect.equal theCount 2 "There should have been 2 matching documents" Expect.equal theCount 2 "There should have been 2 matching documents"
} }
testTask "countByContains succeeds" { testTask "countByContains succeeds" {
@ -257,7 +257,7 @@ let integrationTests =
use conn = mkConn db use conn = mkConn db
do! loadDocs conn do! loadDocs conn
let! exists = conn.existsByField PostgresDb.TableName "Sub" EX "" let! exists = conn.existsByField PostgresDb.TableName (Field.EX "Sub")
Expect.isTrue exists "There should have been existing documents" Expect.isTrue exists "There should have been existing documents"
} }
testTask "succeeds when documents do not exist" { testTask "succeeds when documents do not exist" {
@ -265,7 +265,7 @@ let integrationTests =
use conn = mkConn db use conn = mkConn db
do! loadDocs conn do! loadDocs conn
let! exists = conn.existsByField PostgresDb.TableName "NumValue" EQ "six" let! exists = conn.existsByField PostgresDb.TableName (Field.EQ "NumValue" "six")
Expect.isFalse exists "There should not have been existing documents" Expect.isFalse exists "There should not have been existing documents"
} }
] ]
@ -354,7 +354,7 @@ let integrationTests =
use conn = mkConn db use conn = mkConn db
do! loadDocs conn do! loadDocs conn
let! docs = conn.findByField<JsonDocument> PostgresDb.TableName "Value" EQ "another" let! docs = conn.findByField<JsonDocument> PostgresDb.TableName (Field.EQ "Value" "another")
Expect.equal (List.length docs) 1 "There should have been one document returned" Expect.equal (List.length docs) 1 "There should have been one document returned"
} }
testTask "succeeds when documents are not found" { testTask "succeeds when documents are not found" {
@ -362,7 +362,7 @@ let integrationTests =
use conn = mkConn db use conn = mkConn db
do! loadDocs conn do! loadDocs conn
let! docs = conn.findByField<JsonDocument> PostgresDb.TableName "Value" EQ "mauve" let! docs = conn.findByField<JsonDocument> PostgresDb.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"
} }
] ]
@ -408,7 +408,7 @@ let integrationTests =
use conn = mkConn db use conn = mkConn db
do! loadDocs conn do! loadDocs conn
let! doc = conn.findFirstByField<JsonDocument> PostgresDb.TableName "Value" EQ "another" let! doc = conn.findFirstByField<JsonDocument> PostgresDb.TableName (Field.EQ "Value" "another")
Expect.isSome doc "There should have been a document returned" Expect.isSome doc "There should have been a document returned"
Expect.equal doc.Value.Id "two" "The incorrect document was returned" Expect.equal doc.Value.Id "two" "The incorrect document was returned"
} }
@ -417,7 +417,7 @@ let integrationTests =
use conn = mkConn db use conn = mkConn db
do! loadDocs conn do! loadDocs conn
let! doc = conn.findFirstByField<JsonDocument> PostgresDb.TableName "Value" EQ "purple" let! doc = conn.findFirstByField<JsonDocument> PostgresDb.TableName (Field.EQ "Value" "purple")
Expect.isSome doc "There should have been a document returned" Expect.isSome doc "There should have been a document returned"
Expect.contains [ "five"; "four" ] doc.Value.Id "An incorrect document was returned" Expect.contains [ "five"; "four" ] doc.Value.Id "An incorrect document was returned"
} }
@ -426,7 +426,7 @@ let integrationTests =
use conn = mkConn db use conn = mkConn db
do! loadDocs conn do! loadDocs conn
let! doc = conn.findFirstByField<JsonDocument> PostgresDb.TableName "Value" EQ "absent" let! doc = conn.findFirstByField<JsonDocument> PostgresDb.TableName (Field.EQ "Value" "absent")
Expect.isNone doc "There should not have been a document returned" Expect.isNone doc "There should not have been a document returned"
} }
] ]
@ -562,8 +562,8 @@ let integrationTests =
use conn = mkConn db use conn = mkConn db
do! loadDocs conn do! loadDocs conn
do! conn.patchByField PostgresDb.TableName "Value" EQ "purple" {| NumValue = 77 |} do! conn.patchByField PostgresDb.TableName (Field.EQ "Value" "purple") {| NumValue = 77 |}
let! after = conn.countByField PostgresDb.TableName "NumValue" EQ "77" let! after = conn.countByField PostgresDb.TableName (Field.EQ "NumValue" "77")
Expect.equal after 2 "There should have been 2 documents returned" Expect.equal after 2 "There should have been 2 documents returned"
} }
testTask "succeeds when no document is updated" { testTask "succeeds when no document is updated" {
@ -573,7 +573,7 @@ let integrationTests =
Expect.equal before 0 "There should have been no documents returned" Expect.equal before 0 "There should have been no documents returned"
// This not raising an exception is the test // This not raising an exception is the test
do! conn.patchByField PostgresDb.TableName "Value" EQ "burgundy" {| Foo = "green" |} do! conn.patchByField PostgresDb.TableName (Field.EQ "Value" "burgundy") {| Foo = "green" |}
} }
] ]
testList "patchByContains" [ testList "patchByContains" [
@ -642,7 +642,7 @@ let integrationTests =
use conn = mkConn db use conn = mkConn db
do! loadDocs conn do! loadDocs conn
do! conn.deleteByField PostgresDb.TableName "Value" EQ "purple" do! conn.deleteByField PostgresDb.TableName (Field.EQ "Value" "purple")
let! remaining = conn.countAll PostgresDb.TableName let! remaining = conn.countAll PostgresDb.TableName
Expect.equal remaining 3 "There should have been 3 documents remaining" Expect.equal remaining 3 "There should have been 3 documents remaining"
} }
@ -651,7 +651,7 @@ let integrationTests =
use conn = mkConn db use conn = mkConn db
do! loadDocs conn do! loadDocs conn
do! conn.deleteByField PostgresDb.TableName "Value" EQ "crimson" do! conn.deleteByField PostgresDb.TableName (Field.EQ "Value" "crimson")
let! remaining = conn.countAll PostgresDb.TableName let! remaining = conn.countAll PostgresDb.TableName
Expect.equal remaining 5 "There should have been 5 documents remaining" Expect.equal remaining 5 "There should have been 5 documents remaining"
} }

View File

@ -18,15 +18,23 @@ let unitTests =
("@test", Sql.jsonb """{"Something":"good"}""") ("@test", Sql.jsonb """{"Something":"good"}""")
"JSON parameter not constructed correctly" "JSON parameter not constructed correctly"
} }
test "fieldParam succeeds" { testList "addFieldParam" [
let it = fieldParam 242 test "succeeds when a parameter is added" {
let paramList = addFieldParam (Field.EQ "it" "242") []
Expect.hasLength paramList 1 "There should have been a parameter added"
let it = paramList[0]
Expect.equal (fst it) "@field" "Field parameter name not correct" Expect.equal (fst it) "@field" "Field parameter name not correct"
match snd it with match snd it with
| SqlValue.Parameter value -> | SqlValue.Parameter value ->
Expect.equal value.ParameterName "@field" "Parameter name not correct" Expect.equal value.ParameterName "@field" "Parameter name not correct"
Expect.equal value.Value 242 "Parameter value not correct" Expect.equal value.Value "242" "Parameter value not correct"
| _ -> Expect.isTrue false "The parameter was not a Parameter type" | _ -> Expect.isTrue false "The parameter was not a Parameter type"
} }
test "succeeds when a parameter is not added" {
let paramList = addFieldParam (Field.EX "tacos") []
Expect.isEmpty paramList "There should not have been any parameters added"
}
]
test "noParams succeeds" { test "noParams succeeds" {
Expect.isEmpty noParams "The no-params sequence should be empty" Expect.isEmpty noParams "The no-params sequence should be empty"
} }
@ -110,7 +118,7 @@ let unitTests =
} }
test "byField succeeds" { test "byField succeeds" {
Expect.equal Expect.equal
(Query.Patch.byField PostgresDb.TableName "Snail" LT) (Query.Patch.byField PostgresDb.TableName (Field.LT "Snail" 0))
$"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data ->> 'Snail' < @field" $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data ->> 'Snail' < @field"
"UPDATE partial by ID statement not correct" "UPDATE partial by ID statement not correct"
} }
@ -357,7 +365,7 @@ let integrationTests =
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
let! theCount = Count.byField PostgresDb.TableName "Value" EQ "purple" let! theCount = Count.byField PostgresDb.TableName (Field.EQ "Value" "purple")
Expect.equal theCount 2 "There should have been 2 matching documents" Expect.equal theCount 2 "There should have been 2 matching documents"
} }
testTask "byContains succeeds" { testTask "byContains succeeds" {
@ -397,14 +405,14 @@ let integrationTests =
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
let! exists = Exists.byField PostgresDb.TableName "Sub" EX "" let! exists = Exists.byField PostgresDb.TableName (Field.EX "Sub")
Expect.isTrue exists "There should have been existing documents" Expect.isTrue exists "There should have been existing documents"
} }
testTask "succeeds when documents do not exist" { testTask "succeeds when documents do not exist" {
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
let! exists = Exists.byField PostgresDb.TableName "NumValue" EQ "six" let! exists = Exists.byField PostgresDb.TableName (Field.EQ "NumValue" "six")
Expect.isFalse exists "There should not have been existing documents" Expect.isFalse exists "There should not have been existing documents"
} }
] ]
@ -486,14 +494,14 @@ let integrationTests =
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
let! docs = Find.byField<JsonDocument> PostgresDb.TableName "Value" EQ "another" let! docs = Find.byField<JsonDocument> PostgresDb.TableName (Field.EQ "Value" "another")
Expect.equal (List.length docs) 1 "There should have been one document returned" Expect.equal (List.length docs) 1 "There should have been one document returned"
} }
testTask "succeeds when documents are not found" { testTask "succeeds when documents are not found" {
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
let! docs = Find.byField<JsonDocument> PostgresDb.TableName "Value" EQ "mauve" let! docs = Find.byField<JsonDocument> PostgresDb.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"
} }
] ]
@ -534,7 +542,7 @@ let integrationTests =
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
let! doc = Find.firstByField<JsonDocument> PostgresDb.TableName "Value" EQ "another" let! doc = Find.firstByField<JsonDocument> PostgresDb.TableName (Field.EQ "Value" "another")
Expect.isSome doc "There should have been a document returned" Expect.isSome doc "There should have been a document returned"
Expect.equal doc.Value.Id "two" "The incorrect document was returned" Expect.equal doc.Value.Id "two" "The incorrect document was returned"
} }
@ -542,7 +550,7 @@ let integrationTests =
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
let! doc = Find.firstByField<JsonDocument> PostgresDb.TableName "Value" EQ "purple" let! doc = Find.firstByField<JsonDocument> PostgresDb.TableName (Field.EQ "Value" "purple")
Expect.isSome doc "There should have been a document returned" Expect.isSome doc "There should have been a document returned"
Expect.contains [ "five"; "four" ] doc.Value.Id "An incorrect document was returned" Expect.contains [ "five"; "four" ] doc.Value.Id "An incorrect document was returned"
} }
@ -550,7 +558,7 @@ let integrationTests =
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
let! doc = Find.firstByField<JsonDocument> PostgresDb.TableName "Value" EQ "absent" let! doc = Find.firstByField<JsonDocument> PostgresDb.TableName (Field.EQ "Value" "absent")
Expect.isNone doc "There should not have been a document returned" Expect.isNone doc "There should not have been a document returned"
} }
] ]
@ -682,8 +690,8 @@ let integrationTests =
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
do! Patch.byField PostgresDb.TableName "Value" EQ "purple" {| NumValue = 77 |} do! Patch.byField PostgresDb.TableName (Field.EQ "Value" "purple") {| NumValue = 77 |}
let! after = Count.byField PostgresDb.TableName "NumValue" EQ "77" let! after = Count.byField PostgresDb.TableName (Field.EQ "NumValue" "77")
Expect.equal after 2 "There should have been 2 documents returned" Expect.equal after 2 "There should have been 2 documents returned"
} }
testTask "succeeds when no document is updated" { testTask "succeeds when no document is updated" {
@ -693,7 +701,7 @@ let integrationTests =
Expect.equal before 0 "There should have been no documents returned" Expect.equal before 0 "There should have been no documents returned"
// This not raising an exception is the test // This not raising an exception is the test
do! Patch.byField PostgresDb.TableName "Value" EQ "burgundy" {| Foo = "green" |} do! Patch.byField PostgresDb.TableName (Field.EQ "Value" "burgundy") {| Foo = "green" |}
} }
] ]
testList "byContains" [ testList "byContains" [
@ -759,7 +767,7 @@ let integrationTests =
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
do! Delete.byField PostgresDb.TableName "Value" EQ "purple" do! Delete.byField PostgresDb.TableName (Field.EQ "Value" "purple")
let! remaining = Count.all PostgresDb.TableName let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 3 "There should have been 3 documents remaining" Expect.equal remaining 3 "There should have been 3 documents remaining"
} }
@ -767,7 +775,7 @@ let integrationTests =
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
do! loadDocs () do! loadDocs ()
do! Delete.byField PostgresDb.TableName "Value" EQ "crimson" do! Delete.byField PostgresDb.TableName (Field.EQ "Value" "crimson")
let! remaining = Count.all PostgresDb.TableName let! remaining = Count.all PostgresDb.TableName
Expect.equal remaining 5 "There should have been 5 documents remaining" Expect.equal remaining 5 "There should have been 5 documents remaining"
} }

View File

@ -27,7 +27,7 @@ let unitTests =
} }
test "byField succeeds" { test "byField succeeds" {
Expect.equal Expect.equal
(Query.Patch.byField "tbl" "Part" NE) (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' <> @field"
"UPDATE partial by JSON comparison query not correct" "UPDATE partial by JSON comparison query not correct"
} }
@ -41,7 +41,7 @@ let unitTests =
} }
test "byField succeeds" { test "byField succeeds" {
Expect.equal Expect.equal
(Query.RemoveField.byField "tbl" "Fly" GT) (Query.RemoveField.byField "tbl" (Field.GT "Fly" 0))
"UPDATE tbl SET data = json_remove(data, @name) WHERE data ->> 'Fly' > @field" "UPDATE tbl SET data = json_remove(data, @name) WHERE data ->> 'Fly' > @field"
"Remove field by field query not correct" "Remove field by field query not correct"
} }
@ -58,11 +58,19 @@ let unitTests =
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"
} }
test "fieldParam succeeds" { testList "addFieldParam" [
let theParam = fieldParam 99 test "succeeds when adding a parameter" {
let paramList = addFieldParam (Field.EQ "it" 99) []
Expect.hasLength paramList 1 "There should have been a parameter added"
let theParam = paramList[0]
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"
} }
test "succeeds when not adding a parameter" {
let paramList = addFieldParam (Field.NEX "Coffee") []
Expect.isEmpty paramList "There should not have been any parameters added"
}
]
test "noParams succeeds" { test "noParams succeeds" {
Expect.isEmpty noParams "The parameter list should have been empty" Expect.isEmpty noParams "The parameter list should have been empty"
} }