diff --git a/src/Postgres/Extensions.fs b/src/Postgres/Extensions.fs index f6ba32e..8e1c7a3 100644 --- a/src/Postgres/Extensions.fs +++ b/src/Postgres/Extensions.fs @@ -260,7 +260,7 @@ type NpgsqlConnectionCSharpExtensions = /// Count matching documents using a JSON field comparison query (->> =) [] static member inline CountByFields(conn, tableName, howMatched, fields) = - WithProps.Count.ByFields(tableName, howMatched, fields, Sql.existingConnection conn) + WithProps.Count.byFields tableName howMatched fields (Sql.existingConnection conn) /// Count matching documents using a JSON field comparison query (->> =) [] @@ -286,7 +286,7 @@ type NpgsqlConnectionCSharpExtensions = /// Determine if documents exist using a JSON field comparison query (->> =) [] static member inline ExistsByFields(conn, tableName, howMatched, fields) = - WithProps.Exists.ByFields(tableName, howMatched, fields, Sql.existingConnection conn) + WithProps.Exists.byFields tableName howMatched fields (Sql.existingConnection conn) /// Determine if documents exist using a JSON field comparison query (->> =) [] @@ -374,7 +374,7 @@ type NpgsqlConnectionCSharpExtensions = /// Patch documents using a JSON field comparison query in the WHERE clause (->> =) [] static member inline PatchByFields(conn, tableName, howMatched, fields, patch: 'TPatch) = - WithProps.Patch.ByFields(tableName, howMatched, fields, patch, Sql.existingConnection conn) + WithProps.Patch.byFields tableName howMatched fields patch (Sql.existingConnection conn) /// Patch documents using a JSON field comparison query in the WHERE clause (->> =) [] @@ -400,13 +400,13 @@ type NpgsqlConnectionCSharpExtensions = /// Remove fields from documents via a comparison on JSON fields in the document [] static member inline RemoveFieldsByFields(conn, tableName, howMatched, fields, fieldNames) = - WithProps.RemoveFields.ByFields(tableName, howMatched, fields, fieldNames, Sql.existingConnection conn) + WithProps.RemoveFields.byFields tableName howMatched fields fieldNames (Sql.existingConnection conn) /// Remove fields from documents via a comparison on a JSON field in the document [] [] static member inline RemoveFieldsByField(conn, tableName, field, fieldNames) = - WithProps.RemoveFields.ByField(tableName, field, fieldNames, Sql.existingConnection conn) + WithProps.RemoveFields.byField tableName field fieldNames (Sql.existingConnection conn) /// Remove fields from documents via a JSON containment query (@>) [] @@ -426,7 +426,7 @@ type NpgsqlConnectionCSharpExtensions = /// Delete documents by matching a JSON field comparison query (->> =) [] static member inline DeleteByFields(conn, tableName, howMatched, fields) = - WithProps.Delete.ByFields(tableName, howMatched, fields, Sql.existingConnection conn) + WithProps.Delete.byFields tableName howMatched fields (Sql.existingConnection conn) /// Delete documents by matching a JSON field comparison query (->> =) [] diff --git a/src/Postgres/Library.fs b/src/Postgres/Library.fs index c586168..c4dfc2a 100644 --- a/src/Postgres/Library.fs +++ b/src/Postgres/Library.fs @@ -63,8 +63,9 @@ module Parameters = let jsonParam (name: string) (it: 'TJson) = name, Sql.jsonb (Configuration.serializer().Serialize it) - /// Convert the fields to their parameters - let private convertFieldsToParameters fields = + /// Create JSON field parameters + [] + let addFieldParams fields parameters = let name = ParameterName() fields |> Seq.map (fun it -> @@ -80,41 +81,22 @@ module Parameters = let p = name.Derive it.ParameterName yield (p, Sql.parameter (NpgsqlParameter(p, it.Value))) }) |> Seq.collect id - - /// Create JSON field parameters - [] - 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.toList + |> Seq.ofList /// Create a JSON field parameter - [] - [] + [] + [] let addFieldParam name field parameters = addFieldParams [ { field with ParameterName = Some name } ] parameters - /// Create a JSON field parameter - [] - 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 - [] - let fieldNameParam (fieldNames: string list) = - if fieldNames.Length = 1 then "@name", Sql.string fieldNames[0] - else "@name", Sql.stringArray (Array.ofList fieldNames) - - /// Append JSON field name parameters for the given field names to the given parameters - let FieldName(fieldNames: string seq) = - if Seq.isEmpty fieldNames then "@name", Sql.string (Seq.head fieldNames) + [] + let fieldNameParam (fieldNames: string seq) = + if Seq.length fieldNames = 1 then "@name", Sql.string (Seq.head fieldNames) else "@name", Sql.stringArray (Array.ofSeq fieldNames) - + /// An empty parameter sequence [] let noParams = @@ -126,11 +108,11 @@ module Parameters = module Query = /// Create a WHERE clause fragment to implement a comparison on fields in a JSON document - [] + [] let whereByFields howMatched fields = let name = ParameterName() fields - |> List.map (fun it -> + |> Seq.map (fun it -> match it.Op with | EX | NEX -> $"{it.PgSqlPath} {it.Op}" | BT -> @@ -144,10 +126,6 @@ module Query = | _ -> $"{it.PgSqlPath} {it.Op} {name.Derive it.ParameterName}") |> 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 [] [] @@ -198,7 +176,7 @@ module Query = $"SELECT COUNT(*) AS it FROM %s{tableName}" /// Query to count matching documents using a text comparison on JSON fields - [] + [] let byFields tableName howMatched fields = $"SELECT COUNT(*) AS it FROM %s{tableName} WHERE {whereByFields howMatched fields}" @@ -208,10 +186,6 @@ module Query = let byField tableName field = byFields tableName Any [ field ] - /// Query to count matching documents using a text comparison on JSON fields - let ByFields tableName howMatched fields = - byFields tableName howMatched (List.ofSeq fields) - /// Query to count matching documents using a JSON containment query (@>) [] let byContains tableName = @@ -231,7 +205,7 @@ module Query = $"""SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE {whereById "@id"}) AS it""" /// Query to determine if documents exist using a comparison on JSON fields - [] + [] let byFields tableName howMatched fields = $"SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE {whereByFields howMatched fields}) AS it" @@ -241,10 +215,6 @@ module Query = let byField tableName field = byFields tableName Any [ field ] - /// Query to determine if documents exist using a comparison on JSON fields - let ByFields tableName howMatched fields = - byFields tableName howMatched (List.ofSeq fields) - /// Query to determine if documents exist using a JSON containment query (@>) [] let byContains tableName = @@ -264,7 +234,7 @@ module Query = $"""{Query.selectFromTable tableName} WHERE {whereById "@id"}""" /// Query to retrieve documents using a comparison on JSON fields - [] + [] let byFields tableName howMatched fields = $"{Query.selectFromTable tableName} WHERE {whereByFields howMatched fields}" @@ -274,10 +244,6 @@ module Query = let byField tableName field = byFields tableName Any [ field ] - /// Query to retrieve documents using a comparison on JSON fields - let ByFields tableName howMatched fields = - byFields tableName howMatched (List.ofSeq fields) - /// Query to retrieve documents using a JSON containment query (@>) [] let byContains tableName = @@ -301,7 +267,7 @@ module Query = whereById "@id" |> update tableName /// Query to patch documents match JSON field comparisons (->> =) - [] + [] let byFields tableName howMatched fields = whereByFields howMatched fields |> update tableName @@ -311,10 +277,6 @@ module Query = let byField tableName field = byFields tableName Any [ field ] - /// Query to patch documents match JSON field comparisons (->> =) - let ByFields tableName howMatched fields = - whereByFields howMatched (List.ofSeq fields) |> update tableName - /// Query to patch documents matching a JSON containment query (@>) [] let byContains tableName = @@ -338,7 +300,7 @@ module Query = whereById "@id" |> update tableName /// Query to remove fields from documents via a comparison on JSON fields within the document - [] + [] let byFields tableName howMatched fields = whereByFields howMatched fields |> update tableName @@ -348,10 +310,6 @@ module Query = let byField tableName field = byFields tableName Any [ field ] - /// Query to remove fields from documents via a comparison on JSON fields within the document - let ByFields tableName howMatched fields = - whereByFields howMatched (List.ofSeq fields) |> update tableName - /// Query to patch documents matching a JSON containment query (@>) [] let byContains tableName = @@ -371,7 +329,7 @@ module Query = $"""DELETE FROM %s{tableName} WHERE {whereById "@id"}""" /// Query to delete documents using a comparison on JSON fields - [] + [] let byFields tableName howMatched fields = $"DELETE FROM %s{tableName} WHERE {whereByFields howMatched fields}" @@ -381,10 +339,6 @@ module Query = let byField tableName field = byFields tableName Any [ field ] - /// Query to delete documents using a comparison on JSON fields - let ByFields tableName howMatched fields = - byFields tableName howMatched (List.ofSeq fields) - /// Query to delete documents using a JSON containment query (@>) [] let byContains tableName = @@ -424,6 +378,8 @@ module Results = /// Versions of queries that accept SqlProps as the last parameter module WithProps = + module FSharpList = Microsoft.FSharp.Collections.List + /// Commands to execute custom SQL queries [] module Custom = @@ -432,12 +388,12 @@ module WithProps = [] let list<'TDoc> query parameters (mapFunc: RowReader -> 'TDoc) sqlProps = Sql.query query sqlProps - |> Sql.parameters parameters + |> Sql.parameters (List.ofSeq parameters) |> Sql.executeAsync mapFunc /// Execute a query that returns a list of results let List<'TDoc>(query, parameters, mapFunc: System.Func, sqlProps) = backgroundTask { - let! results = list<'TDoc> query (List.ofSeq parameters) mapFunc.Invoke sqlProps + let! results = list<'TDoc> query parameters mapFunc.Invoke sqlProps return ResizeArray results } @@ -451,7 +407,7 @@ module WithProps = /// Execute a query that returns one or no results; returns null if not found let Single<'TDoc when 'TDoc: null>( query, parameters, mapFunc: System.Func, sqlProps) = backgroundTask { - let! result = single<'TDoc> query (FSharp.Collections.List.ofSeq parameters) mapFunc.Invoke sqlProps + let! result = single<'TDoc> query parameters mapFunc.Invoke sqlProps return Option.toObj result } @@ -459,7 +415,7 @@ module WithProps = [] let nonQuery query parameters sqlProps = Sql.query query sqlProps - |> Sql.parameters (FSharp.Collections.List.ofSeq parameters) + |> Sql.parameters (FSharpList.ofSeq parameters) |> Sql.executeNonQueryAsync |> ignoreTask @@ -467,12 +423,12 @@ module WithProps = [] let scalar<'T when 'T: struct> query parameters (mapFunc: RowReader -> 'T) sqlProps = Sql.query query sqlProps - |> Sql.parameters parameters + |> Sql.parameters (FSharpList.ofSeq parameters) |> Sql.executeRowAsync mapFunc /// Execute a query that returns a scalar value let Scalar<'T when 'T: struct>(query, parameters, mapFunc: System.Func, sqlProps) = - scalar<'T> query (FSharp.Collections.List.ofSeq parameters) mapFunc.Invoke sqlProps + scalar<'T> query parameters mapFunc.Invoke sqlProps /// Table and index definition commands module Definition = @@ -518,7 +474,7 @@ module WithProps = Custom.scalar (Query.Count.all tableName) [] toCount sqlProps /// Count matching documents using JSON field comparisons (->> =) - [] + [] let byFields tableName howMatched fields sqlProps = Custom.scalar (Query.Count.byFields tableName howMatched fields) (addFieldParams fields []) toCount sqlProps @@ -528,10 +484,6 @@ module WithProps = let byField tableName field sqlProps = byFields tableName Any [ field ] sqlProps - /// Count matching documents using JSON field comparisons (->> =) - let ByFields(tableName, howMatched, fields, sqlProps) = - Custom.Scalar(Query.Count.ByFields tableName howMatched fields, AddFields fields [], toCount, sqlProps) - /// Count matching documents using a JSON containment query (@>) [] let byContains tableName (criteria: 'TContains) sqlProps = @@ -552,7 +504,7 @@ module WithProps = Custom.scalar (Query.Exists.byId tableName) [ idParam docId ] toExists sqlProps /// Determine if a document exists using JSON field comparisons (->> =) - [] + [] let byFields tableName howMatched fields sqlProps = Custom.scalar (Query.Exists.byFields tableName howMatched fields) (addFieldParams fields []) toExists sqlProps @@ -563,10 +515,6 @@ module WithProps = let byField tableName field sqlProps = byFields tableName Any [ field ] sqlProps - /// Determine if a document exists using JSON field comparisons (->> =) - let ByFields(tableName, howMatched, fields, sqlProps) = - Custom.Scalar(Query.Exists.ByFields tableName howMatched fields, AddFields fields [], toExists, sqlProps) - /// Determine if a document exists using a JSON containment query (@>) [] let byContains tableName (criteria: 'TContains) sqlProps = @@ -614,7 +562,7 @@ module WithProps = /// Retrieve documents matching JSON field comparisons (->> =) let ByFields<'TDoc>(tableName, howMatched, fields, sqlProps) = Custom.List<'TDoc>( - Query.Find.ByFields tableName howMatched fields, AddFields fields [], fromData<'TDoc>, sqlProps) + Query.Find.byFields tableName howMatched fields, addFieldParams fields [], fromData<'TDoc>, sqlProps) /// Retrieve documents matching a JSON field comparison (->> =) [] @@ -661,8 +609,8 @@ module WithProps = /// Retrieve the first document matching JSON field comparisons (->> =); returns null if not found let FirstByFields<'TDoc when 'TDoc: null>(tableName, howMatched, fields, sqlProps) = Custom.Single<'TDoc>( - $"{Query.Find.ByFields tableName howMatched fields} LIMIT 1", - AddFields fields [], + $"{Query.Find.byFields tableName howMatched fields} LIMIT 1", + addFieldParams fields [], fromData<'TDoc>, sqlProps) @@ -727,7 +675,7 @@ module WithProps = Custom.nonQuery (Query.Patch.byId tableName) [ idParam docId; jsonParam "@data" patch ] sqlProps /// Patch documents using a JSON field comparison query in the WHERE clause (->> =) - [] + [] let byFields tableName howMatched fields (patch: 'TPatch) sqlProps = Custom.nonQuery (Query.Patch.byFields tableName howMatched fields) @@ -740,13 +688,6 @@ module WithProps = let byField tableName field (patch: 'TPatch) sqlProps = byFields tableName Any [ field ] patch sqlProps - /// Patch documents using a JSON field comparison query in the WHERE clause (->> =) - let ByFields(tableName, howMatched, fields, patch: 'TPatch, sqlProps) = - Custom.nonQuery - (Query.Patch.ByFields tableName howMatched fields) - (AddFields fields [ jsonParam "@data" patch ]) - sqlProps - /// Patch documents using a JSON containment query in the WHERE clause (@>) [] let byContains tableName (criteria: 'TContains) (patch: 'TPatch) sqlProps = @@ -773,7 +714,7 @@ module WithProps = byId tableName docId (List.ofSeq fieldNames) sqlProps /// Remove fields from documents via a comparison on JSON fields in the document - [] + [] let byFields tableName howMatched fields fieldNames sqlProps = Custom.nonQuery (Query.RemoveFields.byFields tableName howMatched fields) @@ -781,23 +722,11 @@ module WithProps = sqlProps /// Remove fields from documents via a comparison on a JSON field in the document - [] + [] [] let byField tableName field fieldNames sqlProps = byFields tableName Any [ field ] fieldNames sqlProps - /// Remove fields from documents via a comparison on JSON fields in the document - let ByFields(tableName, howMatched, fields, fieldNames, sqlProps) = - Custom.nonQuery - (Query.RemoveFields.ByFields tableName howMatched fields) - (AddFields fields [ FieldName fieldNames ]) - sqlProps - - /// Remove fields from documents via a comparison on a JSON field in the document - [] - let ByField(tableName, field, fieldNames, sqlProps) = - ByFields(tableName, Any, Seq.singleton field, fieldNames, sqlProps) - /// Remove fields from documents via a JSON containment query (@>) [] let byContains tableName (criteria: 'TContains) fieldNames sqlProps = @@ -832,7 +761,7 @@ module WithProps = Custom.nonQuery (Query.Delete.byId tableName) [ idParam docId ] sqlProps /// Delete documents by matching a JSON field comparison query (->> =) - [] + [] let byFields tableName howMatched fields sqlProps = Custom.nonQuery (Query.Delete.byFields tableName howMatched fields) (addFieldParams fields []) sqlProps @@ -842,9 +771,6 @@ module WithProps = let byField tableName field sqlProps = byFields tableName Any [ field ] sqlProps - let ByFields(tableName, howMatched, fields, sqlProps) = - Custom.nonQuery (Query.Delete.ByFields tableName howMatched fields) (AddFields fields []) sqlProps - /// Delete documents by matching a JSON contains query (@>) [] let byContains tableName (criteria: 'TCriteria) sqlProps = @@ -938,7 +864,7 @@ module Count = WithProps.Count.all tableName (fromDataSource ()) /// Count matching documents using a JSON field comparison query (->> =) - [] + [] let byFields tableName howMatched fields = WithProps.Count.byFields tableName howMatched fields (fromDataSource ()) @@ -948,10 +874,6 @@ module Count = let byField tableName field = byFields tableName Any [ field ] - /// Count matching documents using a JSON field comparison query (->> =) - let ByFields(tableName, howMatched, fields) = - WithProps.Count.ByFields(tableName, howMatched, fields, fromDataSource ()) - /// Count matching documents using a JSON containment query (@>) [] let byContains tableName criteria = @@ -973,7 +895,7 @@ module Exists = WithProps.Exists.byId tableName docId (fromDataSource ()) /// Determine if documents exist using a JSON field comparison query (->> =) - [] + [] let byFields tableName howMatched fields = WithProps.Exists.byFields tableName howMatched fields (fromDataSource ()) @@ -983,10 +905,6 @@ module Exists = let byField tableName field = byFields tableName Any [ field ] - /// Determine if documents exist using a JSON field comparison query (->> =) - let ByFields(tableName, howMatched, fields) = - WithProps.Exists.ByFields(tableName, howMatched, fields, fromDataSource ()) - /// Determine if documents exist using a JSON containment query (@>) [] let byContains tableName criteria = @@ -1126,7 +1044,7 @@ module Patch = WithProps.Patch.byId tableName docId patch (fromDataSource ()) /// Patch documents using a JSON field comparison query in the WHERE clause (->> =) - [] + [] let byFields tableName howMatched fields (patch: 'TPatch) = WithProps.Patch.byFields tableName howMatched fields patch (fromDataSource ()) @@ -1136,10 +1054,6 @@ module Patch = let byField tableName field (patch: 'TPatch) = byFields tableName Any [ field ] patch - /// Patch documents using a JSON field comparison query in the WHERE clause (->> =) - let ByFields(tableName, howMatched, fields, patch: 'TPatch) = - WithProps.Patch.ByFields(tableName, howMatched, fields, patch, fromDataSource ()) - /// Patch documents using a JSON containment query in the WHERE clause (@>) [] let byContains tableName (criteria: 'TCriteria) (patch: 'TPatch) = @@ -1165,25 +1079,16 @@ module RemoveFields = WithProps.RemoveFields.ById(tableName, docId, fieldNames, fromDataSource ()) /// Remove fields from documents via a comparison on JSON fields in the document - [] + [] let byFields tableName howMatched fields fieldNames = WithProps.RemoveFields.byFields tableName howMatched fields fieldNames (fromDataSource ()) /// Remove fields from documents via a comparison on a JSON field in the document - [] + [] [] let byField tableName field fieldNames = byFields tableName Any [ field ] fieldNames - /// Remove fields from documents via a comparison on JSON fields in the document - let ByFields(tableName, howMatched, fields, fieldNames) = - WithProps.RemoveFields.ByFields(tableName, howMatched, fields, fieldNames, fromDataSource ()) - - /// Remove fields from documents via a comparison on a JSON field in the document - [] - let ByField(tableName, field, fieldNames) = - ByFields(tableName, Any, Seq.singleton field, fieldNames) - /// Remove fields from documents via a JSON containment query (@>) [] let byContains tableName (criteria: 'TContains) fieldNames = @@ -1213,7 +1118,7 @@ module Delete = WithProps.Delete.byId tableName docId (fromDataSource ()) /// Delete documents by matching a JSON field comparison query (->> =) - [] + [] let byFields tableName howMatched fields = WithProps.Delete.byFields tableName howMatched fields (fromDataSource ()) @@ -1223,10 +1128,6 @@ module Delete = let byField tableName field = byFields tableName Any [ field ] - /// Delete documents by matching a JSON field comparison query (->> =) - let ByFields(tableName, howMatched, fields) = - WithProps.Delete.ByFields(tableName, howMatched, fields, fromDataSource ()) - /// Delete documents by matching a JSON containment query (@>) [] let byContains tableName (criteria: 'TContains) = diff --git a/src/Tests.CSharp/PostgresCSharpExtensionTests.cs b/src/Tests.CSharp/PostgresCSharpExtensionTests.cs index b4afe7f..df85d27 100644 --- a/src/Tests.CSharp/PostgresCSharpExtensionTests.cs +++ b/src/Tests.CSharp/PostgresCSharpExtensionTests.cs @@ -31,10 +31,10 @@ public class PostgresCSharpExtensionTests /// Integration tests for the SQLite extension methods /// [Tests] - public static readonly Test Integration = TestList("Postgres.C#.Extensions", new[] - { - TestList("CustomList", new[] - { + public static readonly Test Integration = TestList("Postgres.C#.Extensions", + [ + TestList("CustomList", + [ TestCase("succeeds when data is found", async () => { await using var db = PostgresDb.BuildDb(); @@ -57,9 +57,9 @@ public class PostgresCSharpExtensionTests Results.FromData); Expect.isEmpty(docs, "There should have been no documents returned"); }) - }), - TestList("CustomSingle", new[] - { + ]), + TestList("CustomSingle", + [ TestCase("succeeds when a row is found", async () => { await using var db = PostgresDb.BuildDb(); @@ -81,9 +81,9 @@ public class PostgresCSharpExtensionTests new[] { Tuple.Create("@id", Sql.@string("eighty")) }, Results.FromData); Expect.isNull(doc, "There should not have been a document returned"); }) - }), - TestList("CustomNonQuery", new[] - { + ]), + TestList("CustomNonQuery", + [ TestCase("succeeds when operating on data", async () => { await using var db = PostgresDb.BuildDb(); @@ -107,7 +107,7 @@ public class PostgresCSharpExtensionTests var remaining = await conn.CountAll(PostgresDb.TableName); Expect.equal(remaining, 5, "There should be 5 documents remaining in the table"); }) - }), + ]), TestCase("Scalar succeeds", async () => { await using var db = PostgresDb.BuildDb(); @@ -169,8 +169,8 @@ public class PostgresCSharpExtensionTests exists = await indexExists(); Expect.isTrue(exists, "The index should now exist"); }), - TestList("Insert", new[] - { + TestList("Insert", + [ TestCase("succeeds", async () => { await using var db = PostgresDb.BuildDb(); @@ -198,9 +198,9 @@ public class PostgresCSharpExtensionTests // This is what should have happened } }) - }), - TestList("save", new[] - { + ]), + TestList("save", + [ TestCase("succeeds when a document is inserted", async () => { await using var db = PostgresDb.BuildDb(); @@ -230,7 +230,7 @@ public class PostgresCSharpExtensionTests Expect.isNotNull(after, "There should have been a document returned post-update"); Expect.equal(after.Sub!.Foo, "c", "The updated document is not correct"); }) - }), + ]), TestCase("CountAll succeeds", async () => { await using var db = PostgresDb.BuildDb(); @@ -240,6 +240,7 @@ public class PostgresCSharpExtensionTests var theCount = await conn.CountAll(PostgresDb.TableName); Expect.equal(theCount, 5, "There should have been 5 matching documents"); }), +#pragma warning disable CS0618 TestCase("CountByField succeeds", async () => { await using var db = PostgresDb.BuildDb(); @@ -249,6 +250,7 @@ public class PostgresCSharpExtensionTests var theCount = await conn.CountByField(PostgresDb.TableName, Field.EQ("Value", "purple")); Expect.equal(theCount, 2, "There should have been 2 matching documents"); }), +#pragma warning restore CS0618 TestCase("CountByContains succeeds", async () => { await using var db = PostgresDb.BuildDb(); @@ -267,8 +269,8 @@ public class PostgresCSharpExtensionTests var theCount = await conn.CountByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 5)"); Expect.equal(theCount, 3, "There should have been 3 matching documents"); }), - TestList("ExistsById", new[] - { + TestList("ExistsById", + [ TestCase("succeeds when a document exists", async () => { await using var db = PostgresDb.BuildDb(); @@ -287,9 +289,10 @@ public class PostgresCSharpExtensionTests var exists = await conn.ExistsById(PostgresDb.TableName, "seven"); 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 () => { await using var db = PostgresDb.BuildDb(); @@ -308,9 +311,10 @@ public class PostgresCSharpExtensionTests var exists = await conn.ExistsByField(PostgresDb.TableName, Field.EQ("NumValue", "six")); Expect.isFalse(exists, "There should not have been existing documents"); }) - }), - TestList("ExistsByContains", new[] - { + ]), +#pragma warning restore CS0618 + TestList("ExistsByContains", + [ TestCase("succeeds when documents exist", async () => { await using var db = PostgresDb.BuildDb(); @@ -329,9 +333,9 @@ public class PostgresCSharpExtensionTests var exists = await conn.ExistsByContains(PostgresDb.TableName, new { Nothing = "none" }); Expect.isFalse(exists, "There should not have been any existing documents"); }) - }), - TestList("ExistsByJsonPath", new[] - { + ]), + TestList("ExistsByJsonPath", + [ TestCase("succeeds when documents exist", async () => { await using var db = PostgresDb.BuildDb(); @@ -350,9 +354,9 @@ public class PostgresCSharpExtensionTests var exists = await conn.ExistsByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 1000)"); Expect.isFalse(exists, "There should not have been any existing documents"); }) - }), - TestList("FindAll", new[] - { + ]), + TestList("FindAll", + [ TestCase("succeeds when there is data", async () => { await using var db = PostgresDb.BuildDb(); @@ -372,9 +376,9 @@ public class PostgresCSharpExtensionTests var results = await conn.FindAll(PostgresDb.TableName); Expect.isEmpty(results, "There should have been no documents returned"); }) - }), - TestList("FindById", new[] - { + ]), + TestList("FindById", + [ TestCase("succeeds when a document is found", async () => { await using var db = PostgresDb.BuildDb(); @@ -394,9 +398,10 @@ public class PostgresCSharpExtensionTests var doc = await conn.FindById(PostgresDb.TableName, "three hundred eighty-seven"); 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 () => { await using var db = PostgresDb.BuildDb(); @@ -415,9 +420,10 @@ public class PostgresCSharpExtensionTests var docs = await conn.FindByField(PostgresDb.TableName, Field.EQ("Value", "mauve")); Expect.isEmpty(docs, "There should have been no documents returned"); }) - }), - TestList("FindByContains", new[] - { + ]), +#pragma warning restore CS0618 + TestList("FindByContains", + [ TestCase("succeeds when documents are found", async () => { await using var db = PostgresDb.BuildDb(); @@ -437,9 +443,9 @@ public class PostgresCSharpExtensionTests var docs = await conn.FindByContains(PostgresDb.TableName, new { Value = "mauve" }); Expect.isEmpty(docs, "There should have been no documents returned"); }) - }), - TestList("FindByJsonPath", new[] - { + ]), + TestList("FindByJsonPath", + [ TestCase("succeeds when documents are found", async () => { await using var db = PostgresDb.BuildDb(); @@ -458,9 +464,10 @@ public class PostgresCSharpExtensionTests var docs = await conn.FindByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)"); Expect.isEmpty(docs, "There should have been no documents returned"); }) - }), - TestList("FindFirstByField", new[] - { + ]), +#pragma warning disable CS0618 + TestList("FindFirstByField", + [ TestCase("succeeds when a document is found", async () => { await using var db = PostgresDb.BuildDb(); @@ -490,9 +497,10 @@ public class PostgresCSharpExtensionTests var doc = await conn.FindFirstByField(PostgresDb.TableName, Field.EQ("Value", "absent")); Expect.isNull(doc, "There should not have been a document returned"); }) - }), - TestList("FindFirstByContains", new[] - { + ]), +#pragma warning restore CS0618 + TestList("FindFirstByContains", + [ TestCase("succeeds when a document is found", async () => { await using var db = PostgresDb.BuildDb(); @@ -523,9 +531,9 @@ public class PostgresCSharpExtensionTests var doc = await conn.FindFirstByContains(PostgresDb.TableName, new { Value = "absent" }); Expect.isNull(doc, "There should not have been a document returned"); }) - }), - TestList("FindFirstByJsonPath", new[] - { + ]), + TestList("FindFirstByJsonPath", + [ TestCase("succeeds when a document is found", async () => { await using var db = PostgresDb.BuildDb(); @@ -557,9 +565,9 @@ public class PostgresCSharpExtensionTests var doc = await conn.FindFirstByJsonPath(PostgresDb.TableName, "$.Id ? (@ == \"nope\")"); Expect.isNull(doc, "There should not have been a document returned"); }) - }), - TestList("UpdateById", new[] - { + ]), + TestList("UpdateById", + [ TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); @@ -588,9 +596,9 @@ public class PostgresCSharpExtensionTests await conn.UpdateById(PostgresDb.TableName, "test", new JsonDocument { Id = "x", Sub = new() { Foo = "blue", Bar = "red" } }); }) - }), - TestList("UpdateByFunc", new[] - { + ]), + TestList("UpdateByFunc", + [ TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); @@ -617,9 +625,9 @@ public class PostgresCSharpExtensionTests await conn.UpdateByFunc(PostgresDb.TableName, doc => doc.Id, new JsonDocument { Id = "one", Value = "le un", NumValue = 1 }); }) - }), - TestList("PatchById", new[] - { + ]), + TestList("PatchById", + [ TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); @@ -641,9 +649,10 @@ public class PostgresCSharpExtensionTests // This not raising an exception is the test await conn.PatchById(PostgresDb.TableName, "test", new { Foo = "green" }); }) - }), - TestList("PatchByField", new[] - { + ]), +#pragma warning disable CS0618 + TestList("PatchByField", + [ TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); @@ -664,9 +673,10 @@ public class PostgresCSharpExtensionTests // This not raising an exception is the test await conn.PatchByField(PostgresDb.TableName, Field.EQ("Value", "burgundy"), new { Foo = "green" }); }) - }), - TestList("PatchByContains", new[] - { + ]), +#pragma warning restore CS0618 + TestList("PatchByContains", + [ TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); @@ -687,9 +697,9 @@ public class PostgresCSharpExtensionTests // This not raising an exception is the test await conn.PatchByContains(PostgresDb.TableName, new { Value = "burgundy" }, new { Foo = "green" }); }) - }), - TestList("PatchByJsonPath", new[] - { + ]), + TestList("PatchByJsonPath", + [ TestCase("succeeds when a document is updated", async () => { await using var db = PostgresDb.BuildDb(); @@ -710,9 +720,9 @@ public class PostgresCSharpExtensionTests // This not raising an exception is the test await conn.PatchByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)", new { Foo = "green" }); }) - }), - TestList("RemoveFieldsById", new[] - { + ]), + TestList("RemoveFieldsById", + [ TestCase("succeeds when multiple fields are removed", async () => { await using var db = PostgresDb.BuildDb(); @@ -754,9 +764,10 @@ public class PostgresCSharpExtensionTests // This not raising an exception is the test await conn.RemoveFieldsById(PostgresDb.TableName, "two", new[] { "Value" }); }) - }), - TestList("RemoveFieldsByField", new[] - { + ]), +#pragma warning disable CS0618 + TestList("RemoveFieldsByField", + [ TestCase("succeeds when multiple fields are removed", async () => { await using var db = PostgresDb.BuildDb(); @@ -800,9 +811,10 @@ public class PostgresCSharpExtensionTests await conn.RemoveFieldsByField(PostgresDb.TableName, Field.NE("Abracadabra", "apple"), new[] { "Value" }); }) - }), - TestList("RemoveFieldsByContains", new[] - { + ]), +#pragma warning restore CS0618 + TestList("RemoveFieldsByContains", + [ TestCase("succeeds when multiple fields are removed", async () => { await using var db = PostgresDb.BuildDb(); @@ -846,9 +858,9 @@ public class PostgresCSharpExtensionTests await conn.RemoveFieldsByContains(PostgresDb.TableName, new { Abracadabra = "apple" }, new[] { "Value" }); }) - }), - TestList("RemoveFieldsByJsonPath", new[] - { + ]), + TestList("RemoveFieldsByJsonPath", + [ TestCase("succeeds when multiple fields are removed", async () => { await using var db = PostgresDb.BuildDb(); @@ -892,9 +904,9 @@ public class PostgresCSharpExtensionTests await conn.RemoveFieldsByJsonPath(PostgresDb.TableName, "$.Abracadabra ? (@ == \"apple\")", new[] { "Value" }); }) - }), - TestList("DeleteById", new[] - { + ]), + TestList("DeleteById", + [ TestCase("succeeds when a document is deleted", async () => { await using var db = PostgresDb.BuildDb(); @@ -915,9 +927,10 @@ public class PostgresCSharpExtensionTests var remaining = await conn.CountAll(PostgresDb.TableName); Expect.equal(remaining, 5, "There should have been 5 documents remaining"); }) - }), - TestList("DeleteByField", new[] - { + ]), +#pragma warning disable CS0618 + TestList("DeleteByField", + [ TestCase("succeeds when documents are deleted", async () => { await using var db = PostgresDb.BuildDb(); @@ -938,9 +951,10 @@ public class PostgresCSharpExtensionTests var remaining = await conn.CountAll(PostgresDb.TableName); Expect.equal(remaining, 5, "There should have been 5 documents remaining"); }) - }), - TestList("DeleteByContains", new[] - { + ]), +#pragma warning restore CS0618 + TestList("DeleteByContains", + [ TestCase("succeeds when documents are deleted", async () => { await using var db = PostgresDb.BuildDb(); @@ -961,9 +975,9 @@ public class PostgresCSharpExtensionTests var remaining = await conn.CountAll(PostgresDb.TableName); Expect.equal(remaining, 5, "There should have been 5 documents remaining"); }) - }), - TestList("DeleteByJsonPath", new[] - { + ]), + TestList("DeleteByJsonPath", + [ TestCase("succeeds when documents are deleted", async () => { await using var db = PostgresDb.BuildDb(); @@ -984,6 +998,6 @@ public class PostgresCSharpExtensionTests var remaining = await conn.CountAll(PostgresDb.TableName); Expect.equal(remaining, 5, "There should have been 5 documents remaining"); }) - }), - }); + ]), + ]); } diff --git a/src/Tests.CSharp/PostgresCSharpTests.cs b/src/Tests.CSharp/PostgresCSharpTests.cs index fb9f551..7bf446d 100644 --- a/src/Tests.CSharp/PostgresCSharpTests.cs +++ b/src/Tests.CSharp/PostgresCSharpTests.cs @@ -32,6 +32,68 @@ public static class PostgresCSharpTests Expect.equal(it.Item1, "@test", "JSON parameter not constructed correctly"); Expect.equal(it.Item2, Sql.jsonb("{\"Something\":\"good\"}"), "JSON parameter value incorrect"); }), + TestList("AddFields", + [ + TestCase("succeeds when a parameter is added", () => + { + var paramList = Parameters.AddFields([Field.EQ("it", "242")], []).ToList(); + Expect.hasLength(paramList, 1, "There should have been a parameter added"); + var (name, value) = paramList[0]; + Expect.equal(name, "@field0", "Field parameter name not correct"); + if (!value.IsParameter) + { + Expect.isTrue(false, "The parameter was not a Parameter type"); + } + }), + TestCase("succeeds when multiple independent parameters are added", () => + { + var paramList = Parameters.AddFields([Field.EQ("me", "you"), Field.GT("us", "them")], + [Parameters.Id(14)]).ToList(); + Expect.hasLength(paramList, 3, "There should have been 2 parameters added"); + var (name, value) = paramList[0]; + Expect.equal(name, "@id", "First field parameter name not correct"); + if (!value.IsString) + { + Expect.isTrue(false, "First parameter was not a String type"); + } + (name, value) = paramList[1]; + Expect.equal(name, "@field0", "Second field parameter name not correct"); + if (!value.IsParameter) + { + Expect.isTrue(false, "Second parameter was not a Parameter type"); + } + (name, value) = paramList[2]; + Expect.equal(name, "@field1", "Third parameter name not correct"); + if (!value.IsParameter) + { + Expect.isTrue(false, "Third parameter was not a Parameter type"); + } + }), + TestCase("succeeds when a parameter is not added", () => + { + var paramList = Parameters.AddFields([Field.EX("tacos")], []).ToList(); + Expect.isEmpty(paramList, "There should not have been any parameters added"); + }), + TestCase("succeeds when two parameters are added for one field", () => + { + var paramList = + Parameters.AddFields([Field.BT("that", "eh", "zed").WithParameterName("@test")], []).ToList(); + Expect.hasLength(paramList, 2, "There should have been 2 parameters added"); + var (name, value) = paramList[0]; + Expect.equal(name, "@testmin", "Minimum field name not correct"); + if (!value.IsParameter) + { + Expect.isTrue(false, "Minimum parameter was not a Parameter type"); + } + (name, value) = paramList[1]; + Expect.equal(name, "@testmax", "Maximum field name not correct"); + if (!value.IsParameter) + { + Expect.isTrue(false, "Maximum parameter was not a Parameter type"); + } + }) + ]), +#pragma warning disable CS0618 TestList("AddField", [ TestCase("succeeds when a parameter is added", () => @@ -55,6 +117,28 @@ public static class PostgresCSharpTests Expect.equal(it[1].Item1, "@fieldmax", "Maximum field name not correct"); Expect.isTrue(it[1].Item2.IsParameter, "Maximum field parameter value incorrect"); }) + ]), +#pragma warning restore CS0618 + TestList("FieldName", + [ + TestCase("succeeds for one name", () => + { + var (name, value) = Parameters.FieldName(["bob"]); + Expect.equal(name, "@name", "The parameter name was incorrect"); + if (!value.IsString) + { + Expect.isTrue(false, "The parameter was not a String type"); + } + }), + TestCase("succeeds for multiple names", () => + { + var (name, value) = Parameters.FieldName(["bob", "tom", "mike"]); + Expect.equal(name, "@name", "The parameter name was incorrect"); + if (!value.IsStringArray) + { + Expect.isTrue(false, "The parameter was not a StringArray type"); + } + }) ]) ]), TestList("Query", @@ -110,6 +194,7 @@ public static class PostgresCSharpTests "WHERE clause not correct"); }) ]), +#pragma warning disable CS0618 TestList("WhereByField", [ TestCase("succeeds when a logical operator is passed", () => @@ -133,6 +218,7 @@ public static class PostgresCSharpTests "data->>'field0' BETWEEN @alphamin AND @alphamax", "WHERE clause not correct"); }) ]), +#pragma warning restore CS0618 TestCase("WhereById succeeds", () => { Expect.equal(Postgres.Query.WhereById("@id"), "data->>'Id' = @id", "WHERE clause not correct"); @@ -183,12 +269,14 @@ public static class PostgresCSharpTests Expect.equal(Postgres.Query.Count.All(PostgresDb.TableName), $"SELECT COUNT(*) AS it FROM {PostgresDb.TableName}", "Count query not correct"); }), +#pragma warning disable CS0618 TestCase("ByField succeeds", () => { Expect.equal(Postgres.Query.Count.ByField(PostgresDb.TableName, Field.EQ("thatField", 0)), $"SELECT COUNT(*) AS it FROM {PostgresDb.TableName} WHERE data->>'thatField' = @field0", "JSON field text comparison count query not correct"); }), +#pragma warning restore CS0618 TestCase("ByContains succeeds", () => { Expect.equal(Postgres.Query.Count.ByContains(PostgresDb.TableName), @@ -210,12 +298,14 @@ public static class PostgresCSharpTests $"SELECT EXISTS (SELECT 1 FROM {PostgresDb.TableName} WHERE data->>'Id' = @id) AS it", "ID existence query not correct"); }), +#pragma warning disable CS0618 TestCase("ByField succeeds", () => { Expect.equal(Postgres.Query.Exists.ByField(PostgresDb.TableName, Field.LT("Test", 0)), $"SELECT EXISTS (SELECT 1 FROM {PostgresDb.TableName} WHERE data->>'Test' < @field0) AS it", "JSON field text comparison exists query not correct"); }), +#pragma warning restore CS0618 TestCase("ByContains succeeds", () => { Expect.equal(Postgres.Query.Exists.ByContains(PostgresDb.TableName), @@ -237,12 +327,14 @@ public static class PostgresCSharpTests $"SELECT data FROM {PostgresDb.TableName} WHERE data->>'Id' = @id", "SELECT by ID query not correct"); }), +#pragma warning disable CS0618 TestCase("ByField succeeds", () => { Expect.equal(Postgres.Query.Find.ByField(PostgresDb.TableName, Field.GE("Golf", 0)), $"SELECT data FROM {PostgresDb.TableName} WHERE data->>'Golf' >= @field0", "SELECT by JSON comparison query not correct"); }), +#pragma warning restore CS0618 TestCase("byContains succeeds", () => { Expect.equal(Postgres.Query.Find.ByContains(PostgresDb.TableName), @@ -264,12 +356,14 @@ public static class PostgresCSharpTests $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data->>'Id' = @id", "UPDATE partial by ID statement not correct"); }), +#pragma warning disable CS0618 TestCase("ByField succeeds", () => { Expect.equal(Postgres.Query.Patch.ByField(PostgresDb.TableName, Field.LT("Snail", 0)), $"UPDATE {PostgresDb.TableName} SET data = data || @data WHERE data->>'Snail' < @field0", "UPDATE partial by ID statement not correct"); }), +#pragma warning restore CS0618 TestCase("ByContains succeeds", () => { Expect.equal(Postgres.Query.Patch.ByContains(PostgresDb.TableName), @@ -291,12 +385,14 @@ public static class PostgresCSharpTests $"UPDATE {PostgresDb.TableName} SET data = data - @name WHERE data->>'Id' = @id", "Remove field by ID query not correct"); }), +#pragma warning disable CS0618 TestCase("ByField succeeds", () => { Expect.equal(Postgres.Query.RemoveFields.ByField(PostgresDb.TableName, Field.LT("Fly", 0)), $"UPDATE {PostgresDb.TableName} SET data = data - @name WHERE data->>'Fly' < @field0", "Remove field by field query not correct"); }), +#pragma warning restore CS0618 TestCase("ByContains succeeds", () => { Expect.equal(Postgres.Query.RemoveFields.ByContains(PostgresDb.TableName), @@ -318,12 +414,14 @@ public static class PostgresCSharpTests $"DELETE FROM {PostgresDb.TableName} WHERE data->>'Id' = @id", "DELETE by ID query not correct"); }), +#pragma warning disable CS0618 TestCase("ByField succeeds", () => { Expect.equal(Postgres.Query.Delete.ByField(PostgresDb.TableName, Field.NEX("gone")), $"DELETE FROM {PostgresDb.TableName} WHERE data->>'gone' IS NULL", "DELETE by JSON comparison query not correct"); }), +#pragma warning restore CS0618 TestCase("byContains succeeds", () => { Expect.equal(Postgres.Query.Delete.ByContains(PostgresDb.TableName), @@ -603,6 +701,7 @@ public static class PostgresCSharpTests var theCount = await Count.All(PostgresDb.TableName); Expect.equal(theCount, 5, "There should have been 5 matching documents"); }), +#pragma warning disable CS0618 TestCase("ByField succeeds for numeric range", async () => { await using var db = PostgresDb.BuildDb(); @@ -619,6 +718,7 @@ public static class PostgresCSharpTests var theCount = await Count.ByField(PostgresDb.TableName, Field.BT("Value", "aardvark", "apple")); Expect.equal(theCount, 1, "There should have been 1 matching document"); }), +#pragma warning restore CS0618 TestCase("ByContains succeeds", async () => { await using var db = PostgresDb.BuildDb(); @@ -657,6 +757,7 @@ public static class PostgresCSharpTests Expect.isFalse(exists, "There should not have been an existing document"); }) ]), +#pragma warning disable CS0618 TestList("ByField", [ TestCase("succeeds when documents exist", async () => @@ -676,6 +777,7 @@ public static class PostgresCSharpTests Expect.isFalse(exists, "There should not have been existing documents"); }) ]), +#pragma warning restore CS0618 TestList("ByContains", [ TestCase("succeeds when documents exist", async () => @@ -757,6 +859,7 @@ public static class PostgresCSharpTests Expect.isNull(doc, "There should not have been a document returned"); }) ]), +#pragma warning disable CS0618 TestList("ByField", [ TestCase("succeeds when documents are found", async () => @@ -776,6 +879,7 @@ public static class PostgresCSharpTests Expect.isEmpty(docs, "There should have been no documents returned"); }) ]), +#pragma warning restore CS0618 TestList("ByContains", [ TestCase("succeeds when documents are found", async () => @@ -815,6 +919,7 @@ public static class PostgresCSharpTests Expect.isEmpty(docs, "There should have been no documents returned"); }) ]), +#pragma warning disable CS0618 TestList("FirstByField", [ TestCase("succeeds when a document is found", async () => @@ -844,6 +949,7 @@ public static class PostgresCSharpTests Expect.isNull(doc, "There should not have been a document returned"); }) ]), +#pragma warning restore CS0618 TestList("FirstByContains", [ TestCase("succeeds when a document is found", async () => @@ -992,6 +1098,7 @@ public static class PostgresCSharpTests await Patch.ById(PostgresDb.TableName, "test", new { Foo = "green" }); }) ]), +#pragma warning disable CS0618 TestList("ByField", [ TestCase("succeeds when a document is updated", async () => @@ -1014,6 +1121,7 @@ public static class PostgresCSharpTests await Patch.ByField(PostgresDb.TableName, Field.EQ("Value", "burgundy"), new { Foo = "green" }); }) ]), +#pragma warning restore CS0618 TestList("ByContains", [ TestCase("succeeds when a document is updated", async () => @@ -1101,6 +1209,7 @@ public static class PostgresCSharpTests await RemoveFields.ById(PostgresDb.TableName, "two", new[] { "Value" }); }) ]), +#pragma warning disable CS0618 TestList("ByField", [ TestCase("succeeds when multiple fields are removed", async () => @@ -1143,6 +1252,7 @@ public static class PostgresCSharpTests new[] { "Value" }); }) ]), +#pragma warning restore CS0618 TestList("ByContains", [ TestCase("succeeds when multiple fields are removed", async () => @@ -1251,6 +1361,7 @@ public static class PostgresCSharpTests Expect.equal(remaining, 5, "There should have been 5 documents remaining"); }) ]), +#pragma warning disable CS0618 TestList("ByField", [ TestCase("succeeds when documents are deleted", async () => @@ -1272,6 +1383,7 @@ public static class PostgresCSharpTests Expect.equal(remaining, 5, "There should have been 5 documents remaining"); }) ]), +#pragma warning restore CS0618 TestList("ByContains", [ TestCase("succeeds when documents are deleted", async () => diff --git a/src/Tests/PostgresExtensionTests.fs b/src/Tests/PostgresExtensionTests.fs index 41b1210..b895289 100644 --- a/src/Tests/PostgresExtensionTests.fs +++ b/src/Tests/PostgresExtensionTests.fs @@ -7,6 +7,8 @@ open Expecto open Npgsql open Types +#nowarn "0044" + /// Open a connection to the throwaway database let private mkConn (db: ThrowawayPostgresDb) = let conn = new NpgsqlConnection(db.ConnectionString) diff --git a/src/Tests/PostgresTests.fs b/src/Tests/PostgresTests.fs index d43309b..7683c42 100644 --- a/src/Tests/PostgresTests.fs +++ b/src/Tests/PostgresTests.fs @@ -5,6 +5,8 @@ open BitBadger.Documents open BitBadger.Documents.Postgres open BitBadger.Documents.Tests +#nowarn "0044" + /// Tests which do not hit the database let unitTests = testList "Unit" [ @@ -18,11 +20,69 @@ let unitTests = ("@test", Sql.jsonb """{"Something":"good"}""") "JSON parameter not constructed correctly" } + testList "addFieldParams" [ + test "succeeds when a parameter is added" { + let paramList = addFieldParams [ Field.EQ "it" "242" ] [] + Expect.hasLength paramList 1 "There should have been a parameter added" + let it = Seq.head paramList + Expect.equal (fst it) "@field0" "Field parameter name not correct" + match snd it with + | SqlValue.Parameter value -> + Expect.equal value.ParameterName "@field0" "Parameter name not correct" + Expect.equal value.Value "242" "Parameter value not correct" + | _ -> Expect.isTrue false "The parameter was not a Parameter type" + } + test "succeeds when multiple independent parameters are added" { + let paramList = addFieldParams [ Field.EQ "me" "you"; Field.GT "us" "them" ] [ idParam 14 ] + Expect.hasLength paramList 3 "There should have been 2 parameters added" + let p = Array.ofSeq paramList + Expect.equal (fst p[0]) "@id" "First field parameter name not correct" + match snd p[0] with + | SqlValue.String value -> + Expect.equal value "14" "First parameter value not correct" + | _ -> Expect.isTrue false "First parameter was not a String type" + Expect.equal (fst p[1]) "@field0" "Second field parameter name not correct" + match snd p[1] with + | SqlValue.Parameter value -> + Expect.equal value.ParameterName "@field0" "Second parameter name not correct" + Expect.equal value.Value "you" "Second parameter value not correct" + | _ -> Expect.isTrue false "Second parameter was not a Parameter type" + Expect.equal (fst p[2]) "@field1" "Third parameter name not correct" + match snd p[2] with + | SqlValue.Parameter value -> + Expect.equal value.ParameterName "@field1" "Third parameter name not correct" + Expect.equal value.Value "them" "Third parameter value not correct" + | _ -> Expect.isTrue false "Third parameter was not a Parameter type" + } + test "succeeds when a parameter is not added" { + let paramList = addFieldParams [ Field.EX "tacos" ] [] + Expect.isEmpty paramList "There should not have been any parameters added" + } + test "succeeds when two parameters are added for one field" { + let paramList = + addFieldParams [ { Field.BT "that" "eh" "zed" with ParameterName = Some "@test" } ] [] + Expect.hasLength paramList 2 "There should have been 2 parameters added" + let min = Seq.head paramList + Expect.equal (fst min) "@testmin" "Minimum field name not correct" + match snd min with + | SqlValue.Parameter value -> + Expect.equal value.ParameterName "@testmin" "Minimum parameter name not correct" + Expect.equal value.Value "eh" "Minimum parameter value not correct" + | _ -> Expect.isTrue false "Minimum parameter was not a Parameter type" + let max = paramList |> Seq.skip 1 |> Seq.head + Expect.equal (fst max) "@testmax" "Maximum field name not correct" + match snd max with + | SqlValue.Parameter value -> + Expect.equal value.ParameterName "@testmax" "Maximum parameter name not correct" + Expect.equal value.Value "zed" "Maximum parameter value not correct" + | _ -> Expect.isTrue false "Maximum parameter was not a Parameter type" + } + ] testList "addFieldParam" [ test "succeeds when a parameter is added" { let paramList = addFieldParam "@field" (Field.EQ "it" "242") [] Expect.hasLength paramList 1 "There should have been a parameter added" - let it = paramList[0] + let it = Seq.head paramList Expect.equal (fst it) "@field" "Field parameter name not correct" match snd it with | SqlValue.Parameter value -> @@ -37,14 +97,14 @@ let unitTests = test "succeeds when two parameters are added" { let paramList = addFieldParam "@field" (Field.BT "that" "eh" "zed") [] Expect.hasLength paramList 2 "There should have been 2 parameters added" - let min = paramList[0] + let min = Seq.head paramList Expect.equal (fst min) "@fieldmin" "Minimum field name not correct" match snd min with | SqlValue.Parameter value -> Expect.equal value.ParameterName "@fieldmin" "Minimum parameter name not correct" Expect.equal value.Value "eh" "Minimum parameter value not correct" | _ -> Expect.isTrue false "Minimum parameter was not a Parameter type" - let max = paramList[1] + let max = paramList |> Seq.skip 1 |> Seq.head Expect.equal (fst max) "@fieldmax" "Maximum field name not correct" match snd max with | SqlValue.Parameter value -> @@ -53,6 +113,23 @@ let unitTests = | _ -> Expect.isTrue false "Maximum parameter was not a Parameter type" } ] + testList "fieldNameParam" [ + test "succeeds for one name" { + let name, value = fieldNameParam [ "bob" ] + Expect.equal name "@name" "The parameter name was incorrect" + match value with + | SqlValue.String it -> Expect.equal it "bob" "The parameter value was incorrect" + | _ -> Expect.isTrue false "The parameter was not a String type" + } + test "succeeds for multiple names" { + let name, value = fieldNameParam [ "bob"; "tom"; "mike" ] + Expect.equal name "@name" "The parameter name was incorrect" + match value with + | SqlValue.StringArray it -> + Expect.equal it [| "bob"; "tom"; "mike" |] "The parameter value was incorrect" + | _ -> Expect.isTrue false "The parameter was not a StringArray type" + } + ] test "noParams succeeds" { Expect.isEmpty noParams "The no-params sequence should be empty" } diff --git a/src/Tests/SqliteTests.fs b/src/Tests/SqliteTests.fs index 0a3b249..733d1d8 100644 --- a/src/Tests/SqliteTests.fs +++ b/src/Tests/SqliteTests.fs @@ -8,6 +8,8 @@ open Expecto open Microsoft.Data.Sqlite open Types +#nowarn "0044" + /// Unit tests for the SQLite library let unitTests = testList "Unit" [