v3 RC1 #1

Merged
danieljsummers merged 25 commits from merge-projects into main 2024-01-06 20:51:49 +00:00
6 changed files with 104 additions and 53 deletions
Showing only changes of commit 52c00d2485 - Show all commits

View File

@ -29,8 +29,8 @@ module Extensions =
WithConn.Definition.ensureTable name conn WithConn.Definition.ensureTable name conn
/// Create an index on a document table /// Create an index on a document table
member conn.ensureIndex tableName indexName fields = member conn.ensureFieldIndex tableName indexName fields =
WithConn.Definition.ensureIndex tableName indexName fields conn WithConn.Definition.ensureFieldIndex tableName indexName fields conn
/// Insert a new document /// Insert a new document
member conn.insert<'TDoc> tableName (document: 'TDoc) = member conn.insert<'TDoc> tableName (document: 'TDoc) =
@ -131,8 +131,8 @@ type SqliteConnectionCSharpExtensions =
/// Create an index on one or more fields in a document table /// Create an index on one or more fields in a document table
[<Extension>] [<Extension>]
static member inline EnsureIndex(conn, tableName, indexName, fields) = static member inline EnsureFieldIndex(conn, tableName, indexName, fields) =
WithConn.Definition.ensureIndex tableName indexName fields conn WithConn.Definition.ensureFieldIndex tableName indexName fields conn
/// Insert a new document /// Insert a new document
[<Extension>] [<Extension>]

View File

@ -104,20 +104,15 @@ module Results =
return List.ofSeq it return List.ofSeq it
} }
/// Create a list of items for the results of the given command, using the specified mapping function /// Extract a count from the first column
let ToCustomList<'TDoc>(cmd, mapFunc: System.Func<SqliteDataReader, 'TDoc>) = backgroundTask { [<CompiledName "ToCount">]
let! results = toCustomList<'TDoc> cmd mapFunc.Invoke let toCount (row: SqliteDataReader) =
return ResizeArray<'TDoc> results row.GetInt64 0
}
/// Create a list of items for the results of the given command /// Extract a true/false value from a count in the first column
[<CompiledName "FSharpToDocumentList">] [<CompiledName "ToExists">]
let toDocumentList<'TDoc> (cmd: SqliteCommand) = let toExists row =
toCustomList<'TDoc> cmd fromData toCount(row) > 0L
/// Create a list of items for the results of the given command
let ToDocumentList<'TDoc> cmd =
ToCustomList<'TDoc>(cmd, fromData<'TDoc>)
[<AutoOpen>] [<AutoOpen>]
@ -203,8 +198,8 @@ module WithConn =
} }
/// Create an index on a document table /// Create an index on a document table
[<CompiledName "EnsureIndex">] [<CompiledName "EnsureFieldIndex">]
let ensureIndex tableName indexName fields conn = let ensureFieldIndex tableName indexName fields conn =
Custom.nonQuery (Query.Definition.ensureIndexOn tableName indexName fields) [] conn Custom.nonQuery (Query.Definition.ensureIndexOn tableName indexName fields) [] conn
/// Insert a new document /// Insert a new document
@ -224,30 +219,26 @@ module WithConn =
/// Count all documents in a table /// Count all documents in a table
[<CompiledName "All">] [<CompiledName "All">]
let all tableName conn = let all tableName conn =
Custom.scalar (Query.Count.all tableName) [] (_.GetInt64(0)) conn Custom.scalar (Query.Count.all tableName) [] toCount conn
/// Count matching documents using a comparison on a JSON field /// Count matching documents using a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op (value: obj) conn = let byField tableName fieldName op (value: obj) conn =
Custom.scalar (Query.Count.byField tableName fieldName op) [ fieldParam value ] (_.GetInt64(0)) conn Custom.scalar (Query.Count.byField tableName fieldName op) [ fieldParam value ] toCount conn
/// Commands to determine if documents exist /// Commands to determine if documents exist
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
module Exists = module Exists =
/// SQLite returns a 0 for not-exists and 1 for exists
let private exists (rdr: SqliteDataReader) =
rdr.GetInt64(0) > 0
/// Determine if a document exists for the given ID /// Determine if a document exists for the given ID
[<CompiledName "ById">] [<CompiledName "ById">]
let byId tableName (docId: 'TKey) conn = let byId tableName (docId: 'TKey) conn =
Custom.scalar (Query.Exists.byId tableName) [ idParam docId ] exists conn Custom.scalar (Query.Exists.byId tableName) [ idParam docId ] toExists conn
/// Determine if a document exists using a comparison on a JSON field /// Determine if a document exists using a comparison on a JSON field
[<CompiledName "ByField">] [<CompiledName "ByField">]
let byField tableName fieldName op (value: obj) conn = let byField tableName fieldName op (value: obj) conn =
Custom.scalar (Query.Exists.byField tableName fieldName op) [ fieldParam value ] exists conn Custom.scalar (Query.Exists.byField tableName fieldName op) [ fieldParam value ] toExists conn
/// Commands to retrieve documents /// Commands to retrieve documents
[<RequireQualifiedAccess>] [<RequireQualifiedAccess>]
@ -392,6 +383,12 @@ module Definition =
use conn = Configuration.dbConn () use conn = Configuration.dbConn ()
WithConn.Definition.ensureTable name conn WithConn.Definition.ensureTable name conn
/// Create an index on a document table
[<CompiledName "EnsureFieldIndex">]
let ensureFieldIndex tableName indexName fields =
use conn = Configuration.dbConn ()
WithConn.Definition.ensureFieldIndex tableName indexName fields conn
/// Document insert/save functions /// Document insert/save functions
[<AutoOpen>] [<AutoOpen>]
module Document = module Document =

