v3 RC1 #1

Merged
danieljsummers merged 25 commits from merge-projects into main 2024-01-06 20:51:49 +00:00
7 changed files with 2037 additions and 1257 deletions
Showing only changes of commit 18ec31d16b - Show all commits

View File

@ -18,11 +18,13 @@ module Configuration =
let mutable private dataSourceValue : NpgsqlDataSource option = None let mutable private dataSourceValue : NpgsqlDataSource option = None
/// Register a data source to use for query execution (disposes the current one if it exists) /// Register a data source to use for query execution (disposes the current one if it exists)
[<CompiledName "UseDataSource">]
let useDataSource source = let useDataSource source =
if Option.isSome dataSourceValue then dataSourceValue.Value.Dispose() if Option.isSome dataSourceValue then dataSourceValue.Value.Dispose()
dataSourceValue <- Some source dataSourceValue <- Some source
/// Retrieve the currently configured data source /// Retrieve the currently configured data source
[<CompiledName "DataSource">]
let dataSource () = let dataSource () =
match dataSourceValue with match dataSourceValue with
| Some source -> source | Some source -> source
@ -85,8 +87,8 @@ module Query =
Query.Definition.ensureTableFor name "JSONB" Query.Definition.ensureTableFor name "JSONB"
/// SQL statement to create an index on JSON documents in the specified table /// SQL statement to create an index on JSON documents in the specified table
[<CompiledName "EnsureJsonIndex">] [<CompiledName "EnsureDocumentIndex">]
let ensureJsonIndex (name: string) idxType = let ensureDocumentIndex (name: string) idxType =
let extraOps = match idxType with Full -> "" | Optimized -> " jsonb_path_ops" let extraOps = match idxType with Full -> "" | Optimized -> " jsonb_path_ops"
let tableName = name.Split '.' |> Array.last let tableName = name.Split '.' |> Array.last
$"CREATE INDEX IF NOT EXISTS idx_{tableName}_document ON {name} USING GIN (data{extraOps})" $"CREATE INDEX IF NOT EXISTS idx_{tableName}_document ON {name} USING GIN (data{extraOps})"
@ -266,9 +268,9 @@ module WithProps =
} }
/// Create an index on documents in the specified table /// Create an index on documents in the specified table
[<CompiledName "EnsureJsonIndex">] [<CompiledName "EnsureDocumentIndex">]
let ensureJsonIndex name idxType sqlProps = let ensureDocumentIndex name idxType sqlProps =
Custom.nonQuery (Query.Definition.ensureJsonIndex name idxType) [] sqlProps Custom.nonQuery (Query.Definition.ensureDocumentIndex name idxType) [] sqlProps
/// Create an index on field(s) within documents in the specified table /// Create an index on field(s) within documents in the specified table
[<CompiledName "EnsureFieldIndex">] [<CompiledName "EnsureFieldIndex">]
@ -549,9 +551,9 @@ module Definition =
WithProps.Definition.ensureTable name (fromDataSource ()) WithProps.Definition.ensureTable name (fromDataSource ())
/// Create an index on documents in the specified table /// Create an index on documents in the specified table
[<CompiledName "EnsureJsonIndex">] [<CompiledName "EnsureDocumentIndex">]
let ensureJsonIndex name idxType = let ensureDocumentIndex name idxType =
WithProps.Definition.ensureJsonIndex name idxType (fromDataSource ()) WithProps.Definition.ensureDocumentIndex name idxType (fromDataSource ())
/// Create an index on field(s) within documents in the specified table /// Create an index on field(s) within documents in the specified table
[<CompiledName "EnsureFieldIndex">] [<CompiledName "EnsureFieldIndex">]

View File

