Version 4 rc1 (#6)
Changes in this version: - **BREAKING CHANGE**: All `*byField`/`*ByField` functions are now `*byFields`/`*ByFields`, and take a `FieldMatch` case before the list of fields. The `Compat` namespace in both libraries will assist in this transition. In support of this change, the `Field` parameter name is optional; the library will generate parameter names for it if they are not specified. - **BREAKING CHANGE**: The `Query` namespaces have had some significant work, particularly from the full-query perspective. Most have been broken up into the base query and modifiers `by*` that will combine the base query with the `WHERE` clause needed to satisfy the criteria. - **FEATURE / BREAKING CHANGE**: PostgreSQL document fields will now be cast to numeric if the parameter value passed to the query is numeric. This drove the `Query` breaking changes, as the fields need to have their intended value for the library to generate the appropriate SQL. Additionally, if code assumes the library can be given something like `8` and transform it to `"8"`, this is no longer the case. - **FEATURE**: All `Find` queries (except `byId`/`ById`) now have a version with the `Ordered` suffix. These take a list of fields by which the query should be ordered. A new `Field` method called `Named` can assist with creating these fields. Prefixing the field name with `n:` will cast the field to numeric in PostgreSQL (and will be ignored by SQLite); adding " DESC" to the field name will sort it descending (Z-A, high to low) instead of ascending (A-Z, low to high). - **BREAKING CHANGE** (PostgreSQL only): `fieldNameParam`/`Parameters.FieldName` are now plural. The function still only generates one parameter, but the name is now the same between PostgreSQL and SQLite. The goal of this library is to abstract the differences away as much as practical, and this furthers that end. There are functions with these names in the `Compat` namespace. - **FEATURE**: In the F# v3 library, lists of parameters were expected to be F#'s `List` type, and the C# version took either `List<T>` or `IEnumerable<T>`. In this version, these all expect `seq`/`IEnumerable<T>`. F#'s `List` satisfies the `seq` constraints, so this should not be a breaking change. - **FEATURE**: `Field`s now may have qualifiers; this allows tables to be aliased when joining multiple tables (as all have the same `data` column). F# users can use `with` to specify this at creation, and both F# and C# can use the `WithQualifier` method to create a field with the qualifier specified. Parameter names for fields may be specified in a similar way, substituting `ParameterName` for `Qualifier`. Reviewed-on: #6
This commit was merged in pull request #6.
This commit is contained in:
@@ -8,6 +8,7 @@
|
||||
<ItemGroup>
|
||||
<Compile Include="Library.fs" />
|
||||
<Compile Include="Extensions.fs" />
|
||||
<Compile Include="Compat.fs" />
|
||||
<None Include="README.md" Pack="true" PackagePath="\" />
|
||||
<None Include="..\icon.png" Pack="true" PackagePath="\" />
|
||||
</ItemGroup>
|
||||
|
||||
269
src/Sqlite/Compat.fs
Normal file
269
src/Sqlite/Compat.fs
Normal file
@@ -0,0 +1,269 @@
|
||||
namespace BitBadger.Documents.Sqlite.Compat
|
||||
|
||||
open BitBadger.Documents
|
||||
open BitBadger.Documents.Sqlite
|
||||
|
||||
[<AutoOpen>]
|
||||
module Parameters =
|
||||
|
||||
/// Create a JSON field parameter
|
||||
[<CompiledName "AddField">]
|
||||
[<System.Obsolete "Use addFieldParams (F#) / AddFields (C#) instead ~ will be removed in v4.1">]
|
||||
let addFieldParam name field parameters =
|
||||
addFieldParams [ { field with ParameterName = Some name } ] parameters
|
||||
|
||||
/// Append JSON field name parameters for the given field names to the given parameters
|
||||
[<CompiledName "FieldName">]
|
||||
[<System.Obsolete "Use fieldNameParams (F#) / FieldNames (C#) instead ~ will be removed in v4.1">]
|
||||
let fieldNameParam fieldNames =
|
||||
fieldNameParams fieldNames
|
||||
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Query =
|
||||
|
||||
/// Create a WHERE clause fragment to implement a comparison on a field in a JSON document
|
||||
[<CompiledName "WhereByField">]
|
||||
[<System.Obsolete "Use WhereByFields instead ~ will be removed in v4.1">]
|
||||
let whereByField field paramName =
|
||||
Query.whereByFields Any [ { field with ParameterName = Some paramName } ]
|
||||
|
||||
|
||||
module WithConn =
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Count =
|
||||
|
||||
/// Count matching documents using a JSON field comparison (->> =)
|
||||
[<CompiledName "ByField">]
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let byField tableName field conn =
|
||||
WithConn.Count.byFields tableName Any [ field ] conn
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Exists =
|
||||
|
||||
/// Determine if a document exists using a JSON field comparison (->> =)
|
||||
[<CompiledName "ByField">]
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let byField tableName field conn =
|
||||
WithConn.Exists.byFields tableName Any [ field ] conn
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Find =
|
||||
|
||||
/// Retrieve documents matching a JSON field comparison (->> =)
|
||||
[<CompiledName "FSharpByField">]
|
||||
[<System.Obsolete "Use byFields instead ~ will be removed in v4.1">]
|
||||
let byField<'TDoc> tableName field conn =
|
||||
WithConn.Find.byFields<'TDoc> tableName Any [ field ] conn
|
||||
|
||||
/// Retrieve documents matching a JSON field comparison (->> =)
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let ByField<'TDoc>(tableName, field, conn) =
|
||||
WithConn.Find.ByFields<'TDoc>(tableName, Any, Seq.singleton field, conn)
|
||||
|
||||
/// Retrieve the first document matching a JSON field comparison (->> =); returns None if not found
|
||||
[<CompiledName "FSharpFirstByField">]
|
||||
[<System.Obsolete "Use firstByFields instead ~ will be removed in v4.1">]
|
||||
let firstByField<'TDoc> tableName field conn =
|
||||
WithConn.Find.firstByFields<'TDoc> tableName Any [ field ] conn
|
||||
|
||||
/// Retrieve the first document matching a JSON field comparison (->> =); returns null if not found
|
||||
[<System.Obsolete "Use FirstByFields instead ~ will be removed in v4.1">]
|
||||
let FirstByField<'TDoc when 'TDoc: null>(tableName, field, conn) =
|
||||
WithConn.Find.FirstByFields<'TDoc>(tableName, Any, Seq.singleton field, conn)
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Patch =
|
||||
|
||||
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
|
||||
[<CompiledName "ByField">]
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let byField tableName field (patch: 'TPatch) conn =
|
||||
WithConn.Patch.byFields tableName Any [ field ] patch conn
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module RemoveFields =
|
||||
|
||||
/// Remove fields from documents via a comparison on a JSON field in the document
|
||||
[<CompiledName "ByField">]
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let byField tableName field fieldNames conn =
|
||||
WithConn.RemoveFields.byFields tableName Any [ field ] fieldNames conn
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Delete =
|
||||
|
||||
/// Delete documents by matching a JSON field comparison query (->> =)
|
||||
[<CompiledName "ByField">]
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let byField tableName field conn =
|
||||
WithConn.Delete.byFields tableName Any [ field ] conn
|
||||
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Count =
|
||||
|
||||
/// Count matching documents using a JSON field comparison (->> =)
|
||||
[<CompiledName "ByField">]
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let byField tableName field =
|
||||
Count.byFields tableName Any [ field ]
|
||||
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Exists =
|
||||
|
||||
/// Determine if a document exists using a JSON field comparison (->> =)
|
||||
[<CompiledName "ByField">]
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let byField tableName field =
|
||||
Exists.byFields tableName Any [ field ]
|
||||
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Find =
|
||||
|
||||
/// Retrieve documents matching a JSON field comparison (->> =)
|
||||
[<CompiledName "FSharpByField">]
|
||||
[<System.Obsolete "Use byFields instead ~ will be removed in v4.1">]
|
||||
let byField<'TDoc> tableName field =
|
||||
Find.byFields<'TDoc> tableName Any [ field ]
|
||||
|
||||
/// Retrieve documents matching a JSON field comparison (->> =)
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let ByField<'TDoc>(tableName, field) =
|
||||
Find.ByFields<'TDoc>(tableName, Any, Seq.singleton field)
|
||||
|
||||
/// Retrieve the first document matching a JSON field comparison (->> =); returns None if not found
|
||||
[<CompiledName "FSharpFirstByField">]
|
||||
[<System.Obsolete "Use firstByFields instead ~ will be removed in v4.1">]
|
||||
let firstByField<'TDoc> tableName field =
|
||||
Find.firstByFields<'TDoc> tableName Any [ field ]
|
||||
|
||||
/// Retrieve the first document matching a JSON field comparison (->> =); returns null if not found
|
||||
[<System.Obsolete "Use FirstByFields instead ~ will be removed in v4.1">]
|
||||
let FirstByField<'TDoc when 'TDoc: null>(tableName, field) =
|
||||
Find.FirstByFields<'TDoc>(tableName, Any, Seq.singleton field)
|
||||
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Patch =
|
||||
|
||||
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
|
||||
[<CompiledName "ByField">]
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let byField tableName field (patch: 'TPatch) =
|
||||
Patch.byFields tableName Any [ field ] patch
|
||||
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module RemoveFields =
|
||||
|
||||
/// Remove fields from documents via a comparison on a JSON field in the document
|
||||
[<CompiledName "ByField">]
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let byField tableName field fieldNames =
|
||||
RemoveFields.byFields tableName Any [ field ] fieldNames
|
||||
|
||||
|
||||
[<RequireQualifiedAccess>]
|
||||
module Delete =
|
||||
|
||||
/// Delete documents by matching a JSON field comparison query (->> =)
|
||||
[<CompiledName "ByField">]
|
||||
[<System.Obsolete "Use ByFields instead ~ will be removed in v4.1">]
|
||||
let byField tableName field =
|
||||
Delete.byFields tableName Any [ field ]
|
||||
|
||||
|
||||
open Microsoft.Data.Sqlite
|
||||
|
||||
/// F# Extensions for the NpgsqlConnection type
|
||||
[<AutoOpen>]
|
||||
module Extensions =
|
||||
|
||||
type SqliteConnection with
|
||||
|
||||
/// Count matching documents using a JSON field comparison query (->> =)
|
||||
[<System.Obsolete "Use countByFields instead ~ will be removed in v4.1">]
|
||||
member conn.countByField tableName field =
|
||||
conn.countByFields tableName Any [ field ]
|
||||
|
||||
/// Determine if documents exist using a JSON field comparison query (->> =)
|
||||
[<System.Obsolete "Use existsByFields instead ~ will be removed in v4.1">]
|
||||
member conn.existsByField tableName field =
|
||||
conn.existsByFields tableName Any [ field ]
|
||||
|
||||
/// Retrieve documents matching a JSON field comparison query (->> =)
|
||||
[<System.Obsolete "Use findByFields instead ~ will be removed in v4.1">]
|
||||
member conn.findByField<'TDoc> tableName field =
|
||||
conn.findByFields<'TDoc> tableName Any [ field ]
|
||||
|
||||
/// Retrieve the first document matching a JSON field comparison query (->> =); returns None if not found
|
||||
[<System.Obsolete "Use findFirstByFields instead ~ will be removed in v4.1">]
|
||||
member conn.findFirstByField<'TDoc> tableName field =
|
||||
conn.findFirstByFields<'TDoc> tableName Any [ field ]
|
||||
|
||||
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
|
||||
[<System.Obsolete "Use patchByFields instead ~ will be removed in v4.1">]
|
||||
member conn.patchByField tableName field (patch: 'TPatch) =
|
||||
conn.patchByFields tableName Any [ field ] patch
|
||||
|
||||
/// Remove fields from documents via a comparison on a JSON field in the document
|
||||
[<System.Obsolete "Use removeFieldsByFields instead ~ will be removed in v4.1">]
|
||||
member conn.removeFieldsByField tableName field fieldNames =
|
||||
conn.removeFieldsByFields tableName Any [ field ] fieldNames
|
||||
|
||||
/// Delete documents by matching a JSON field comparison query (->> =)
|
||||
[<System.Obsolete "Use deleteByFields instead ~ will be removed in v4.1">]
|
||||
member conn.deleteByField tableName field =
|
||||
conn.deleteByFields tableName Any [ field ]
|
||||
|
||||
|
||||
open System.Runtime.CompilerServices
|
||||
|
||||
type SqliteConnectionCSharpCompatExtensions =
|
||||
|
||||
/// Count matching documents using a JSON field comparison query (->> =)
|
||||
[<Extension>]
|
||||
[<System.Obsolete "Use CountByFields instead ~ will be removed in v4.1">]
|
||||
static member inline CountByField(conn, tableName, field) =
|
||||
WithConn.Count.byFields tableName Any [ field ] conn
|
||||
|
||||
/// Determine if documents exist using a JSON field comparison query (->> =)
|
||||
[<Extension>]
|
||||
[<System.Obsolete "Use ExistsByFields instead ~ will be removed in v4.1">]
|
||||
static member inline ExistsByField(conn, tableName, field) =
|
||||
WithConn.Exists.byFields tableName Any [ field ] conn
|
||||
|
||||
/// Retrieve documents matching a JSON field comparison query (->> =)
|
||||
[<Extension>]
|
||||
[<System.Obsolete "Use FindByFields instead ~ will be removed in v4.1">]
|
||||
static member inline FindByField<'TDoc>(conn, tableName, field) =
|
||||
WithConn.Find.ByFields<'TDoc>(tableName, Any, [ field ], conn)
|
||||
|
||||
/// Retrieve the first document matching a JSON field comparison query (->> =); returns null if not found
|
||||
[<Extension>]
|
||||
[<System.Obsolete "Use FindFirstByFields instead ~ will be removed in v4.1">]
|
||||
static member inline FindFirstByField<'TDoc when 'TDoc: null>(conn, tableName, field) =
|
||||
WithConn.Find.FirstByFields<'TDoc>(tableName, Any, [ field ], conn)
|
||||
|
||||
/// Patch documents using a JSON field comparison query in the WHERE clause (->> =)
|
||||
[<Extension>]
|
||||
[<System.Obsolete "Use PatchByFields instead ~ will be removed in v4.1">]
|
||||
static member inline PatchByField(conn, tableName, field, patch: 'TPatch) =
|
||||
WithConn.Patch.byFields tableName Any [ field ] patch conn
|
||||
|
||||
/// Remove fields from documents via a comparison on a JSON field in the document
|
||||
[<Extension>]
|
||||
[<System.Obsolete "Use RemoveFieldsByFields instead ~ will be removed in v4.1">]
|
||||
static member inline RemoveFieldsByField(conn, tableName, field, fieldNames) =
|
||||
WithConn.RemoveFields.byFields tableName Any [ field ] fieldNames conn
|
||||
|
||||
/// Delete documents by matching a JSON field comparison query (->> =)
|
||||
[<Extension>]
|
||||
[<System.Obsolete "Use DeleteByFields instead ~ will be removed in v4.1">]
|
||||
static member inline DeleteByField(conn, tableName, field) =
|
||||
WithConn.Delete.byFields tableName Any [ field ] conn
|
||||
@@ -1,5 +1,6 @@
|
||||
namespace BitBadger.Documents.Sqlite
|
||||
|
||||
open BitBadger.Documents
|
||||
open Microsoft.Data.Sqlite
|
||||
|
||||
/// F# extensions for the SqliteConnection type
|
||||
@@ -34,44 +35,57 @@ module Extensions =
|
||||
|
||||
/// Insert a new document
|
||||
member conn.insert<'TDoc> tableName (document: 'TDoc) =
|
||||
WithConn.insert<'TDoc> tableName document conn
|
||||
WithConn.Document.insert<'TDoc> tableName document conn
|
||||
|
||||
/// Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
|
||||
member conn.save<'TDoc> tableName (document: 'TDoc) =
|
||||
WithConn.save tableName document conn
|
||||
WithConn.Document.save tableName document conn
|
||||
|
||||
/// Count all documents in a table
|
||||
member conn.countAll tableName =
|
||||
WithConn.Count.all tableName conn
|
||||
|
||||
/// Count matching documents using a comparison on a JSON field
|
||||
member conn.countByField tableName field =
|
||||
WithConn.Count.byField tableName field conn
|
||||
/// Count matching documents using a comparison on JSON fields
|
||||
member conn.countByFields tableName howMatched fields =
|
||||
WithConn.Count.byFields tableName howMatched fields conn
|
||||
|
||||
/// Determine if a document exists for the given ID
|
||||
member conn.existsById tableName (docId: 'TKey) =
|
||||
WithConn.Exists.byId tableName docId conn
|
||||
|
||||
/// Determine if a document exists using a comparison on a JSON field
|
||||
member conn.existsByField tableName field =
|
||||
WithConn.Exists.byField tableName field conn
|
||||
|
||||
/// Determine if a document exists using a comparison on JSON fields
|
||||
member conn.existsByFields tableName howMatched fields =
|
||||
WithConn.Exists.byFields tableName howMatched fields conn
|
||||
|
||||
/// Retrieve all documents in the given table
|
||||
member conn.findAll<'TDoc> tableName =
|
||||
WithConn.Find.all<'TDoc> tableName conn
|
||||
|
||||
/// Retrieve all documents in the given table ordered by the given fields in the document
|
||||
member conn.findAllOrdered<'TDoc> tableName orderFields =
|
||||
WithConn.Find.allOrdered<'TDoc> tableName orderFields conn
|
||||
|
||||
/// Retrieve a document by its ID
|
||||
member conn.findById<'TKey, 'TDoc> tableName (docId: 'TKey) =
|
||||
WithConn.Find.byId<'TKey, 'TDoc> tableName docId conn
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field
|
||||
member conn.findByField<'TDoc> tableName field =
|
||||
WithConn.Find.byField<'TDoc> tableName field conn
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field, returning only the first result
|
||||
member conn.findFirstByField<'TDoc> tableName field =
|
||||
WithConn.Find.firstByField<'TDoc> tableName field conn
|
||||
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields
|
||||
member conn.findByFields<'TDoc> tableName howMatched fields =
|
||||
WithConn.Find.byFields<'TDoc> tableName howMatched fields conn
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document
|
||||
member conn.findByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields =
|
||||
WithConn.Find.byFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields, returning only the first result
|
||||
member conn.findFirstByFields<'TDoc> tableName howMatched fields =
|
||||
WithConn.Find.firstByFields<'TDoc> tableName howMatched fields conn
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document, returning
|
||||
/// only the first result
|
||||
member conn.findFirstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields =
|
||||
WithConn.Find.firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// Update an entire document by its ID
|
||||
member conn.updateById tableName (docId: 'TKey) (document: 'TDoc) =
|
||||
WithConn.Update.byId tableName docId document conn
|
||||
@@ -84,25 +98,25 @@ module Extensions =
|
||||
member conn.patchById tableName (docId: 'TKey) (patch: 'TPatch) =
|
||||
WithConn.Patch.byId tableName docId patch conn
|
||||
|
||||
/// Patch documents using a comparison on a JSON field
|
||||
member conn.patchByField tableName field (patch: 'TPatch) =
|
||||
WithConn.Patch.byField tableName field patch conn
|
||||
|
||||
/// Patch documents using a comparison on JSON fields
|
||||
member conn.patchByFields tableName howMatched fields (patch: 'TPatch) =
|
||||
WithConn.Patch.byFields tableName howMatched fields patch conn
|
||||
|
||||
/// Remove fields from a document by the document's ID
|
||||
member conn.removeFieldsById tableName (docId: 'TKey) fieldNames =
|
||||
WithConn.RemoveFields.byId tableName docId fieldNames conn
|
||||
|
||||
/// Remove a field from a document via a comparison on a JSON field in the document
|
||||
member conn.removeFieldsByField tableName field fieldNames =
|
||||
WithConn.RemoveFields.byField tableName field fieldNames conn
|
||||
/// Remove a field from a document via a comparison on JSON fields in the document
|
||||
member conn.removeFieldsByFields tableName howMatched fields fieldNames =
|
||||
WithConn.RemoveFields.byFields tableName howMatched fields fieldNames conn
|
||||
|
||||
/// Delete a document by its ID
|
||||
member conn.deleteById tableName (docId: 'TKey) =
|
||||
WithConn.Delete.byId tableName docId conn
|
||||
|
||||
/// Delete documents by matching a comparison on a JSON field
|
||||
member conn.deleteByField tableName field =
|
||||
WithConn.Delete.byField tableName field conn
|
||||
/// Delete documents by matching a comparison on JSON fields
|
||||
member conn.deleteByFields tableName howMatched fields =
|
||||
WithConn.Delete.byFields tableName howMatched fields conn
|
||||
|
||||
|
||||
open System.Runtime.CompilerServices
|
||||
@@ -145,53 +159,70 @@ type SqliteConnectionCSharpExtensions =
|
||||
/// Insert a new document
|
||||
[<Extension>]
|
||||
static member inline Insert<'TDoc>(conn, tableName, document: 'TDoc) =
|
||||
WithConn.insert<'TDoc> tableName document conn
|
||||
WithConn.Document.insert<'TDoc> tableName document conn
|
||||
|
||||
/// Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
|
||||
[<Extension>]
|
||||
static member inline Save<'TDoc>(conn, tableName, document: 'TDoc) =
|
||||
WithConn.save<'TDoc> tableName document conn
|
||||
WithConn.Document.save<'TDoc> tableName document conn
|
||||
|
||||
/// Count all documents in a table
|
||||
[<Extension>]
|
||||
static member inline CountAll(conn, tableName) =
|
||||
WithConn.Count.all tableName conn
|
||||
|
||||
/// Count matching documents using a comparison on a JSON field
|
||||
/// Count matching documents using a comparison on JSON fields
|
||||
[<Extension>]
|
||||
static member inline CountByField(conn, tableName, field) =
|
||||
WithConn.Count.byField tableName field conn
|
||||
|
||||
static member inline CountByFields(conn, tableName, howMatched, fields) =
|
||||
WithConn.Count.byFields tableName howMatched fields conn
|
||||
|
||||
/// Determine if a document exists for the given ID
|
||||
[<Extension>]
|
||||
static member inline ExistsById<'TKey>(conn, tableName, docId: 'TKey) =
|
||||
WithConn.Exists.byId tableName docId conn
|
||||
|
||||
/// Determine if a document exists using a comparison on a JSON field
|
||||
/// Determine if a document exists using a comparison on JSON fields
|
||||
[<Extension>]
|
||||
static member inline ExistsByField(conn, tableName, field) =
|
||||
WithConn.Exists.byField tableName field conn
|
||||
static member inline ExistsByFields(conn, tableName, howMatched, fields) =
|
||||
WithConn.Exists.byFields tableName howMatched fields conn
|
||||
|
||||
/// Retrieve all documents in the given table
|
||||
[<Extension>]
|
||||
static member inline FindAll<'TDoc>(conn, tableName) =
|
||||
WithConn.Find.All<'TDoc>(tableName, conn)
|
||||
|
||||
/// Retrieve all documents in the given table ordered by the given fields in the document
|
||||
[<Extension>]
|
||||
static member inline FindAllOrdered<'TDoc>(conn, tableName, orderFields) =
|
||||
WithConn.Find.AllOrdered<'TDoc>(tableName, orderFields, conn)
|
||||
|
||||
/// Retrieve a document by its ID
|
||||
[<Extension>]
|
||||
static member inline FindById<'TKey, 'TDoc when 'TDoc: null>(conn, tableName, docId: 'TKey) =
|
||||
WithConn.Find.ById<'TKey, 'TDoc>(tableName, docId, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field
|
||||
/// Retrieve documents via a comparison on JSON fields
|
||||
[<Extension>]
|
||||
static member inline FindByField<'TDoc>(conn, tableName, field) =
|
||||
WithConn.Find.ByField<'TDoc>(tableName, field, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field, returning only the first result
|
||||
static member inline FindByFields<'TDoc>(conn, tableName, howMatched, fields) =
|
||||
WithConn.Find.ByFields<'TDoc>(tableName, howMatched, fields, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document
|
||||
[<Extension>]
|
||||
static member inline FindFirstByField<'TDoc when 'TDoc: null>(conn, tableName, field) =
|
||||
WithConn.Find.FirstByField<'TDoc>(tableName, field, conn)
|
||||
|
||||
static member inline FindByFieldsOrdered<'TDoc>(conn, tableName, howMatched, queryFields, orderFields) =
|
||||
WithConn.Find.ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields, returning only the first result
|
||||
[<Extension>]
|
||||
static member inline FindFirstByFields<'TDoc when 'TDoc: null>(conn, tableName, howMatched, fields) =
|
||||
WithConn.Find.FirstByFields<'TDoc>(tableName, howMatched, fields, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document, returning only
|
||||
/// the first result
|
||||
[<Extension>]
|
||||
static member inline FindFirstByFieldsOrdered<'TDoc when 'TDoc: null>(
|
||||
conn, tableName, howMatched, queryFields, orderFields) =
|
||||
WithConn.Find.FirstByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, conn)
|
||||
|
||||
/// Update an entire document by its ID
|
||||
[<Extension>]
|
||||
static member inline UpdateById<'TKey, 'TDoc>(conn, tableName, docId: 'TKey, document: 'TDoc) =
|
||||
@@ -207,27 +238,33 @@ type SqliteConnectionCSharpExtensions =
|
||||
static member inline PatchById<'TKey, 'TPatch>(conn, tableName, docId: 'TKey, patch: 'TPatch) =
|
||||
WithConn.Patch.byId tableName docId patch conn
|
||||
|
||||
/// Patch documents using a comparison on a JSON field
|
||||
/// Patch documents using a comparison on JSON fields
|
||||
[<Extension>]
|
||||
static member inline PatchByField<'TPatch>(conn, tableName, field, patch: 'TPatch) =
|
||||
WithConn.Patch.byField tableName field patch conn
|
||||
|
||||
static member inline PatchByFields<'TPatch>(conn, tableName, howMatched, fields, patch: 'TPatch) =
|
||||
WithConn.Patch.byFields tableName howMatched fields patch conn
|
||||
|
||||
/// Remove fields from a document by the document's ID
|
||||
[<Extension>]
|
||||
static member inline RemoveFieldsById<'TKey>(conn, tableName, docId: 'TKey, fieldNames) =
|
||||
WithConn.RemoveFields.ById(tableName, docId, fieldNames, conn)
|
||||
|
||||
/// Remove fields from documents via a comparison on a JSON field in the document
|
||||
WithConn.RemoveFields.byId tableName docId fieldNames conn
|
||||
|
||||
/// Remove fields from documents via a comparison on JSON fields in the document
|
||||
[<Extension>]
|
||||
static member inline RemoveFieldsByField(conn, tableName, field, fieldNames) =
|
||||
WithConn.RemoveFields.ByField(tableName, field, fieldNames, conn)
|
||||
static member inline RemoveFieldsByFields(conn, tableName, howMatched, fields, fieldNames) =
|
||||
WithConn.RemoveFields.byFields tableName howMatched fields fieldNames conn
|
||||
|
||||
/// Delete a document by its ID
|
||||
[<Extension>]
|
||||
static member inline DeleteById<'TKey>(conn, tableName, docId: 'TKey) =
|
||||
WithConn.Delete.byId tableName docId conn
|
||||
|
||||
|
||||
/// Delete documents by matching a comparison on JSON fields
|
||||
[<Extension>]
|
||||
static member inline DeleteByFields(conn, tableName, howMatched, fields) =
|
||||
WithConn.Delete.byFields tableName howMatched fields conn
|
||||
|
||||
/// Delete documents by matching a comparison on a JSON field
|
||||
[<Extension>]
|
||||
[<System.Obsolete "Use DeleteByFields instead; will be removed in v4">]
|
||||
static member inline DeleteByField(conn, tableName, field) =
|
||||
WithConn.Delete.byField tableName field conn
|
||||
conn.DeleteByFields(tableName, Any, [ field ])
|
||||
|
||||
@@ -31,20 +31,47 @@ module Configuration =
|
||||
[<RequireQualifiedAccess>]
|
||||
module Query =
|
||||
|
||||
/// Create a WHERE clause fragment to implement a comparison on a field in a JSON document
|
||||
[<CompiledName "WhereByField">]
|
||||
let whereByField field paramName =
|
||||
let theRest =
|
||||
match field.Op with
|
||||
| EX | NEX -> ""
|
||||
| BT -> $" {paramName}min AND {paramName}max"
|
||||
| _ -> $" %s{paramName}"
|
||||
$"data->>'{field.Name}' {field.Op}{theRest}"
|
||||
|
||||
/// Create a WHERE clause fragment to implement a comparison on fields in a JSON document
|
||||
[<CompiledName "WhereByFields">]
|
||||
let whereByFields (howMatched: FieldMatch) fields =
|
||||
let name = ParameterName()
|
||||
fields
|
||||
|> Seq.map (fun it ->
|
||||
match it.Op with
|
||||
| EX | NEX -> $"{it.Path SQLite} {it.Op}"
|
||||
| BT ->
|
||||
let p = name.Derive it.ParameterName
|
||||
$"{it.Path SQLite} {it.Op} {p}min AND {p}max"
|
||||
| _ -> $"{it.Path SQLite} {it.Op} {name.Derive it.ParameterName}")
|
||||
|> String.concat $" {howMatched} "
|
||||
|
||||
/// Create a WHERE clause fragment to implement an ID-based query
|
||||
[<CompiledName "WhereById">]
|
||||
let whereById paramName =
|
||||
whereByField (Field.EQ (Configuration.idField ()) 0) paramName
|
||||
whereByFields Any [ { Field.EQ (Configuration.idField ()) 0 with ParameterName = Some paramName } ]
|
||||
|
||||
/// Create an UPDATE statement to patch documents
|
||||
[<CompiledName "Patch">]
|
||||
let patch tableName =
|
||||
$"UPDATE %s{tableName} SET data = json_patch(data, json(@data))"
|
||||
|
||||
/// Create an UPDATE statement to remove fields from documents
|
||||
[<CompiledName "RemoveFields">]
|
||||
let removeFields tableName (parameters: SqliteParameter seq) =
|
||||
let paramNames = parameters |> Seq.map _.ParameterName |> String.concat ", "
|
||||
$"UPDATE %s{tableName} SET data = json_remove(data, {paramNames})"
|
||||
|
||||
/// Create a query by a document's ID
|
||||
[<CompiledName "ById">]
|
||||
let byId<'TKey> statement (docId: 'TKey) =
|
||||
Query.statementWhere
|
||||
statement
|
||||
(whereByFields Any [ { Field.EQ (Configuration.idField ()) docId with ParameterName = Some "@id" } ])
|
||||
|
||||
/// Create a query on JSON fields
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields statement howMatched fields =
|
||||
Query.statementWhere statement (whereByFields howMatched fields)
|
||||
|
||||
/// Data definition
|
||||
module Definition =
|
||||
@@ -53,107 +80,7 @@ module Query =
|
||||
[<CompiledName "EnsureTable">]
|
||||
let ensureTable name =
|
||||
Query.Definition.ensureTableFor name "TEXT"
|
||||
|
||||
/// Query to update a document
|
||||
[<CompiledName "Update">]
|
||||
let update tableName =
|
||||
$"""UPDATE %s{tableName} SET data = @data WHERE {whereById "@id"}"""
|
||||
|
||||
/// Queries for counting documents
|
||||
module Count =
|
||||
|
||||
/// Query to count all documents in a table
|
||||
[<CompiledName "All">]
|
||||
let all tableName =
|
||||
$"SELECT COUNT(*) AS it FROM %s{tableName}"
|
||||
|
||||
/// Query to count matching documents using a text comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field =
|
||||
$"""SELECT COUNT(*) AS it FROM %s{tableName} WHERE {whereByField field "@field"}"""
|
||||
|
||||
/// Queries for determining document existence
|
||||
module Exists =
|
||||
|
||||
/// Query to determine if a document exists for the given ID
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName =
|
||||
$"""SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE {whereById "@id"}) AS it"""
|
||||
|
||||
/// Query to determine if documents exist using a comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field =
|
||||
$"""SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE {whereByField field "@field"}) AS it"""
|
||||
|
||||
/// Queries for retrieving documents
|
||||
module Find =
|
||||
|
||||
/// Query to retrieve a document by its ID
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName =
|
||||
$"""{Query.selectFromTable tableName} WHERE {whereById "@id"}"""
|
||||
|
||||
/// Query to retrieve documents using a comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field =
|
||||
$"""{Query.selectFromTable tableName} WHERE {whereByField field "@field"}"""
|
||||
|
||||
/// Document patching (partial update) queries
|
||||
module Patch =
|
||||
|
||||
/// Create an UPDATE statement to patch documents
|
||||
let internal update tableName whereClause =
|
||||
$"UPDATE %s{tableName} SET data = json_patch(data, json(@data)) WHERE %s{whereClause}"
|
||||
|
||||
/// Query to patch (partially update) a document by its ID
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName =
|
||||
whereById "@id" |> update tableName
|
||||
|
||||
/// Query to patch (partially update) a document via a comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field =
|
||||
whereByField field "@field" |> update tableName
|
||||
|
||||
/// Queries to remove fields from documents
|
||||
module RemoveFields =
|
||||
|
||||
/// Create an UPDATE statement to remove parameters
|
||||
let internal update tableName (parameters: SqliteParameter list) whereClause =
|
||||
let paramNames = parameters |> List.map _.ParameterName |> String.concat ", "
|
||||
$"UPDATE %s{tableName} SET data = json_remove(data, {paramNames}) WHERE {whereClause}"
|
||||
|
||||
/// Query to remove fields from a document by the document's ID
|
||||
[<CompiledName "FSharpById">]
|
||||
let byId tableName parameters =
|
||||
whereById "@id" |> update tableName parameters
|
||||
|
||||
/// Query to remove fields from a document by the document's ID
|
||||
let ById(tableName, parameters) =
|
||||
byId tableName (List.ofSeq parameters)
|
||||
|
||||
/// Query to remove fields from documents via a comparison on a JSON field within the document
|
||||
[<CompiledName "FSharpByField">]
|
||||
let byField tableName field parameters =
|
||||
whereByField field "@field" |> update tableName parameters
|
||||
|
||||
/// Query to remove fields from documents via a comparison on a JSON field within the document
|
||||
let ByField(tableName, field, parameters) =
|
||||
byField tableName field (List.ofSeq parameters)
|
||||
|
||||
/// Queries to delete documents
|
||||
module Delete =
|
||||
|
||||
/// Query to delete a document by its ID
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName =
|
||||
$"""DELETE FROM %s{tableName} WHERE {whereById "@id"}"""
|
||||
|
||||
/// Query to delete documents using a comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field =
|
||||
$"""DELETE FROM %s{tableName} WHERE {whereByField field "@field"}"""
|
||||
|
||||
|
||||
/// Parameter handling helpers
|
||||
[<AutoOpen>]
|
||||
@@ -169,39 +96,39 @@ module Parameters =
|
||||
let jsonParam name (it: 'TJson) =
|
||||
SqliteParameter(name, Configuration.serializer().Serialize it)
|
||||
|
||||
/// Create JSON field parameters
|
||||
[<CompiledName "AddFields">]
|
||||
let addFieldParams fields parameters =
|
||||
let name = ParameterName()
|
||||
fields
|
||||
|> Seq.map (fun it ->
|
||||
seq {
|
||||
match it.Op with
|
||||
| EX | NEX -> ()
|
||||
| BT ->
|
||||
let p = name.Derive it.ParameterName
|
||||
let values = it.Value :?> obj list
|
||||
yield SqliteParameter($"{p}min", List.head values)
|
||||
yield SqliteParameter($"{p}max", List.last values)
|
||||
| _ -> yield SqliteParameter(name.Derive it.ParameterName, it.Value) })
|
||||
|> Seq.collect id
|
||||
|> Seq.append parameters
|
||||
|> Seq.toList
|
||||
|> Seq.ofList
|
||||
|
||||
/// Create a JSON field parameter (name "@field")
|
||||
[<CompiledName "FSharpAddField">]
|
||||
[<CompiledName "AddField">]
|
||||
[<System.Obsolete "Use addFieldParams instead; will be removed in v4">]
|
||||
let addFieldParam name field parameters =
|
||||
match field.Op with
|
||||
| EX | NEX -> parameters
|
||||
| BT ->
|
||||
let values = field.Value :?> obj list
|
||||
SqliteParameter($"{name}min", values[0]) :: SqliteParameter($"{name}max", values[1]) :: parameters
|
||||
| _ -> SqliteParameter(name, field.Value) :: parameters
|
||||
addFieldParams [ { field with ParameterName = Some name } ] parameters
|
||||
|
||||
/// Create a JSON field parameter (name "@field")
|
||||
let AddField(name, field, parameters) =
|
||||
match field.Op with
|
||||
| EX | NEX -> parameters
|
||||
| BT ->
|
||||
let values = field.Value :?> obj list
|
||||
// let min = SqliteParameter($"{name}min", SqliteType.Integer)
|
||||
// min.Value <- values[0]
|
||||
// let max = SqliteParameter($"{name}max", SqliteType.Integer)
|
||||
// max.Value <- values[1]
|
||||
[ SqliteParameter($"{name}min", values[0]); SqliteParameter($"{name}max", values[1]) ]
|
||||
// [min; max]
|
||||
|> Seq.append parameters
|
||||
| _ -> SqliteParameter(name, field.Value) |> Seq.singleton |> Seq.append parameters
|
||||
|
||||
/// Append JSON field name parameters for the given field names to the given parameters
|
||||
[<CompiledName "FSharpFieldNames">]
|
||||
let fieldNameParams paramName (fieldNames: string list) =
|
||||
fieldNames |> List.mapi (fun idx name -> SqliteParameter($"%s{paramName}{idx}", $"$.{name}"))
|
||||
|
||||
/// Append JSON field name parameters for the given field names to the given parameters
|
||||
let FieldNames(paramName, fieldNames: string seq) =
|
||||
fieldNames |> Seq.mapi (fun idx name -> SqliteParameter($"%s{paramName}{idx}", $"$.{name}"))
|
||||
[<CompiledName "FieldNames">]
|
||||
let fieldNameParams paramName fieldNames =
|
||||
fieldNames
|
||||
|> Seq.mapi (fun idx name -> SqliteParameter($"%s{paramName}{idx}", $"$.%s{name}"))
|
||||
|> Seq.toList
|
||||
|> Seq.ofList
|
||||
|
||||
/// An empty parameter sequence
|
||||
[<CompiledName "None">]
|
||||
@@ -323,23 +250,42 @@ module WithConn =
|
||||
[<CompiledName "EnsureTable">]
|
||||
let ensureTable name conn = backgroundTask {
|
||||
do! Custom.nonQuery (Query.Definition.ensureTable name) [] conn
|
||||
do! Custom.nonQuery (Query.Definition.ensureKey name) [] conn
|
||||
do! Custom.nonQuery (Query.Definition.ensureKey name SQLite) [] conn
|
||||
}
|
||||
|
||||
/// Create an index on a document table
|
||||
[<CompiledName "EnsureFieldIndex">]
|
||||
let ensureFieldIndex tableName indexName fields conn =
|
||||
Custom.nonQuery (Query.Definition.ensureIndexOn tableName indexName fields) [] conn
|
||||
Custom.nonQuery (Query.Definition.ensureIndexOn tableName indexName fields SQLite) [] conn
|
||||
|
||||
/// Insert a new document
|
||||
[<CompiledName "Insert">]
|
||||
let insert<'TDoc> tableName (document: 'TDoc) conn =
|
||||
Custom.nonQuery (Query.insert tableName) [ jsonParam "@data" document ] conn
|
||||
|
||||
/// Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
|
||||
[<CompiledName "Save">]
|
||||
let save<'TDoc> tableName (document: 'TDoc) conn =
|
||||
Custom.nonQuery (Query.save tableName) [ jsonParam "@data" document ] conn
|
||||
/// Commands to add documents
|
||||
[<AutoOpen>]
|
||||
module Document =
|
||||
|
||||
/// Insert a new document
|
||||
[<CompiledName "Insert">]
|
||||
let insert<'TDoc> tableName (document: 'TDoc) conn =
|
||||
let query =
|
||||
match Configuration.autoIdStrategy () with
|
||||
| Disabled -> Query.insert tableName
|
||||
| strategy ->
|
||||
let idField = Configuration.idField ()
|
||||
let dataParam =
|
||||
if AutoId.NeedsAutoId strategy document idField then
|
||||
match strategy with
|
||||
| Number -> $"(SELECT coalesce(max(data->>'{idField}'), 0) + 1 FROM {tableName})"
|
||||
| Guid -> $"'{AutoId.GenerateGuid()}'"
|
||||
| RandomString -> $"'{AutoId.GenerateRandomString(Configuration.idStringLength ())}'"
|
||||
| Disabled -> "@data"
|
||||
|> function it -> $"json_set(@data, '$.{idField}', {it})"
|
||||
else "@data"
|
||||
(Query.insert tableName).Replace("@data", dataParam)
|
||||
Custom.nonQuery query [ jsonParam "@data" document ] conn
|
||||
|
||||
/// Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
|
||||
[<CompiledName "Save">]
|
||||
let save<'TDoc> tableName (document: 'TDoc) conn =
|
||||
Custom.nonQuery (Query.save tableName) [ jsonParam "@data" document ] conn
|
||||
|
||||
/// Commands to count documents
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -348,12 +294,13 @@ module WithConn =
|
||||
/// Count all documents in a table
|
||||
[<CompiledName "All">]
|
||||
let all tableName conn =
|
||||
Custom.scalar (Query.Count.all tableName) [] toCount conn
|
||||
Custom.scalar (Query.count tableName) [] toCount conn
|
||||
|
||||
/// Count matching documents using a comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field conn =
|
||||
Custom.scalar (Query.Count.byField tableName field) (addFieldParam "@field" field []) toCount conn
|
||||
/// Count matching documents using a comparison on JSON fields
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields conn =
|
||||
Custom.scalar
|
||||
(Query.byFields (Query.count tableName) howMatched fields) (addFieldParams fields []) toCount conn
|
||||
|
||||
/// Commands to determine if documents exist
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -362,12 +309,16 @@ module WithConn =
|
||||
/// Determine if a document exists for the given ID
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) conn =
|
||||
Custom.scalar (Query.Exists.byId tableName) [ idParam docId ] toExists conn
|
||||
|
||||
/// Determine if a document exists using a comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field conn =
|
||||
Custom.scalar (Query.Exists.byField tableName field) (addFieldParam "@field" field []) toExists conn
|
||||
Custom.scalar (Query.exists tableName (Query.whereById "@id")) [ idParam docId ] toExists conn
|
||||
|
||||
/// Determine if a document exists using a comparison on JSON fields
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields conn =
|
||||
Custom.scalar
|
||||
(Query.exists tableName (Query.whereByFields howMatched fields))
|
||||
(addFieldParams fields [])
|
||||
toExists
|
||||
conn
|
||||
|
||||
/// Commands to retrieve documents
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -376,42 +327,99 @@ module WithConn =
|
||||
/// Retrieve all documents in the given table
|
||||
[<CompiledName "FSharpAll">]
|
||||
let all<'TDoc> tableName conn =
|
||||
Custom.list<'TDoc> (Query.selectFromTable tableName) [] fromData<'TDoc> conn
|
||||
Custom.list<'TDoc> (Query.find tableName) [] fromData<'TDoc> conn
|
||||
|
||||
/// Retrieve all documents in the given table
|
||||
let All<'TDoc>(tableName, conn) =
|
||||
Custom.List(Query.selectFromTable tableName, [], fromData<'TDoc>, conn)
|
||||
Custom.List(Query.find tableName, [], fromData<'TDoc>, conn)
|
||||
|
||||
/// Retrieve all documents in the given table ordered by the given fields in the document
|
||||
[<CompiledName "FSharpAllOrdered">]
|
||||
let allOrdered<'TDoc> tableName orderFields conn =
|
||||
Custom.list<'TDoc> (Query.find tableName + Query.orderBy orderFields SQLite) [] fromData<'TDoc> conn
|
||||
|
||||
/// Retrieve all documents in the given table ordered by the given fields in the document
|
||||
let AllOrdered<'TDoc>(tableName, orderFields, conn) =
|
||||
Custom.List(Query.find tableName + Query.orderBy orderFields SQLite, [], fromData<'TDoc>, conn)
|
||||
|
||||
/// Retrieve a document by its ID (returns None if not found)
|
||||
[<CompiledName "FSharpById">]
|
||||
let byId<'TKey, 'TDoc> tableName (docId: 'TKey) conn =
|
||||
Custom.single<'TDoc> (Query.Find.byId tableName) [ idParam docId ] fromData<'TDoc> conn
|
||||
Custom.single<'TDoc> (Query.byId (Query.find tableName) docId) [ idParam docId ] fromData<'TDoc> conn
|
||||
|
||||
/// Retrieve a document by its ID (returns null if not found)
|
||||
let ById<'TKey, 'TDoc when 'TDoc: null>(tableName, docId: 'TKey, conn) =
|
||||
Custom.Single<'TDoc>(Query.Find.byId tableName, [ idParam docId ], fromData<'TDoc>, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field
|
||||
[<CompiledName "FSharpByField">]
|
||||
let byField<'TDoc> tableName field conn =
|
||||
Custom.Single<'TDoc>(Query.byId (Query.find tableName) docId, [ idParam docId ], fromData<'TDoc>, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields
|
||||
[<CompiledName "FSharpByFields">]
|
||||
let byFields<'TDoc> tableName howMatched fields conn =
|
||||
Custom.list<'TDoc>
|
||||
(Query.Find.byField tableName field) (addFieldParam "@field" field []) fromData<'TDoc> conn
|
||||
(Query.byFields (Query.find tableName) howMatched fields)
|
||||
(addFieldParams fields [])
|
||||
fromData<'TDoc>
|
||||
conn
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field
|
||||
let ByField<'TDoc>(tableName, field, conn) =
|
||||
/// Retrieve documents via a comparison on JSON fields
|
||||
let ByFields<'TDoc>(tableName, howMatched, fields, conn) =
|
||||
Custom.List<'TDoc>(
|
||||
Query.Find.byField tableName field, addFieldParam "@field" field [], fromData<'TDoc>, conn)
|
||||
Query.byFields (Query.find tableName) howMatched fields,
|
||||
addFieldParams fields [],
|
||||
fromData<'TDoc>,
|
||||
conn)
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field, returning only the first result
|
||||
[<CompiledName "FSharpFirstByField">]
|
||||
let firstByField<'TDoc> tableName field conn =
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document
|
||||
[<CompiledName "FSharpByFieldsOrdered">]
|
||||
let byFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn =
|
||||
Custom.list<'TDoc>
|
||||
(Query.byFields (Query.find tableName) howMatched queryFields + Query.orderBy orderFields SQLite)
|
||||
(addFieldParams queryFields [])
|
||||
fromData<'TDoc>
|
||||
conn
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document
|
||||
let ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, conn) =
|
||||
Custom.List<'TDoc>(
|
||||
Query.byFields (Query.find tableName) howMatched queryFields + Query.orderBy orderFields SQLite,
|
||||
addFieldParams queryFields [],
|
||||
fromData<'TDoc>,
|
||||
conn)
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields, returning only the first result
|
||||
[<CompiledName "FSharpFirstByFields">]
|
||||
let firstByFields<'TDoc> tableName howMatched fields conn =
|
||||
Custom.single
|
||||
$"{Query.Find.byField tableName field} LIMIT 1" (addFieldParam "@field" field []) fromData<'TDoc> conn
|
||||
$"{Query.byFields (Query.find tableName) howMatched fields} LIMIT 1"
|
||||
(addFieldParams fields [])
|
||||
fromData<'TDoc>
|
||||
conn
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field, returning only the first result
|
||||
let FirstByField<'TDoc when 'TDoc: null>(tableName, field, conn) =
|
||||
/// Retrieve documents via a comparison on JSON fields, returning only the first result
|
||||
let FirstByFields<'TDoc when 'TDoc: null>(tableName, howMatched, fields, conn) =
|
||||
Custom.Single(
|
||||
$"{Query.Find.byField tableName field} LIMIT 1", addFieldParam "@field" field [], fromData<'TDoc>, conn)
|
||||
$"{Query.byFields (Query.find tableName) howMatched fields} LIMIT 1",
|
||||
addFieldParams fields [],
|
||||
fromData<'TDoc>,
|
||||
conn)
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document, returning
|
||||
/// only the first result
|
||||
[<CompiledName "FSharpFirstByFieldsOrdered">]
|
||||
let firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn =
|
||||
Custom.single
|
||||
$"{Query.byFields (Query.find tableName) howMatched queryFields}{Query.orderBy orderFields SQLite} LIMIT 1"
|
||||
(addFieldParams queryFields [])
|
||||
fromData<'TDoc>
|
||||
conn
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document, returning
|
||||
/// only the first result
|
||||
let FirstByFieldsOrdered<'TDoc when 'TDoc: null>(tableName, howMatched, queryFields, orderFields, conn) =
|
||||
Custom.Single(
|
||||
$"{Query.byFields (Query.find tableName) howMatched queryFields}{Query.orderBy orderFields SQLite} LIMIT 1",
|
||||
addFieldParams queryFields [],
|
||||
fromData<'TDoc>,
|
||||
conn)
|
||||
|
||||
/// Commands to update documents
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -420,7 +428,10 @@ module WithConn =
|
||||
/// Update an entire document by its ID
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) (document: 'TDoc) conn =
|
||||
Custom.nonQuery (Query.update tableName) [ idParam docId; jsonParam "@data" document ] conn
|
||||
Custom.nonQuery
|
||||
(Query.statementWhere (Query.update tableName) (Query.whereById "@id"))
|
||||
[ idParam docId; jsonParam "@data" document ]
|
||||
conn
|
||||
|
||||
/// Update an entire document by its ID, using the provided function to obtain the ID from the document
|
||||
[<CompiledName "FSharpByFunc">]
|
||||
@@ -438,38 +449,38 @@ module WithConn =
|
||||
/// Patch a document by its ID
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) (patch: 'TPatch) conn =
|
||||
Custom.nonQuery (Query.Patch.byId tableName) [ idParam docId; jsonParam "@data" patch ] conn
|
||||
|
||||
/// Patch documents using a comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field (patch: 'TPatch) (conn: SqliteConnection) =
|
||||
Custom.nonQuery
|
||||
(Query.Patch.byField tableName field) (addFieldParam "@field" field [ jsonParam "@data" patch ]) conn
|
||||
|
||||
(Query.byId (Query.patch tableName) docId) [ idParam docId; jsonParam "@data" patch ] conn
|
||||
|
||||
/// Patch documents using a comparison on JSON fields
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields (patch: 'TPatch) conn =
|
||||
Custom.nonQuery
|
||||
(Query.byFields (Query.patch tableName) howMatched fields)
|
||||
(addFieldParams fields [ jsonParam "@data" patch ])
|
||||
conn
|
||||
|
||||
/// Commands to remove fields from documents
|
||||
[<RequireQualifiedAccess>]
|
||||
module RemoveFields =
|
||||
|
||||
/// Remove fields from a document by the document's ID
|
||||
[<CompiledName "FSharpById">]
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) fieldNames conn =
|
||||
let nameParams = fieldNameParams "@name" fieldNames
|
||||
Custom.nonQuery (Query.RemoveFields.byId tableName nameParams) (idParam docId :: nameParams) conn
|
||||
Custom.nonQuery
|
||||
(Query.byId (Query.removeFields tableName nameParams) docId)
|
||||
(idParam docId |> Seq.singleton |> Seq.append nameParams)
|
||||
conn
|
||||
|
||||
/// Remove fields from a document by the document's ID
|
||||
let ById(tableName, docId: 'TKey, fieldNames, conn) =
|
||||
byId tableName docId (List.ofSeq fieldNames) conn
|
||||
|
||||
/// Remove fields from documents via a comparison on a JSON field in the document
|
||||
[<CompiledName "FSharpByField">]
|
||||
let byField tableName field fieldNames conn =
|
||||
/// Remove fields from documents via a comparison on JSON fields in the document
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields fieldNames conn =
|
||||
let nameParams = fieldNameParams "@name" fieldNames
|
||||
Custom.nonQuery
|
||||
(Query.RemoveFields.byField tableName field nameParams) (addFieldParam "@field" field nameParams) conn
|
||||
|
||||
/// Remove fields from documents via a comparison on a JSON field in the document
|
||||
let ByField(tableName, field, fieldNames, conn) =
|
||||
byField tableName field (List.ofSeq fieldNames) conn
|
||||
(Query.byFields (Query.removeFields tableName nameParams) howMatched fields)
|
||||
(addFieldParams fields nameParams)
|
||||
conn
|
||||
|
||||
/// Commands to delete documents
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -478,12 +489,12 @@ module WithConn =
|
||||
/// Delete a document by its ID
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) conn =
|
||||
Custom.nonQuery (Query.Delete.byId tableName) [ idParam docId ] conn
|
||||
|
||||
/// Delete documents by matching a comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field conn =
|
||||
Custom.nonQuery (Query.Delete.byField tableName field) (addFieldParam "@field" field []) conn
|
||||
Custom.nonQuery (Query.byId (Query.delete tableName) docId) [ idParam docId ] conn
|
||||
|
||||
/// Delete documents by matching a comparison on JSON fields
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields conn =
|
||||
Custom.nonQuery (Query.byFields (Query.delete tableName) howMatched fields) (addFieldParams fields []) conn
|
||||
|
||||
|
||||
/// Commands to execute custom SQL queries
|
||||
@@ -529,6 +540,7 @@ module Custom =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.Scalar<'T>(query, parameters, mapFunc, conn)
|
||||
|
||||
|
||||
/// Functions to create tables and indexes
|
||||
[<RequireQualifiedAccess>]
|
||||
module Definition =
|
||||
@@ -545,6 +557,7 @@ module Definition =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Definition.ensureFieldIndex tableName indexName fields conn
|
||||
|
||||
|
||||
/// Document insert/save functions
|
||||
[<AutoOpen>]
|
||||
module Document =
|
||||
@@ -553,13 +566,14 @@ module Document =
|
||||
[<CompiledName "Insert">]
|
||||
let insert<'TDoc> tableName (document: 'TDoc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.insert tableName document conn
|
||||
WithConn.Document.insert tableName document conn
|
||||
|
||||
/// Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
|
||||
[<CompiledName "Save">]
|
||||
let save<'TDoc> tableName (document: 'TDoc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.save tableName document conn
|
||||
WithConn.Document.save tableName document conn
|
||||
|
||||
|
||||
/// Commands to count documents
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -571,11 +585,12 @@ module Count =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Count.all tableName conn
|
||||
|
||||
/// Count matching documents using a comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field =
|
||||
/// Count matching documents using a comparison on JSON fields
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Count.byField tableName field conn
|
||||
WithConn.Count.byFields tableName howMatched fields conn
|
||||
|
||||
|
||||
/// Commands to determine if documents exist
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -586,12 +601,13 @@ module Exists =
|
||||
let byId tableName (docId: 'TKey) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Exists.byId tableName docId conn
|
||||
|
||||
/// Determine if a document exists using a comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field =
|
||||
|
||||
/// Determine if a document exists using a comparison on JSON fields
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Exists.byField tableName field conn
|
||||
WithConn.Exists.byFields tableName howMatched fields conn
|
||||
|
||||
|
||||
/// Commands to determine if documents exist
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -608,6 +624,17 @@ module Find =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.All<'TDoc>(tableName, conn)
|
||||
|
||||
/// Retrieve all documents in the given table ordered by the given fields in the document
|
||||
[<CompiledName "FSharpAllOrdered">]
|
||||
let allOrdered<'TDoc> tableName orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.allOrdered<'TDoc> tableName orderFields conn
|
||||
|
||||
/// Retrieve all documents in the given table ordered by the given fields in the document
|
||||
let AllOrdered<'TDoc> tableName orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.AllOrdered<'TDoc>(tableName, orderFields, conn)
|
||||
|
||||
/// Retrieve a document by its ID (returns None if not found)
|
||||
[<CompiledName "FSharpById">]
|
||||
let byId<'TKey, 'TDoc> tableName docId =
|
||||
@@ -619,27 +646,52 @@ module Find =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.ById<'TKey, 'TDoc>(tableName, docId, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field
|
||||
[<CompiledName "FSharpByField">]
|
||||
let byField<'TDoc> tableName field =
|
||||
/// Retrieve documents via a comparison on JSON fields
|
||||
[<CompiledName "FSharpByFields">]
|
||||
let byFields<'TDoc> tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.byField<'TDoc> tableName field conn
|
||||
WithConn.Find.byFields<'TDoc> tableName howMatched fields conn
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields
|
||||
let ByFields<'TDoc>(tableName, howMatched, fields) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.ByFields<'TDoc>(tableName, howMatched, fields, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document
|
||||
[<CompiledName "FSharpByFieldsOrdered">]
|
||||
let byFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.byFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document
|
||||
let ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields, returning only the first result
|
||||
[<CompiledName "FSharpFirstByFields">]
|
||||
let firstByFields<'TDoc> tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.firstByFields<'TDoc> tableName howMatched fields conn
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields, returning only the first result
|
||||
let FirstByFields<'TDoc when 'TDoc: null>(tableName, howMatched, fields) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.FirstByFields<'TDoc>(tableName, howMatched, fields, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field
|
||||
let ByField<'TDoc>(tableName, field) =
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document, returning only
|
||||
/// the first result
|
||||
[<CompiledName "FSharpFirstByFieldsOrdered">]
|
||||
let firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.ByField<'TDoc>(tableName, field, conn)
|
||||
WithConn.Find.firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// Retrieve documents via a comparison on JSON fields ordered by the given fields in the document, returning only
|
||||
/// the first result
|
||||
let FirstByFieldsOrdered<'TDoc when 'TDoc: null>(tableName, howMatched, queryFields, orderFields) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.FirstByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, conn)
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field, returning only the first result
|
||||
[<CompiledName "FSharpFirstByField">]
|
||||
let firstByField<'TDoc> tableName field =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.firstByField<'TDoc> tableName field conn
|
||||
|
||||
/// Retrieve documents via a comparison on a JSON field, returning only the first result
|
||||
let FirstByField<'TDoc when 'TDoc: null>(tableName, field) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.FirstByField<'TDoc>(tableName, field, conn)
|
||||
|
||||
/// Commands to update documents
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -662,6 +714,7 @@ module Update =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Update.ByFunc(tableName, idFunc, document, conn)
|
||||
|
||||
|
||||
/// Commands to patch (partially update) documents
|
||||
[<RequireQualifiedAccess>]
|
||||
module Patch =
|
||||
@@ -672,37 +725,29 @@ module Patch =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Patch.byId tableName docId patch conn
|
||||
|
||||
/// Patch documents using a comparison on a JSON field in the WHERE clause
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field (patch: 'TPatch) =
|
||||
/// Patch documents using a comparison on JSON fields in the WHERE clause
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields (patch: 'TPatch) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Patch.byField tableName field patch conn
|
||||
WithConn.Patch.byFields tableName howMatched fields patch conn
|
||||
|
||||
|
||||
/// Commands to remove fields from documents
|
||||
[<RequireQualifiedAccess>]
|
||||
module RemoveFields =
|
||||
|
||||
/// Remove fields from a document by the document's ID
|
||||
[<CompiledName "FSharpById">]
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) fieldNames =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.RemoveFields.byId tableName docId fieldNames conn
|
||||
|
||||
/// Remove fields from a document by the document's ID
|
||||
let ById(tableName, docId: 'TKey, fieldNames) =
|
||||
|
||||
/// Remove field from documents via a comparison on JSON fields in the document
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields fieldNames =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.RemoveFields.ById(tableName, docId, fieldNames, conn)
|
||||
|
||||
/// Remove field from documents via a comparison on a JSON field in the document
|
||||
[<CompiledName "FSharpByField">]
|
||||
let byField tableName field fieldNames =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.RemoveFields.byField tableName field fieldNames conn
|
||||
WithConn.RemoveFields.byFields tableName howMatched fields fieldNames conn
|
||||
|
||||
/// Remove field from documents via a comparison on a JSON field in the document
|
||||
let ByField(tableName, field, fieldNames) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.RemoveFields.ByField(tableName, field, fieldNames, conn)
|
||||
|
||||
/// Commands to delete documents
|
||||
[<RequireQualifiedAccess>]
|
||||
@@ -713,9 +758,9 @@ module Delete =
|
||||
let byId tableName (docId: 'TKey) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Delete.byId tableName docId conn
|
||||
|
||||
/// Delete documents by matching a comparison on a JSON field
|
||||
[<CompiledName "ByField">]
|
||||
let byField tableName field =
|
||||
|
||||
/// Delete documents by matching a comparison on JSON fields
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Delete.byField tableName field conn
|
||||
WithConn.Delete.byFields tableName howMatched fields conn
|
||||
|
||||
Reference in New Issue
Block a user