View File

@ -108,12 +108,9 @@ public static class SqliteCSharpExtensionTests
await using var conn = Sqlite.Configuration.DbConn(); await using var conn = Sqlite.Configuration.DbConn();
Func<string, ValueTask<bool>> itExists = async name => Func<string, ValueTask<bool>> itExists = async name =>
{ await conn.CustomScalar(
var result = await conn.CustomScalar(
$"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) }, rdr => rdr.GetInt64(0)); new SqliteParameter[] { new("@name", name) }, Results.ToExists);
return result > 0L;
};
var exists = await itExists("ensured"); var exists = await itExists("ensured");
var alsoExists = await itExists("idx_ensured_key"); var alsoExists = await itExists("idx_ensured_key");
@ -127,6 +124,22 @@ public static class SqliteCSharpExtensionTests
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");
}), }),
TestCase("EnsureFieldIndex succeeds", async () =>
{
await using var db = await SqliteDb.BuildDb();
await using var conn = Sqlite.Configuration.DbConn();
var indexExists = () => conn.CustomScalar(
$"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = 'idx_ensured_test') AS it",
Parameters.None, Results.ToExists);
var exists = await indexExists();
Expect.isFalse(exists, "The index should not exist already");
await conn.EnsureTable("ensured");
await conn.EnsureFieldIndex("ensured", "test", new[] { "Id", "Category" });
exists = await indexExists();
Expect.isTrue(exists, "The index should now exist");
}),
TestList("Insert", new[] TestList("Insert", new[]
{ {
TestCase("succeeds", async () => TestCase("succeeds", async () =>

View File

@ -200,11 +200,25 @@ public static class SqliteCSharpTests
async ValueTask<bool> ItExists(string name) async ValueTask<bool> ItExists(string name)
{ {
var result = await Custom.Scalar( return 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) }, rdr => rdr.GetInt64(0)); new SqliteParameter[] { new("@name", name) }, Results.ToExists);
return result > 0L;
} }
}),
TestCase("EnsureFieldIndex succeeds", async () =>
{
await using var db = await SqliteDb.BuildDb();
var indexExists = () => Custom.Scalar(
$"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = '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.Insert", new[] TestList("Document.Insert", new[]

View File

@ -16,14 +16,11 @@ let integrationTests =
testTask "ensureTable succeeds" { testTask "ensureTable succeeds" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
use conn = Configuration.dbConn () use conn = Configuration.dbConn ()
let itExists (name: string) = task { let itExists (name: string) =
let! result =
conn.customScalar conn.customScalar
$"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = @name) AS it" $"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = @name) AS it"
[ SqliteParameter("@name", name) ] [ SqliteParameter("@name", name) ]
_.GetInt64(0) toExists
return result > 0
}
let! exists = itExists "ensured" let! exists = itExists "ensured"
let! alsoExists = itExists "idx_ensured_key" let! alsoExists = itExists "idx_ensured_key"
@ -36,6 +33,23 @@ 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 "ensureFieldIndex succeeds" {
use! db = SqliteDb.BuildDb()
use conn = Configuration.dbConn ()
let indexExists () =
conn.customScalar
$"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = 'idx_ensured_test') AS it"
[]
toExists
let! exists = indexExists ()
Expect.isFalse exists "The index should not exist already"
do! conn.ensureTable "ensured"
do! conn.ensureFieldIndex "ensured" "test" [ "Name"; "Age" ]
let! exists' = indexExists ()
Expect.isTrue exists' "The index should now exist"
}
testList "insert" [ testList "insert" [
testTask "succeeds" { testTask "succeeds" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()

View File

@ -184,14 +184,11 @@ let integrationTests =
testList "Definition" [ testList "Definition" [
testTask "ensureTable succeeds" { testTask "ensureTable succeeds" {
use! db = SqliteDb.BuildDb() use! db = SqliteDb.BuildDb()
let itExists (name: string) = task { let itExists (name: string) =
let! result =
Custom.scalar 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"
[ SqliteParameter("@name", name) ] [ SqliteParameter("@name", name) ]
_.GetInt64(0) toExists
return result > 0
}
let! exists = itExists "ensured" let! exists = itExists "ensured"
let! alsoExists = itExists "idx_ensured_key" let! alsoExists = itExists "idx_ensured_key"
@ -204,6 +201,22 @@ 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 "ensureFieldIndex succeeds" {
use! db = SqliteDb.BuildDb()
let indexExists () =
Custom.scalar
$"SELECT EXISTS (SELECT 1 FROM {SqliteDb.Catalog} WHERE name = 'idx_ensured_test') AS it"
[]
toExists
let! exists = indexExists ()
Expect.isFalse exists "The index should not exist already"
do! Definition.ensureTable "ensured"
do! Definition.ensureFieldIndex "ensured" "test" [ "Name"; "Age" ]
let! exists' = indexExists ()
Expect.isTrue exists' "The index should now exist"
}
] ]
testList "insert" [ testList "insert" [
testTask "succeeds" { testTask "succeeds" {