@ -23,8 +23,7 @@ public static class CommonCSharpTests
/// Unit tests /// Unit tests
/// </summary> /// </summary>
[Tests] [Tests]
public static Test Unit = public static readonly Test Unit = TestList("Common.C# Unit", new[]
TestList("Common.C# Unit", new[]
{ {
TestSequenced( TestSequenced(
TestList("Configuration", new[] TestList("Configuration", new[]
@ -177,8 +176,7 @@ public static class CommonCSharpTests
{ {
TestCase("All succeeds", () => TestCase("All succeeds", () =>
{ {
Expect.equal(Query.Count.All("tbl"), "SELECT COUNT(*) AS it FROM tbl", Expect.equal(Query.Count.All("tbl"), "SELECT COUNT(*) AS it FROM tbl", "Count query not correct");
"Count query not correct");
}), }),
TestCase("ByField succeeds", () => TestCase("ByField succeeds", () =>
{ {

View File

@ -1,10 +1,11 @@
using Expecto.CSharp; using Expecto.CSharp;
using Expecto; using Expecto;
using BitBadger.Documents.Postgres; using BitBadger.Documents.Postgres;
using Npgsql.FSharp; using ThrowawayDb.Postgres;
namespace BitBadger.Documents.Tests.CSharp; namespace BitBadger.Documents.Tests.CSharp;
using static CommonExtensionsAndTypesForNpgsqlFSharp;
using static Runner; using static Runner;
/// <summary> /// <summary>
@ -12,24 +13,33 @@ using static Runner;
/// </summary> /// </summary>
public class PostgresCSharpTests public class PostgresCSharpTests
{ {
public static Test Unit = /// <summary>
TestList("Unit", new[] /// Tests which do not hit the database
/// </summary>
private static readonly Test Unit = TestList("Unit", new[]
{ {
TestList("Parameters", new[] TestList("Parameters", new[]
{ {
TestCase("Id succeeds", () => { TestCase("Id succeeds", () =>
Expect.equal(Parameters.Id(88).Item1, "@id", "ID parameter not constructed correctly"); {
var it = Parameters.Id(88);
Expect.equal(it.Item1, "@id", "ID parameter not constructed correctly");
Expect.equal(it.Item2, Sql.@string("88"), "ID parameter value incorrect");
}), }),
TestCase("Json succeeds", () => TestCase("Json succeeds", () =>
{ {
Expect.equal(Parameters.Json("@test", new { Something = "good" }).Item1, "@test", var it = Parameters.Json("@test", new { Something = "good" });
"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");
}), }),
TestCase("Field succeeds", () => TestCase("Field succeeds", () =>
{ {
Expect.equal(Parameters.Field(242).Item1, "@field", "Field parameter not constructed correctly"); var it = Parameters.Field(242);
Expect.equal(it.Item1, "@field", "Field parameter not constructed correctly");
Expect.isTrue(it.Item2.IsParameter, "Field parameter value incorrect");
}), }),
TestCase("None succeeds", () => { TestCase("None succeeds", () =>
{
Expect.isEmpty(Parameters.None, "The no-params sequence should be empty"); Expect.isEmpty(Parameters.None, "The no-params sequence should be empty");
}) })
}), }),
@ -43,16 +53,16 @@ public class PostgresCSharpTests
$"CREATE TABLE IF NOT EXISTS {PostgresDb.TableName} (data JSONB NOT NULL)", $"CREATE TABLE IF NOT EXISTS {PostgresDb.TableName} (data JSONB NOT NULL)",
"CREATE TABLE statement not constructed correctly"); "CREATE TABLE statement not constructed correctly");
}), }),
TestCase("EnsureJsonIndex succeeds for full index", () => TestCase("EnsureDocumentIndex succeeds for full index", () =>
{ {
Expect.equal(Postgres.Query.Definition.EnsureJsonIndex("schema.tbl", DocumentIndex.Full), Expect.equal(Postgres.Query.Definition.EnsureDocumentIndex("schema.tbl", DocumentIndex.Full),
"CREATE INDEX IF NOT EXISTS idx_tbl_document ON schema.tbl USING GIN (data)", "CREATE INDEX IF NOT EXISTS idx_tbl_document ON schema.tbl USING GIN (data)",
"CREATE INDEX statement not constructed correctly"); "CREATE INDEX statement not constructed correctly");
}), }),
TestCase("EnsureJsonIndex succeeds for JSONB Path Ops index", () => TestCase("EnsureDocumentIndex succeeds for JSONB Path Ops index", () =>
{ {
Expect.equal( Expect.equal(
Postgres.Query.Definition.EnsureJsonIndex(PostgresDb.TableName, DocumentIndex.Optimized), Postgres.Query.Definition.EnsureDocumentIndex(PostgresDb.TableName, DocumentIndex.Optimized),
string.Format( string.Format(
"CREATE INDEX IF NOT EXISTS idx_{0}_document ON {0} USING GIN (data jsonb_path_ops)", "CREATE INDEX IF NOT EXISTS idx_{0}_document ON {0} USING GIN (data jsonb_path_ops)",
PostgresDb.TableName), PostgresDb.TableName),
@ -168,13 +178,794 @@ public class PostgresCSharpTests
new() { Id = "five", Value = "purple", NumValue = 18 } new() { Id = "five", Value = "purple", NumValue = 18 }
}; };
/// <summary>
/// Add the test documents to the database
/// </summary>
internal static async Task LoadDocs() internal static async Task LoadDocs()
{ {
foreach (var doc in TestDocuments) await Document.Insert(SqliteDb.TableName, doc); foreach (var doc in TestDocuments) await Document.Insert(SqliteDb.TableName, doc);
} }
/// <summary>
/// Integration tests for the PostgreSQL library
/// </summary>
private static readonly Test Integration = TestList("Integration", new[]
{
TestList("Configuration", new[]
{
TestCase("UseDataSource disposes existing source", () =>
{
using var db1 = ThrowawayDatabase.Create(PostgresDb.ConnStr.Value);
var source = PostgresDb.MkDataSource(db1.ConnectionString);
Postgres.Configuration.UseDataSource(source);
using var db2 = ThrowawayDatabase.Create(PostgresDb.ConnStr.Value);
Postgres.Configuration.UseDataSource(PostgresDb.MkDataSource(db2.ConnectionString));
try
{
_ = source.OpenConnection();
Expect.isTrue(false, "Data source should have been disposed");
}
catch (Exception)
{
// This is what should have happened
}
}),
TestCase("DataSource returns configured data source", () =>
{
using var db = ThrowawayDatabase.Create(PostgresDb.ConnStr.Value);
var source = PostgresDb.MkDataSource(db.ConnectionString);
Postgres.Configuration.UseDataSource(source);
Expect.isTrue(ReferenceEquals(source, Postgres.Configuration.DataSource()),
"Data source should have been the same");
})
}),
TestList("Custom", new[]
{
TestList("List", new[]
{
TestCase("succeeds when data is found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var docs = await Custom.List(Query.SelectFromTable(PostgresDb.TableName), Parameters.None,
Results.FromData<JsonDocument>);
Expect.equal(docs.Count, 5, "There should have been 5 documents returned");
}),
TestCase("succeeds when data is not found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var docs = await Custom.List(
$"SELECT data FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath",
new[] { Tuple.Create("@path", Sql.@string("$.NumValue ? (@ > 100)")) },
Results.FromData<JsonDocument>);
Expect.isEmpty(docs, "There should have been no documents returned");
})
}),
TestList("Single", new[]
{
TestCase("succeeds when a row is found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Custom.Single($"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id",
new[] { Tuple.Create("@id", Sql.@string("one")) }, Results.FromData<JsonDocument>);
Expect.isNotNull(doc, "There should have been a document returned");
Expect.equal(doc.Id, "one", "The incorrect document was returned");
}),
TestCase("succeeds when a row is not found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Custom.Single($"SELECT data FROM {PostgresDb.TableName} WHERE data ->> 'Id' = @id",
new[] { Tuple.Create("@id", Sql.@string("eighty")) }, Results.FromData<JsonDocument>);
Expect.isNull(doc, "There should not have been a document returned");
})
}),
TestList("NonQuery", new[]
{
TestCase("succeeds when operating on data", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Custom.NonQuery($"DELETE FROM {PostgresDb.TableName}", Parameters.None);
var remaining = await Count.All(PostgresDb.TableName);
Expect.equal(remaining, 0, "There should be no documents remaining in the table");
}),
TestCase("succeeds when no data matches where clause", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Custom.NonQuery($"DELETE FROM {PostgresDb.TableName} WHERE data @? @path::jsonpath",
new[] { Tuple.Create("@path", Sql.@string("$.NumValue ? (@ > 100)")) });
var remaining = await Count.All(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();
var nbr = await Custom.Scalar("SELECT 5 AS test_value", Parameters.None, row => row.@int("test_value"));
Expect.equal(nbr, 5, "The query should have returned the number 5");
})
}),
TestList("Definition", new[]
{
TestCase("EnsureTable succeeds", async () =>
{
await using var db = PostgresDb.BuildDb();
var tableExists = () => Custom.Scalar(
"SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'ensured') AS it", Parameters.None,
Results.ToExists);
var keyExists = () => Custom.Scalar(
"SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_ensured_key') AS it", Parameters.None,
Results.ToExists);
var exists = await tableExists();
var alsoExists = await keyExists();
Expect.isFalse(exists, "The table should not exist already");
Expect.isFalse(alsoExists, "The key index should not exist already");
await Definition.EnsureTable("ensured");
exists = await tableExists();
alsoExists = await keyExists();
Expect.isTrue(exists, "The table should now exist");
Expect.isTrue(alsoExists, "The key index should now exist");
}),
TestCase("EnsureDocumentIndex succeeds", async () =>
{
await using var db = PostgresDb.BuildDb();
var indexExists = () => Custom.Scalar(
"SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_ensured_document') AS it",
Parameters.None, Results.ToExists);
var exists = await indexExists();
Expect.isFalse(exists, "The index should not exist already");
await Definition.EnsureTable("ensured");
await Definition.EnsureDocumentIndex("ensured", DocumentIndex.Optimized);
exists = await indexExists();
Expect.isTrue(exists, "The index should now exist");
}),
TestCase("EnsureFieldIndex succeeds", async () =>
{
await using var db = PostgresDb.BuildDb();
var indexExists = () => Custom.Scalar(
"SELECT EXISTS (SELECT 1 FROM pg_class WHERE relname = 'idx_ensured_test') AS it", Parameters.None,
Results.ToExists);
var exists = await indexExists();
Expect.isFalse(exists, "The index should not exist already");
await Definition.EnsureTable("ensured");
await Definition.EnsureFieldIndex("ensured", "test", new[] { "Id", "Category" });
exists = await indexExists();
Expect.isTrue(exists, "The index should now exist");
})
}),
TestList("Document", new[]
{
TestList("Insert", new[]
{
TestCase("succeeds", async () =>
{
await using var db = PostgresDb.BuildDb();
var before = await Count.All(PostgresDb.TableName);
Expect.equal(before, 0, "There should be no documents in the table");
await Document.Insert(PostgresDb.TableName,
new JsonDocument { Id = "turkey", Sub = new() { Foo = "gobble", Bar = "gobble" } });
var after = await Count.All(PostgresDb.TableName);
Expect.equal(after, 1, "There should have been one document inserted");
}),
TestCase("fails for duplicate key", async () =>
{
await using var db = PostgresDb.BuildDb();
await Document.Insert(PostgresDb.TableName, new JsonDocument { Id = "test" });
try
{
await Document.Insert(PostgresDb.TableName, new JsonDocument { Id = "test" });
Expect.isTrue(false, "An exception should have been raised for duplicate document ID insert");
}
catch (Exception)
{
// This is what should have happened
}
})
}),
TestList("Save", new[]
{
TestCase("succeeds when a document is inserted", async () =>
{
await using var db = PostgresDb.BuildDb();
var before = await Count.All(PostgresDb.TableName);
Expect.equal(before, 0, "There should be no documents in the table");
await Document.Save(PostgresDb.TableName,
new JsonDocument { Id = "test", Sub = new() { Foo = "a", Bar = "b" } });
var after = await Count.All(PostgresDb.TableName);
Expect.equal(after, 1, "There should have been one document inserted");
}),
TestCase("succeeds when a document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
await Document.Insert(PostgresDb.TableName,
new JsonDocument { Id = "test", Sub = new() { Foo = "a", Bar = "b" } });
var before = await Find.ById<string, JsonDocument>(PostgresDb.TableName, "test");
Expect.isNotNull(before, "There should have been a document returned");
Expect.equal(before.Id, "test", "The document is not correct");
before.Sub = new() { Foo = "c", Bar = "d" };
await Document.Save(PostgresDb.TableName, before);
var after = await Find.ById<string, JsonDocument>(PostgresDb.TableName, "test");
Expect.isNotNull(after, "There should have been a document returned post-update");
Expect.equal(after.Id, "test", "The document is not correct");
Expect.equal(after.Sub!.Foo, "c", "The updated document is not correct");
})
})
}),
TestList("Count", new[]
{
TestCase("All succeeds", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var theCount = await Count.All(PostgresDb.TableName);
Expect.equal(theCount, 5, "There should have been 5 matching documents");
}),
TestCase("ByField succeeds", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var theCount = await Count.ByField(PostgresDb.TableName, "Value", Op.EQ, "purple");
Expect.equal(theCount, 2, "There should have been 2 matching documents");
}),
TestCase("ByContains succeeds", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var theCount = await Count.ByContains(PostgresDb.TableName, new { Value = "purple" });
Expect.equal(theCount, 2, "There should have been 2 matching documents");
}),
TestCase("ByJsonPath succeeds", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var theCount = await Count.ByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 5)");
Expect.equal(theCount, 3, "There should have been 3 matching documents");
})
}),
TestList("Exists", new[]
{
TestList("ById", new[]
{
TestCase("succeeds when a document exists", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var exists = await Exists.ById(PostgresDb.TableName, "three");
Expect.isTrue(exists, "There should have been an existing document");
}),
TestCase("succeeds when a document does not exist", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var exists = await Exists.ById(PostgresDb.TableName, "seven");
Expect.isFalse(exists, "There should not have been an existing document");
})
}),
TestList("ByField", new[]
{
TestCase("succeeds when documents exist", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var exists = await Exists.ByField(PostgresDb.TableName, "Sub", Op.NEX, "");
Expect.isTrue(exists, "There should have been existing documents");
}),
TestCase("succeeds when documents do not exist", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var exists = await Exists.ByField(PostgresDb.TableName, "NumValue", Op.EQ, "six");
Expect.isFalse(exists, "There should not have been existing documents");
})
}),
TestList("ByContains", new[]
{
TestCase("succeeds when documents exist", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var exists = await Exists.ByContains(PostgresDb.TableName, new { NumValue = 10 });
Expect.isTrue(exists, "There should have been existing documents");
}),
TestCase("succeeds when no matching documents exist", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var exists = await Exists.ByContains(PostgresDb.TableName, new { Nothing = "none" });
Expect.isFalse(exists, "There should not have been any existing documents");
})
}),
TestList("ByJsonPath", new[] {
TestCase("succeeds when documents exist", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var exists = await Exists.ByJsonPath(PostgresDb.TableName, "$.Sub.Foo ? (@ == \"green\")");
Expect.isTrue(exists, "There should have been existing documents");
}),
TestCase("succeeds when no matching documents exist", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var exists = await Exists.ByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 1000)");
Expect.isFalse(exists, "There should not have been any existing documents");
})
})
}),
TestList("Find", new[]
{
TestList("All", new[]
{
TestCase("succeeds when there is data", async () =>
{
await using var db = PostgresDb.BuildDb();
await Document.Insert(PostgresDb.TableName, new SubDocument { Foo = "one", Bar = "two" });
await Document.Insert(PostgresDb.TableName, new SubDocument { Foo = "three", Bar = "four" });
await Document.Insert(PostgresDb.TableName, new SubDocument { Foo = "five", Bar = "six" });
var results = await Find.All<SubDocument>(PostgresDb.TableName);
Expect.equal(results.Count, 3, "There should have been 3 documents returned");
}),
TestCase("succeeds when there is no data", async () =>
{
await using var db = PostgresDb.BuildDb();
var results = await Find.All<SubDocument>(PostgresDb.TableName);
Expect.isEmpty(results, "There should have been no documents returned");
})
}),
TestList("ById", new[]
{
TestCase("succeeds when a document is found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Find.ById<string, JsonDocument>(PostgresDb.TableName, "two");
Expect.isNotNull(doc, "There should have been a document returned");
Expect.equal(doc.Id, "two", "The incorrect document was returned");
}),
TestCase("succeeds when a document is not found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Find.ById<string, JsonDocument>(PostgresDb.TableName, "three hundred eighty-seven");
Expect.isNull(doc, "There should not have been a document returned");
})
}),
TestList("ByField", new[]
{
TestCase("succeeds when documents are found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var docs = await Find.ByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "another");
Expect.equal(docs.Count, 1, "There should have been one document returned");
}),
TestCase("succeeds when documents are not found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var docs = await Find.ByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "mauve");
Expect.isEmpty(docs, "There should have been no documents returned");
})
}),
TestList("ByContains", new[]
{
TestCase("succeeds when documents are found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var docs = await Find.ByContains<JsonDocument>(PostgresDb.TableName,
new { Sub = new { Foo = "green" } });
Expect.equal(docs.Count, 2, "There should have been two documents returned");
}),
TestCase("succeeds when documents are not found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var docs = await Find.ByContains<JsonDocument>(PostgresDb.TableName, new { Value = "mauve" });
Expect.isEmpty(docs, "There should have been no documents returned");
})
}),
TestList("ByJsonPath", new[]
{
TestCase("succeeds when documents are found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var docs = await Find.ByJsonPath<JsonDocument>(PostgresDb.TableName, "$.NumValue ? (@ < 15)");
Expect.equal(docs.Count, 3, "There should have been 3 documents returned");
}),
TestCase("succeeds when documents are not found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var docs = await Find.ByJsonPath<JsonDocument>(PostgresDb.TableName, "$.NumValue ? (@ < 0)");
Expect.isEmpty(docs, "There should have been no documents returned");
})
}),
TestList("FirstByField", new[]
{
TestCase("succeeds when a document is found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Find.FirstByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "another");
Expect.isNotNull(doc, "There should have been a document returned");
Expect.equal(doc.Id, "two", "The incorrect document was returned");
}),
TestCase("succeeds when multiple documents are found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Find.FirstByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "purple");
Expect.isNotNull(doc, "There should have been a document returned");
Expect.contains(new[] { "five", "four" }, doc.Id, "An incorrect document was returned");
}),
TestCase("succeeds when a document is not found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Find.FirstByField<JsonDocument>(PostgresDb.TableName, "Value", Op.EQ, "absent");
Expect.isNull(doc, "There should not have been a document returned");
})
}),
TestList("FirstByContains", new[]
{
TestCase("succeeds when a document is found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Find.FirstByContains<JsonDocument>(PostgresDb.TableName, new { Value = "another" });
Expect.isNotNull(doc, "There should have been a document returned");
Expect.equal(doc.Id, "two", "The incorrect document was returned");
}),
TestCase("succeeds when multiple documents are found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Find.FirstByContains<JsonDocument>(PostgresDb.TableName,
new { Sub = new { Foo = "green" } });
Expect.isNotNull(doc, "There should have been a document returned");
Expect.contains(new[] { "two", "four" }, doc.Id, "An incorrect document was returned");
}),
TestCase("succeeds when a document is not found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Find.FirstByContains<JsonDocument>(PostgresDb.TableName, new { Value = "absent" });
Expect.isNull(doc, "There should not have been a document returned");
})
}),
TestList("FirstByJsonPath", new[]
{
TestCase("succeeds when a document is found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Find.FirstByJsonPath<JsonDocument>(PostgresDb.TableName,
"$.Value ? (@ == \"FIRST!\")");
Expect.isNotNull(doc, "There should have been a document returned");
Expect.equal(doc.Id, "one", "The incorrect document was returned");
}),
TestCase("succeeds when multiple documents are found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Find.FirstByJsonPath<JsonDocument>(PostgresDb.TableName,
"$.Sub.Foo ? (@ == \"green\")");
Expect.isNotNull(doc, "There should have been a document returned");
Expect.contains(new[] { "two", "four" }, doc.Id, "An incorrect document was returned");
}),
TestCase("succeeds when a document is not found", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
var doc = await Find.FirstByJsonPath<JsonDocument>(PostgresDb.TableName, "$.Id ? (@ == \"nope\")");
Expect.isNull(doc, "There should not have been a document returned");
})
})
}),
TestList("Update", new[]
{
TestList("Full", new[]
{
TestCase("succeeds when a document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Update.Full(PostgresDb.TableName, "one",
new JsonDocument { Id = "one", Sub = new() { Foo = "blue", Bar = "red" } });
var after = await Find.ById<string, JsonDocument>(PostgresDb.TableName, "one");
Expect.isNotNull(after, "There should have been a document returned post-update");
Expect.equal(after.Id, "one", "The updated document is not correct (ID)");
Expect.equal(after.Value, "", "The updated document is not correct (Value)");
Expect.equal(after.NumValue, 0, "The updated document is not correct (NumValue)");
Expect.isNotNull(after.Sub, "The updated document should have had a sub-document");
Expect.equal(after.Sub!.Foo, "blue", "The updated document is not correct (Sub.Foo)");
Expect.equal(after.Sub.Bar, "red", "The updated document is not correct (Sub.Bar)");
}),
TestCase("succeeds when no document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
var before = await Count.All(PostgresDb.TableName);
Expect.equal(before, 0, "There should have been no documents returned");
// This not raising an exception is the test
await Update.Full(PostgresDb.TableName, "test",
new JsonDocument { Id = "x", Sub = new() { Foo = "blue", Bar = "red" } });
})
}),
TestList("FullFunc", new[]
{
TestCase("succeeds when a document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Update.FullFunc(PostgresDb.TableName, doc => doc.Id,
new JsonDocument { Id = "one", Value = "le un", NumValue = 1 });
var after = await Find.ById<string, JsonDocument>(PostgresDb.TableName, "one");
Expect.isNotNull(after, "There should have been a document returned post-update");
Expect.equal(after.Id, "one", "The updated document is not correct (ID)");
Expect.equal(after.Value, "le un", "The updated document is not correct (Value)");
Expect.equal(after.NumValue, 1, "The updated document is not correct (NumValue)");
Expect.isNull(after.Sub, "The updated document should not have had a sub-document");
}),
TestCase("succeeds when no document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
var before = await Count.All(PostgresDb.TableName);
Expect.equal(before, 0, "There should have been no documents returned");
// This not raising an exception is the test
await Update.FullFunc(PostgresDb.TableName, doc => doc.Id,
new JsonDocument { Id = "one", Value = "le un", NumValue = 1 });
})
}),
TestList("PartialById", new[]
{
TestCase("succeeds when a document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Update.PartialById(PostgresDb.TableName, "one", new { NumValue = 44 });
var after = await Find.ById<string, JsonDocument>(PostgresDb.TableName, "one");
Expect.isNotNull(after, "There should have been a document returned post-update");
Expect.equal(after.NumValue, 44, "The updated document is not correct");
}),
TestCase("succeeds when no document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
var before = await Count.All(PostgresDb.TableName);
Expect.equal(before, 0, "There should have been no documents returned");
// This not raising an exception is the test
await Update.PartialById(PostgresDb.TableName, "test", new { Foo = "green" });
})
}),
TestList("PartialByField", new[]
{
TestCase("succeeds when a document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Update.PartialByField(PostgresDb.TableName, "Value", Op.EQ, "purple", new { NumValue = 77 });
var after = await Count.ByField(PostgresDb.TableName, "NumValue", Op.EQ, "77");
Expect.equal(after, 2, "There should have been 2 documents returned");
}),
TestCase("succeeds when no document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
var before = await Count.All(PostgresDb.TableName);
Expect.equal(before, 0, "There should have been no documents returned");
// This not raising an exception is the test
await Update.PartialByField(PostgresDb.TableName, "Value", Op.EQ, "burgundy",
new { Foo = "green" });
})
}),
TestList("PartialByContains", new[]
{
TestCase("succeeds when a document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Update.PartialByContains(PostgresDb.TableName, new { Value = "purple" },
new { NumValue = 77 });
var after = await Count.ByContains(PostgresDb.TableName, new { NumValue = 77 });
Expect.equal(after, 2, "There should have been 2 documents returned");
}),
TestCase("succeeds when no document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
var before = await Count.All(PostgresDb.TableName);
Expect.equal(before, 0, "There should have been no documents returned");
// This not raising an exception is the test
await Update.PartialByContains(PostgresDb.TableName, new { Value = "burgundy" },
new { Foo = "green" });
})
}),
TestList("PartialByJsonPath", new[]
{
TestCase("succeeds when a document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Update.PartialByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 10)",
new { NumValue = 1000 });
var after = await Count.ByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 999)");
Expect.equal(after, 2, "There should have been 2 documents returned");
}),
TestCase("succeeds when no document is updated", async () =>
{
await using var db = PostgresDb.BuildDb();
var before = await Count.All(PostgresDb.TableName);
Expect.equal(before, 0, "There should have been no documents returned");
// This not raising an exception is the test
await Update.PartialByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ < 0)", new { Foo = "green" });
})
})
}),
TestList("Delete", new[]
{
TestList("ById", new[]
{
TestCase("succeeds when a document is deleted", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Delete.ById(PostgresDb.TableName, "four");
var remaining = await Count.All(PostgresDb.TableName);
Expect.equal(remaining, 4, "There should have been 4 documents remaining");
}),
TestCase("succeeds when a document is not deleted", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Delete.ById(PostgresDb.TableName, "thirty");
var remaining = await Count.All(PostgresDb.TableName);
Expect.equal(remaining, 5, "There should have been 5 documents remaining");
})
}),
TestList("ByField", new[]
{
TestCase("succeeds when documents are deleted", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Delete.ByField(PostgresDb.TableName, "Value", Op.EQ, "purple");
var remaining = await Count.All(PostgresDb.TableName);
Expect.equal(remaining, 3, "There should have been 3 documents remaining");
}),
TestCase("succeeds when documents are not deleted", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Delete.ByField(PostgresDb.TableName, "Value", Op.EQ, "crimson");
var remaining = await Count.All(PostgresDb.TableName);
Expect.equal(remaining, 5, "There should have been 5 documents remaining");
})
}),
TestList("ByContains", new[]
{
TestCase("succeeds when documents are deleted", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Delete.ByContains(PostgresDb.TableName, new { Value = "purple" });
var remaining = await Count.All(PostgresDb.TableName);
Expect.equal(remaining, 3, "There should have been 3 documents remaining");
}),
TestCase("succeeds when documents are not deleted", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Delete.ByContains(PostgresDb.TableName, new { Value = "crimson" });
var remaining = await Count.All(PostgresDb.TableName);
Expect.equal(remaining, 5, "There should have been 5 documents remaining");
})
}),
TestList("ByJsonPath", new[]
{
TestCase("succeeds when documents are deleted", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Delete.ByJsonPath(PostgresDb.TableName, "$.Sub.Foo ? (@ == \"green\")");
var remaining = await Count.All(PostgresDb.TableName);
Expect.equal(remaining, 3, "There should have been 3 documents remaining");
}),
TestCase("succeeds when documents are not deleted", async () =>
{
await using var db = PostgresDb.BuildDb();
await LoadDocs();
await Delete.ByJsonPath(PostgresDb.TableName, "$.NumValue ? (@ > 100)");
var remaining = await Count.All(PostgresDb.TableName);
Expect.equal(remaining, 5, "There should have been 5 documents remaining");
})
})
})
});
/// <summary> /// <summary>
/// All Postgres C# tests /// All Postgres C# tests
/// </summary> /// </summary>
public static Test All = TestList("Postgres.C#", new[] { Unit }); [Tests]
public static readonly Test All = TestList("Postgres.C#", new[] { Unit, TestSequenced(Integration) });
} }

View File

@ -137,7 +137,7 @@ public static class PostgresDb
Sql.executeNonQuery(Sql.query(Postgres.Query.Definition.EnsureTable(TableName), sqlProps)); Sql.executeNonQuery(Sql.query(Postgres.Query.Definition.EnsureTable(TableName), sqlProps));
Sql.executeNonQuery(Sql.query(Query.Definition.EnsureKey(TableName), sqlProps)); Sql.executeNonQuery(Sql.query(Query.Definition.EnsureKey(TableName), sqlProps));
Postgres.Configuration.useDataSource(MkDataSource(database.ConnectionString)); Postgres.Configuration.UseDataSource(MkDataSource(database.ConnectionString));
return new ThrowawayPostgresDb(database); return new ThrowawayPostgresDb(database);
} }

View File

@ -14,9 +14,11 @@ public static class SqliteCSharpExtensionTests
{ {
private static Task LoadDocs() => SqliteCSharpTests.LoadDocs(); private static Task LoadDocs() => SqliteCSharpTests.LoadDocs();
/// <summary>
/// Integration tests for the SQLite extension methods
/// </summary>
[Tests] [Tests]
public static Test Integration = public static readonly Test Integration = TestList("Extensions", new[]
TestList("Extensions", new[]
{ {
TestList("CustomSingle", new[] TestList("CustomSingle", new[]
{ {
@ -26,8 +28,7 @@ public static class SqliteCSharpExtensionTests
await using var conn = Sqlite.Configuration.DbConn(); await using var conn = Sqlite.Configuration.DbConn();
await LoadDocs(); await LoadDocs();
var doc = await conn.CustomSingle( var doc = await conn.CustomSingle($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
new[] { Parameters.Id("one") }, Results.FromData<JsonDocument>); new[] { Parameters.Id("one") }, Results.FromData<JsonDocument>);
Expect.isNotNull(doc, "There should have been a document returned"); Expect.isNotNull(doc, "There should have been a document returned");
Expect.equal(doc!.Id, "one", "The incorrect document was returned"); Expect.equal(doc!.Id, "one", "The incorrect document was returned");
@ -38,8 +39,7 @@ public static class SqliteCSharpExtensionTests
await using var conn = Sqlite.Configuration.DbConn(); await using var conn = Sqlite.Configuration.DbConn();
await LoadDocs(); await LoadDocs();
var doc = await conn.CustomSingle( var doc = await conn.CustomSingle($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
new[] { Parameters.Id("eighty") }, Results.FromData<JsonDocument>); new[] { Parameters.Id("eighty") }, Results.FromData<JsonDocument>);
Expect.isNull(doc, "There should not have been a document returned"); Expect.isNull(doc, "There should not have been a document returned");
}) })
@ -87,8 +87,7 @@ public static class SqliteCSharpExtensionTests
await using var conn = Sqlite.Configuration.DbConn(); await using var conn = Sqlite.Configuration.DbConn();
await LoadDocs(); await LoadDocs();
await conn.CustomNonQuery( await conn.CustomNonQuery($"DELETE FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value",
$"DELETE FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value",
new[] { new SqliteParameter("@value", 100) }); new[] { new SqliteParameter("@value", 100) });
var remaining = await conn.CountAll(SqliteDb.TableName); var remaining = await conn.CountAll(SqliteDb.TableName);
@ -325,8 +324,7 @@ public static class SqliteCSharpExtensionTests
await using var conn = Sqlite.Configuration.DbConn(); await using var conn = Sqlite.Configuration.DbConn();
await LoadDocs(); await LoadDocs();
var doc = await conn.FindFirstByField<JsonDocument>(SqliteDb.TableName, "Value", Op.EQ, var doc = await conn.FindFirstByField<JsonDocument>(SqliteDb.TableName, "Value", Op.EQ, "another");
"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");
}), }),
@ -336,8 +334,7 @@ public static class SqliteCSharpExtensionTests
await using var conn = Sqlite.Configuration.DbConn(); await using var conn = Sqlite.Configuration.DbConn();
await LoadDocs(); await LoadDocs();
var doc = await conn.FindFirstByField<JsonDocument>(SqliteDb.TableName, "Sub.Foo", Op.EQ, var doc = await conn.FindFirstByField<JsonDocument>(SqliteDb.TableName, "Sub.Foo", Op.EQ, "green");
"green");
Expect.isNotNull(doc, "There should have been a document returned"); Expect.isNotNull(doc, "There should have been a document returned");
Expect.contains(new[] { "two", "four" }, doc!.Id, "An incorrect document was returned"); Expect.contains(new[] { "two", "four" }, doc!.Id, "An incorrect document was returned");
}), }),
@ -347,8 +344,7 @@ public static class SqliteCSharpExtensionTests
await using var conn = Sqlite.Configuration.DbConn(); await using var conn = Sqlite.Configuration.DbConn();
await LoadDocs(); await LoadDocs();
var doc = await conn.FindFirstByField<JsonDocument>(SqliteDb.TableName, "Value", Op.EQ, var doc = await conn.FindFirstByField<JsonDocument>(SqliteDb.TableName, "Value", Op.EQ, "absent");
"absent");
Expect.isNull(doc, "There should not have been a document returned"); Expect.isNull(doc, "There should not have been a document returned");
}) })
}), }),
@ -443,8 +439,7 @@ public static class SqliteCSharpExtensionTests
await using var conn = Sqlite.Configuration.DbConn(); await using var conn = Sqlite.Configuration.DbConn();
await LoadDocs(); await LoadDocs();
await conn.UpdatePartialByField(SqliteDb.TableName, "Value", Op.EQ, "purple", await conn.UpdatePartialByField(SqliteDb.TableName, "Value", Op.EQ, "purple", new { NumValue = 77 });
new { NumValue = 77 });
var after = await conn.CountByField(SqliteDb.TableName, "NumValue", Op.EQ, 77); var after = await conn.CountByField(SqliteDb.TableName, "NumValue", Op.EQ, 77);
Expect.equal(after, 2L, "There should have been 2 documents returned"); Expect.equal(after, 2L, "There should have been 2 documents returned");
}), }),
@ -456,8 +451,7 @@ public static class SqliteCSharpExtensionTests
Expect.isEmpty(before, "There should have been no documents returned"); Expect.isEmpty(before, "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.UpdatePartialByField(SqliteDb.TableName, "Value", Op.EQ, "burgundy", await conn.UpdatePartialByField(SqliteDb.TableName, "Value", Op.EQ, "burgundy", new { Foo = "green" });
new { Foo = "green" });
}) })
}), }),
TestList("DeleteById", new[] TestList("DeleteById", new[]

View File

@ -16,9 +16,7 @@ public static class SqliteCSharpTests
/// <summary> /// <summary>
/// Unit tests for the SQLite library /// Unit tests for the SQLite library
/// </summary> /// </summary>
[Tests] private static readonly Test Unit = TestList("Unit", new[]
public static Test Unit =
TestList("Unit", new[]
{ {
TestList("Query", new[] TestList("Query", new[]
{ {
@ -80,14 +78,15 @@ public static class SqliteCSharpTests
new() { Id = "five", Value = "purple", NumValue = 18 } new() { Id = "five", Value = "purple", NumValue = 18 }
}; };
/// <summary>
/// Add the test documents to the database
/// </summary>
internal static async Task LoadDocs() internal static async Task LoadDocs()
{ {
foreach (var doc in TestDocuments) await Document.Insert(SqliteDb.TableName, doc); foreach (var doc in TestDocuments) await Document.Insert(SqliteDb.TableName, doc);
} }
[Tests] private static readonly Test Integration = TestList("Integration", new[]
public static Test Integration =
TestList("Integration", new[]
{ {
TestCase("Configuration.UseConnectionString succeeds", () => TestCase("Configuration.UseConnectionString succeeds", () =>
{ {
@ -95,8 +94,7 @@ public static class SqliteCSharpTests
{ {
Sqlite.Configuration.UseConnectionString("Data Source=test.db"); Sqlite.Configuration.UseConnectionString("Data Source=test.db");
Expect.equal(Sqlite.Configuration.connectionString, Expect.equal(Sqlite.Configuration.connectionString,
new FSharpOption<string>("Data Source=test.db;Foreign Keys=True"), new FSharpOption<string>("Data Source=test.db;Foreign Keys=True"), "Connection string incorrect");
"Connection string incorrect");
} }
finally finally
{ {
@ -112,8 +110,7 @@ public static class SqliteCSharpTests
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
await LoadDocs(); await LoadDocs();
var doc = await Custom.Single( var doc = await Custom.Single($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
new[] { Parameters.Id("one") }, Results.FromData<JsonDocument>); new[] { Parameters.Id("one") }, Results.FromData<JsonDocument>);
Expect.isNotNull(doc, "There should have been a document returned"); Expect.isNotNull(doc, "There should have been a document returned");
Expect.equal(doc!.Id, "one", "The incorrect document was returned"); Expect.equal(doc!.Id, "one", "The incorrect document was returned");
@ -123,8 +120,7 @@ public static class SqliteCSharpTests
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
await LoadDocs(); await LoadDocs();
var doc = await Custom.Single( var doc = await Custom.Single($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
new[] { Parameters.Id("eighty") }, Results.FromData<JsonDocument>); new[] { Parameters.Id("eighty") }, Results.FromData<JsonDocument>);
Expect.isNull(doc, "There should not have been a document returned"); Expect.isNull(doc, "There should not have been a document returned");
}) })
@ -168,8 +164,7 @@ public static class SqliteCSharpTests
await using var db = await SqliteDb.BuildDb(); await using var db = await SqliteDb.BuildDb();
await LoadDocs(); await LoadDocs();
await Custom.NonQuery( await Custom.NonQuery($"DELETE FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value",
$"DELETE FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value",
new[] { new SqliteParameter("@value", 100) }); new[] { new SqliteParameter("@value", 100) });
var remaining = await Count.All(SqliteDb.TableName); var remaining = await Count.All(SqliteDb.TableName);
@ -207,8 +202,7 @@ public static class SqliteCSharpTests
{ {
var result = await Custom.Scalar( var result = await Custom.Scalar(
$"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = @name) AS it", $"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = @name) AS it",
new SqliteParameter[] { new("@name", name) }, new SqliteParameter[] { new("@name", name) }, rdr => rdr.GetInt64(0));
rdr => rdr.GetInt64(0));
return result > 0L; return result > 0L;
} }
}) })
@ -582,5 +576,6 @@ public static class SqliteCSharpTests
/// <summary> /// <summary>
/// All tests for SQLite C# functions and methods /// All tests for SQLite C# functions and methods
/// </summary> /// </summary>
[Tests]
public static readonly Test All = TestList("Sqlite.C#", new[] { Unit, TestSequenced(Integration) }); public static readonly Test All = TestList("Sqlite.C#", new[] { Unit, TestSequenced(Integration) });
} }

View File

@ -39,15 +39,15 @@ let unitTests =
$"CREATE TABLE IF NOT EXISTS {PostgresDb.TableName} (data JSONB NOT NULL)" $"CREATE TABLE IF NOT EXISTS {PostgresDb.TableName} (data JSONB NOT NULL)"
"CREATE TABLE statement not constructed correctly" "CREATE TABLE statement not constructed correctly"
} }
test "ensureJsonIndex succeeds for full index" { test "ensureDocumentIndex succeeds for full index" {
Expect.equal Expect.equal
(Query.Definition.ensureJsonIndex "schema.tbl" Full) (Query.Definition.ensureDocumentIndex "schema.tbl" Full)
"CREATE INDEX IF NOT EXISTS idx_tbl_document ON schema.tbl USING GIN (data)" "CREATE INDEX IF NOT EXISTS idx_tbl_document ON schema.tbl USING GIN (data)"
"CREATE INDEX statement not constructed correctly" "CREATE INDEX statement not constructed correctly"
} }
test "ensureJsonIndex succeeds for JSONB Path Ops index" { test "ensureDocumentIndex succeeds for JSONB Path Ops index" {
Expect.equal Expect.equal
(Query.Definition.ensureJsonIndex PostgresDb.TableName Optimized) (Query.Definition.ensureDocumentIndex PostgresDb.TableName Optimized)
(sprintf "CREATE INDEX IF NOT EXISTS idx_%s_document ON %s USING GIN (data jsonb_path_ops)" (sprintf "CREATE INDEX IF NOT EXISTS idx_%s_document ON %s USING GIN (data jsonb_path_ops)"
PostgresDb.TableName PostgresDb.TableName) PostgresDb.TableName PostgresDb.TableName)
"CREATE INDEX statement not constructed correctly" "CREATE INDEX statement not constructed correctly"
@ -266,7 +266,7 @@ let integrationTests =
Expect.isTrue exists' "The table should now exist" Expect.isTrue exists' "The table should now exist"
Expect.isTrue alsoExists' "The key index should now exist" Expect.isTrue alsoExists' "The key index should now exist"
} }
testTask "ensureJsonIndex succeeds" { testTask "ensureDocumentIndex succeeds" {
use db = PostgresDb.BuildDb() use db = PostgresDb.BuildDb()
let indexExists () = let indexExists () =
Custom.scalar Custom.scalar
@ -278,7 +278,7 @@ let integrationTests =
Expect.isFalse exists "The index should not exist already" Expect.isFalse exists "The index should not exist already"
do! Definition.ensureTable "ensured" do! Definition.ensureTable "ensured"
do! Definition.ensureJsonIndex "ensured" Optimized do! Definition.ensureDocumentIndex "ensured" Optimized
let! exists' = indexExists () let! exists' = indexExists ()
Expect.isTrue exists' "The index should now exist" Expect.isTrue exists' "The index should now exist"
} }
@ -730,7 +730,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! Update.partialByContains PostgresDb.TableName {| Value = "burgundy" |} {| Foo = "green" |} do! Update.partialByJsonPath PostgresDb.TableName "$.NumValue ? (@ < 0)" {| Foo = "green" |}
} }
] ]
] ]