v4.1 (#11)
- Add `Json` module to return JSON strings and write JSON as it's read to a `PipeWriter` - Add `docfx`-based documentation to allow how-to docs and API docs to be generated on the same site Reviewed-on: #11
This commit was merged in pull request #11.
This commit is contained in:
@@ -1,44 +1,45 @@
|
||||
namespace BitBadger.Documents
|
||||
|
||||
open System.Security.Cryptography
|
||||
open System.Text
|
||||
|
||||
/// <summary>The types of comparisons available for JSON fields</summary>
|
||||
/// <exclude />
|
||||
type Comparison =
|
||||
|
||||
/// <summary>Equals (<tt>=</tt>)</summary>
|
||||
|
||||
/// <summary>Equals (<c>=</c>)</summary>
|
||||
| Equal of Value: obj
|
||||
|
||||
/// <summary>Greater Than (<tt>></tt>)</summary>
|
||||
|
||||
/// <summary>Greater Than (<c>></c>)</summary>
|
||||
| Greater of Value: obj
|
||||
|
||||
/// <summary>Greater Than or Equal To (<tt>>=</tt>)</summary>
|
||||
|
||||
/// <summary>Greater Than or Equal To (<c>>=</c>)</summary>
|
||||
| GreaterOrEqual of Value: obj
|
||||
|
||||
/// <summary>Less Than (<tt><</tt>)</summary>
|
||||
|
||||
/// <summary>Less Than (<c><</c>)</summary>
|
||||
| Less of Value: obj
|
||||
|
||||
/// <summary>Less Than or Equal To (<tt><=</tt>)</summary>
|
||||
| LessOrEqual of Value: obj
|
||||
|
||||
/// <summary>Not Equal to (<tt><></tt>)</summary>
|
||||
|
||||
/// <summary>Less Than or Equal To (<c><=</c>)</summary>
|
||||
| LessOrEqual of Value: obj
|
||||
|
||||
/// <summary>Not Equal to (<c><></c>)</summary>
|
||||
| NotEqual of Value: obj
|
||||
|
||||
/// <summary>Between (<tt>BETWEEN</tt>)</summary>
|
||||
|
||||
/// <summary>Between (<c>BETWEEN</c>)</summary>
|
||||
| Between of Min: obj * Max: obj
|
||||
|
||||
/// <summary>In (<tt>IN</tt>)</summary>
|
||||
|
||||
/// <summary>In (<c>IN</c>)</summary>
|
||||
| In of Values: obj seq
|
||||
|
||||
/// <summary>In Array (PostgreSQL: <tt>|?</tt>, SQLite: <tt>EXISTS / json_each / IN</tt>)</summary>
|
||||
|
||||
/// <summary>In Array (PostgreSQL: <c>|?</c>, SQLite: <c>EXISTS / json_each / IN</c>)</summary>
|
||||
| InArray of Table: string * Values: obj seq
|
||||
|
||||
/// <summary>Exists (<tt>IS NOT NULL</tt>)</summary>
|
||||
|
||||
/// <summary>Exists (<c>IS NOT NULL</c>)</summary>
|
||||
| Exists
|
||||
|
||||
/// <summary>Does Not Exist (<tt>IS NULL</tt>)</summary>
|
||||
|
||||
/// <summary>Does Not Exist (<c>IS NULL</c>)</summary>
|
||||
| NotExists
|
||||
|
||||
|
||||
/// <summary>The operator SQL for this comparison</summary>
|
||||
member this.OpSql =
|
||||
match this with
|
||||
@@ -50,7 +51,7 @@ type Comparison =
|
||||
| NotEqual _ -> "<>"
|
||||
| Between _ -> "BETWEEN"
|
||||
| In _ -> "IN"
|
||||
| InArray _ -> "?|" // PostgreSQL only; SQL needs a subquery for this
|
||||
| InArray _ -> "?|" // PostgreSQL only; SQL needs a subquery for this
|
||||
| Exists -> "IS NOT NULL"
|
||||
| NotExists -> "IS NULL"
|
||||
|
||||
@@ -62,120 +63,120 @@ type Dialect =
|
||||
| SQLite
|
||||
|
||||
|
||||
/// <summary>The format in which an element of a JSON field should be extracted</summary>
|
||||
/// <summary>The format in which an element of a JSON field should be extracted</summary>
|
||||
[<Struct>]
|
||||
type FieldFormat =
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Use <tt>->></tt> or <tt>#>></tt>; extracts a text (PostgreSQL) or SQL (SQLite) value
|
||||
/// Use <c>->></c> or <c>#>></c>; extracts a text (PostgreSQL) or SQL (SQLite) value
|
||||
/// </summary>
|
||||
| AsSql
|
||||
|
||||
/// <summary>Use <tt>-></tt> or <tt>#></tt>; extracts a JSONB (PostgreSQL) or JSON (SQLite) value</summary>
|
||||
|
||||
/// <summary>Use <c>-></c> or <c>#></c>; extracts a JSONB (PostgreSQL) or JSON (SQLite) value</summary>
|
||||
| AsJson
|
||||
|
||||
|
||||
/// <summary>Criteria for a field <tt>WHERE</tt> clause</summary>
|
||||
/// <summary>Criteria for a field <c>WHERE</c> clause</summary>
|
||||
type Field = {
|
||||
|
||||
|
||||
/// <summary>The name of the field</summary>
|
||||
Name: string
|
||||
|
||||
|
||||
/// <summary>The comparison for the field</summary>
|
||||
Comparison: Comparison
|
||||
|
||||
|
||||
/// <summary>The name of the parameter for this field</summary>
|
||||
ParameterName: string option
|
||||
|
||||
|
||||
/// <summary>The table qualifier for this field</summary>
|
||||
Qualifier: string option
|
||||
} with
|
||||
|
||||
|
||||
/// <summary>Create a comparison against a field</summary>
|
||||
/// <param name="name">The name of the field against which the comparison should be applied</param>
|
||||
/// <param name="comparison">The comparison for the given field</param>
|
||||
/// <returns>A new <tt>Field</tt> instance implementing the given comparison</returns>
|
||||
/// <returns>A new <c>Field</c> instance implementing the given comparison</returns>
|
||||
static member Where name (comparison: Comparison) =
|
||||
{ Name = name; Comparison = comparison; ParameterName = None; Qualifier = None }
|
||||
|
||||
/// <summary>Create an equals (<tt>=</tt>) field criterion</summary>
|
||||
|
||||
/// <summary>Create an equals (<c>=</c>) field criterion</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member Equal<'T> name (value: 'T) =
|
||||
Field.Where name (Equal value)
|
||||
|
||||
/// <summary>Create an equals (<tt>=</tt>) field criterion (alias)</summary>
|
||||
|
||||
/// <summary>Create an equals (<c>=</c>) field criterion (alias)</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member EQ<'T> name (value: 'T) = Field.Equal name value
|
||||
|
||||
/// <summary>Create a greater than (<tt>></tt>) field criterion</summary>
|
||||
|
||||
/// <summary>Create a greater than (<c>></c>) field criterion</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member Greater<'T> name (value: 'T) =
|
||||
Field.Where name (Greater value)
|
||||
|
||||
/// <summary>Create a greater than (<tt>></tt>) field criterion (alias)</summary>
|
||||
|
||||
/// <summary>Create a greater than (<c>></c>) field criterion (alias)</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member GT<'T> name (value: 'T) = Field.Greater name value
|
||||
|
||||
/// <summary>Create a greater than or equal to (<tt>>=</tt>) field criterion</summary>
|
||||
|
||||
/// <summary>Create a greater than or equal to (<c>>=</c>) field criterion</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member GreaterOrEqual<'T> name (value: 'T) =
|
||||
Field.Where name (GreaterOrEqual value)
|
||||
|
||||
/// <summary>Create a greater than or equal to (<tt>>=</tt>) field criterion (alias)</summary>
|
||||
|
||||
/// <summary>Create a greater than or equal to (<c>>=</c>) field criterion (alias)</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member GE<'T> name (value: 'T) = Field.GreaterOrEqual name value
|
||||
|
||||
/// <summary>Create a less than (<tt><</tt>) field criterion</summary>
|
||||
|
||||
/// <summary>Create a less than (<c><</c>) field criterion</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member Less<'T> name (value: 'T) =
|
||||
Field.Where name (Less value)
|
||||
|
||||
/// <summary>Create a less than (<tt><</tt>) field criterion (alias)</summary>
|
||||
|
||||
/// <summary>Create a less than (<c><</c>) field criterion (alias)</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member LT<'T> name (value: 'T) = Field.Less name value
|
||||
|
||||
/// <summary>Create a less than or equal to (<tt><=</tt>) field criterion</summary>
|
||||
|
||||
/// <summary>Create a less than or equal to (<c><=</c>) field criterion</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member LessOrEqual<'T> name (value: 'T) =
|
||||
Field.Where name (LessOrEqual value)
|
||||
|
||||
/// <summary>Create a less than or equal to (<tt><=</tt>) field criterion (alias)</summary>
|
||||
|
||||
/// <summary>Create a less than or equal to (<c><=</c>) field criterion (alias)</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member LE<'T> name (value: 'T) = Field.LessOrEqual name value
|
||||
|
||||
/// <summary>Create a not equals (<tt><></tt>) field criterion</summary>
|
||||
|
||||
/// <summary>Create a not equals (<c><></c>) field criterion</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member NotEqual<'T> name (value: 'T) =
|
||||
Field.Where name (NotEqual value)
|
||||
|
||||
/// <summary>Create a not equals (<tt><></tt>) field criterion (alias)</summary>
|
||||
|
||||
/// <summary>Create a not equals (<c><></c>) field criterion (alias)</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="value">The value for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member NE<'T> name (value: 'T) = Field.NotEqual name value
|
||||
|
||||
|
||||
/// <summary>Create a Between field criterion</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="min">The minimum value for the comparison range</param>
|
||||
@@ -183,27 +184,27 @@ type Field = {
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member Between<'T> name (min: 'T) (max: 'T) =
|
||||
Field.Where name (Between(min, max))
|
||||
|
||||
|
||||
/// <summary>Create a Between field criterion (alias)</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="min">The minimum value for the comparison range</param>
|
||||
/// <param name="max">The maximum value for the comparison range</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member BT<'T> name (min: 'T) (max: 'T) = Field.Between name min max
|
||||
|
||||
|
||||
/// <summary>Create an In field criterion</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="values">The values for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member In<'T> name (values: 'T seq) =
|
||||
Field.Where name (In (Seq.map box values))
|
||||
|
||||
|
||||
/// <summary>Create an In field criterion (alias)</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="values">The values for the comparison</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member IN<'T> name (values: 'T seq) = Field.In name values
|
||||
|
||||
|
||||
/// <summary>Create an InArray field criterion</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <param name="tableName">The name of the table in which the field's documents are stored</param>
|
||||
@@ -211,34 +212,34 @@ type Field = {
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member InArray<'T> name tableName (values: 'T seq) =
|
||||
Field.Where name (InArray(tableName, Seq.map box values))
|
||||
|
||||
/// <summary>Create an exists (<tt>IS NOT NULL</tt>) field criterion</summary>
|
||||
|
||||
/// <summary>Create an exists (<c>IS NOT NULL</c>) field criterion</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member Exists name =
|
||||
Field.Where name Exists
|
||||
|
||||
/// <summary>Create an exists (<tt>IS NOT NULL</tt>) field criterion (alias)</summary>
|
||||
|
||||
/// <summary>Create an exists (<c>IS NOT NULL</c>) field criterion (alias)</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member EX name = Field.Exists name
|
||||
|
||||
/// <summary>Create a not exists (<tt>IS NULL</tt>) field criterion</summary>
|
||||
|
||||
/// <summary>Create a not exists (<c>IS NULL</c>) field criterion</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member NotExists name =
|
||||
Field.Where name NotExists
|
||||
|
||||
/// <summary>Create a not exists (<tt>IS NULL</tt>) field criterion (alias)</summary>
|
||||
|
||||
/// <summary>Create a not exists (<c>IS NULL</c>) field criterion (alias)</summary>
|
||||
/// <param name="name">The name of the field to be compared</param>
|
||||
/// <returns>A field with the given comparison</returns>
|
||||
static member NEX name = Field.NotExists name
|
||||
|
||||
/// <summary>Transform a field name (<tt>a.b.c</tt>) to a path for the given SQL dialect</summary>
|
||||
|
||||
/// <summary>Transform a field name (<c>a.b.c</c>) to a path for the given SQL dialect</summary>
|
||||
/// <param name="name">The name of the field in dotted format</param>
|
||||
/// <param name="dialect">The SQL dialect to use when converting the name to nested path format</param>
|
||||
/// <param name="format">Whether to reference this path as a JSON value or a SQL value</param>
|
||||
/// <returns>A <tt>string</tt> with the path required to address the nested document value</returns>
|
||||
/// <returns>A <c>string</c> with the path required to address the nested document value</returns>
|
||||
static member NameToPath (name: string) dialect format =
|
||||
let path =
|
||||
if name.Contains '.' then
|
||||
@@ -254,19 +255,19 @@ type Field = {
|
||||
else
|
||||
match format with AsJson -> $"->'{name}'" | AsSql -> $"->>'{name}'"
|
||||
$"data{path}"
|
||||
|
||||
|
||||
/// <summary>Create a field with a given name, but no other properties filled</summary>
|
||||
/// <param name="name">The field name, along with any other qualifications if used in a sorting context</param>
|
||||
/// <remarks><tt>Comparison</tt> will be <tt>Equal</tt>, value will be an empty string</remarks>
|
||||
/// <remarks><c>Comparison</c> will be <c>Equal</c>, value will be an empty string</remarks>
|
||||
static member Named name =
|
||||
Field.Where name (Equal "")
|
||||
|
||||
|
||||
/// <summary>Specify the name of the parameter for this field</summary>
|
||||
/// <param name="name">The parameter name (including <tt>:</tt> or <tt>@</tt>)</param>
|
||||
/// <param name="name">The parameter name (including <c>:</c> or <c>@</c>)</param>
|
||||
/// <returns>A field with the given parameter name specified</returns>
|
||||
member this.WithParameterName name =
|
||||
{ this with ParameterName = Some name }
|
||||
|
||||
|
||||
/// <summary>Specify a qualifier (alias) for the table from which this field will be referenced</summary>
|
||||
/// <param name="alias">The table alias for this field comparison</param>
|
||||
/// <returns>A field with the given qualifier specified</returns>
|
||||
@@ -276,7 +277,7 @@ type Field = {
|
||||
/// <summary>Get the qualified path to the field</summary>
|
||||
/// <param name="dialect">The SQL dialect to use when converting the name to nested path format</param>
|
||||
/// <param name="format">Whether to reference this path as a JSON value or a SQL value</param>
|
||||
/// <returns>A <tt>string</tt> with the qualified path required to address the nested document value</returns>
|
||||
/// <returns>A <c>string</c> with the qualified path required to address the nested document value</returns>
|
||||
member this.Path dialect format =
|
||||
(this.Qualifier |> Option.map (fun q -> $"{q}.") |> Option.defaultValue "")
|
||||
+ Field.NameToPath this.Name dialect format
|
||||
@@ -285,13 +286,13 @@ type Field = {
|
||||
/// <summary>How fields should be matched</summary>
|
||||
[<Struct>]
|
||||
type FieldMatch =
|
||||
|
||||
/// <summary>Any field matches (<tt>OR</tt>)</summary>
|
||||
|
||||
/// <summary>Any field matches (<c>OR</c>)</summary>
|
||||
| Any
|
||||
|
||||
/// <summary>All fields match (<tt>AND</tt>)</summary>
|
||||
|
||||
/// <summary>All fields match (<c>AND</c>)</summary>
|
||||
| All
|
||||
|
||||
|
||||
/// <summary>The SQL value implementing each matching strategy</summary>
|
||||
override this.ToString() =
|
||||
match this with Any -> "OR" | All -> "AND"
|
||||
@@ -299,10 +300,10 @@ type FieldMatch =
|
||||
|
||||
/// <summary>Derive parameter names (each instance wraps a counter to uniquely name anonymous fields)</summary>
|
||||
type ParameterName() =
|
||||
|
||||
|
||||
/// The counter for the next field value
|
||||
let mutable currentIdx = -1
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Return the specified name for the parameter, or an anonymous parameter name if none is specified
|
||||
/// </summary>
|
||||
@@ -319,30 +320,30 @@ type ParameterName() =
|
||||
/// <summary>Automatically-generated document ID strategies</summary>
|
||||
[<Struct>]
|
||||
type AutoId =
|
||||
|
||||
|
||||
/// <summary>No automatic IDs will be generated</summary>
|
||||
| Disabled
|
||||
|
||||
|
||||
/// <summary>Generate a MAX-plus-1 numeric value for documents</summary>
|
||||
| Number
|
||||
|
||||
/// <summary>Generate a <tt>GUID</tt> for each document (as a lowercase, no-dashes, 32-character string)</summary>
|
||||
|
||||
/// <summary>Generate a <c>GUID</c> for each document (as a lowercase, no-dashes, 32-character string)</summary>
|
||||
| Guid
|
||||
|
||||
|
||||
/// <summary>Generate a random string of hexadecimal characters for each document</summary>
|
||||
| RandomString
|
||||
with
|
||||
/// <summary>Generate a <tt>GUID</tt> string</summary>
|
||||
/// <returns>A <tt>GUID</tt> string</returns>
|
||||
/// <summary>Generate a <c>GUID</c> string</summary>
|
||||
/// <returns>A <c>GUID</c> string</returns>
|
||||
static member GenerateGuid() =
|
||||
System.Guid.NewGuid().ToString "N"
|
||||
|
||||
|
||||
/// <summary>Generate a string of random hexadecimal characters</summary>
|
||||
/// <param name="length">The number of characters to generate</param>
|
||||
/// <returns>A string of the given length with random hexadecimal characters</returns>
|
||||
static member GenerateRandomString(length: int) =
|
||||
RandomNumberGenerator.GetHexString(length, lowercase = true)
|
||||
|
||||
|
||||
/// <summary>Does the given document need an automatic ID generated?</summary>
|
||||
/// <param name="strategy">The auto-ID strategy currently in use</param>
|
||||
/// <param name="document">The document being inserted</param>
|
||||
@@ -387,26 +388,26 @@ with
|
||||
|
||||
/// <summary>The required document serialization implementation</summary>
|
||||
type IDocumentSerializer =
|
||||
|
||||
|
||||
/// <summary>Serialize an object to a JSON string</summary>
|
||||
abstract Serialize<'T> : 'T -> string
|
||||
|
||||
|
||||
/// <summary>Deserialize a JSON string into an object</summary>
|
||||
abstract Deserialize<'T> : string -> 'T
|
||||
|
||||
|
||||
/// <summary>Document serializer defaults</summary>
|
||||
module DocumentSerializer =
|
||||
|
||||
|
||||
open System.Text.Json
|
||||
open System.Text.Json.Serialization
|
||||
|
||||
|
||||
/// The default JSON serializer options to use with the stock serializer
|
||||
let private jsonDefaultOpts =
|
||||
let o = JsonSerializerOptions()
|
||||
o.Converters.Add(JsonFSharpConverter())
|
||||
o
|
||||
|
||||
|
||||
/// <summary>The default JSON serializer</summary>
|
||||
[<CompiledName "Default">]
|
||||
let ``default`` =
|
||||
@@ -424,7 +425,7 @@ module Configuration =
|
||||
|
||||
/// The serializer to use for document manipulation
|
||||
let mutable private serializerValue = DocumentSerializer.``default``
|
||||
|
||||
|
||||
/// <summary>Register a serializer to use for translating documents to domain types</summary>
|
||||
/// <param name="ser">The serializer to use when manipulating documents</param>
|
||||
[<CompiledName "UseSerializer">]
|
||||
@@ -436,46 +437,46 @@ module Configuration =
|
||||
[<CompiledName "Serializer">]
|
||||
let serializer () =
|
||||
serializerValue
|
||||
|
||||
|
||||
/// The serialized name of the ID field for documents
|
||||
let mutable private idFieldValue = "Id"
|
||||
|
||||
|
||||
/// <summary>Specify the name of the ID field for documents</summary>
|
||||
/// <param name="it">The name of the ID field for documents</param>
|
||||
[<CompiledName "UseIdField">]
|
||||
let useIdField it =
|
||||
idFieldValue <- it
|
||||
|
||||
|
||||
/// <summary>Retrieve the currently configured ID field for documents</summary>
|
||||
/// <returns>The currently configured ID field</returns>
|
||||
[<CompiledName "IdField">]
|
||||
let idField () =
|
||||
idFieldValue
|
||||
|
||||
|
||||
/// The automatic ID strategy used by the library
|
||||
let mutable private autoIdValue = Disabled
|
||||
|
||||
|
||||
/// <summary>Specify the automatic ID generation strategy used by the library</summary>
|
||||
/// <param name="it">The automatic ID generation strategy to use</param>
|
||||
[<CompiledName "UseAutoIdStrategy">]
|
||||
let useAutoIdStrategy it =
|
||||
autoIdValue <- it
|
||||
|
||||
|
||||
/// <summary>Retrieve the currently configured automatic ID generation strategy</summary>
|
||||
/// <returns>The current automatic ID generation strategy</returns>
|
||||
[<CompiledName "AutoIdStrategy">]
|
||||
let autoIdStrategy () =
|
||||
autoIdValue
|
||||
|
||||
|
||||
/// The length of automatically generated random strings
|
||||
let mutable private idStringLengthValue = 16
|
||||
|
||||
|
||||
/// <summary>Specify the length of automatically generated random strings</summary>
|
||||
/// <param name="length">The length of automatically generated random strings</param>
|
||||
[<CompiledName "UseIdStringLength">]
|
||||
let useIdStringLength length =
|
||||
idStringLengthValue <- length
|
||||
|
||||
|
||||
/// <summary>Retrieve the currently configured length of automatically generated random strings</summary>
|
||||
/// <returns>The current length of automatically generated random strings</returns>
|
||||
[<CompiledName "IdStringLength">]
|
||||
@@ -486,31 +487,31 @@ module Configuration =
|
||||
/// <summary>Query construction functions</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Query =
|
||||
|
||||
/// <summary>Combine a query (<tt>SELECT</tt>, <tt>UPDATE</tt>, etc.) and a <tt>WHERE</tt> clause</summary>
|
||||
|
||||
/// <summary>Combine a query (<c>SELECT</c>, <c>UPDATE</c>, etc.) and a <c>WHERE</c> clause</summary>
|
||||
/// <param name="statement">The first part of the statement</param>
|
||||
/// <param name="where">The <tt>WHERE</tt> clause for the statement</param>
|
||||
/// <returns>The two parts of the query combined with <tt>WHERE</tt></returns>
|
||||
/// <param name="where">The <c>WHERE</c> clause for the statement</param>
|
||||
/// <returns>The two parts of the query combined with <c>WHERE</c></returns>
|
||||
[<CompiledName "StatementWhere">]
|
||||
let statementWhere statement where =
|
||||
$"%s{statement} WHERE %s{where}"
|
||||
|
||||
|
||||
/// <summary>Queries to define tables and indexes</summary>
|
||||
module Definition =
|
||||
|
||||
|
||||
/// <summary>SQL statement to create a document table</summary>
|
||||
/// <param name="name">The name of the table to create (may include schema)</param>
|
||||
/// <param name="dataType">The type of data for the column (<tt>JSON</tt>, <tt>JSONB</tt>, etc.)</param>
|
||||
/// <param name="dataType">The type of data for the column (<c>JSON</c>, <c>JSONB</c>, etc.)</param>
|
||||
/// <returns>A query to create a document table</returns>
|
||||
[<CompiledName "EnsureTableFor">]
|
||||
let ensureTableFor name dataType =
|
||||
$"CREATE TABLE IF NOT EXISTS %s{name} (data %s{dataType} NOT NULL)"
|
||||
|
||||
|
||||
/// Split a schema and table name
|
||||
let private splitSchemaAndTable (tableName: string) =
|
||||
let parts = tableName.Split '.'
|
||||
if Array.length parts = 1 then "", tableName else parts[0], parts[1]
|
||||
|
||||
|
||||
/// <summary>SQL statement to create an index on one or more fields in a JSON document</summary>
|
||||
/// <param name="tableName">The table on which an index should be created (may include schema)</param>
|
||||
/// <param name="indexName">The name of the index to be created</param>
|
||||
@@ -537,7 +538,7 @@ module Query =
|
||||
[<CompiledName "EnsureKey">]
|
||||
let ensureKey tableName dialect =
|
||||
(ensureIndexOn tableName "key" [ Configuration.idField () ] dialect).Replace("INDEX", "UNIQUE INDEX")
|
||||
|
||||
|
||||
/// <summary>Query to insert a document</summary>
|
||||
/// <param name="tableName">The table into which to insert (may include schema)</param>
|
||||
/// <returns>A query to insert a document</returns>
|
||||
@@ -554,48 +555,48 @@ module Query =
|
||||
let save tableName =
|
||||
sprintf
|
||||
"INSERT INTO %s VALUES (@data) ON CONFLICT ((data->>'%s')) DO UPDATE SET data = EXCLUDED.data"
|
||||
tableName (Configuration.idField ())
|
||||
|
||||
tableName (Configuration.idField ())
|
||||
|
||||
/// <summary>Query to count documents in a table</summary>
|
||||
/// <param name="tableName">The table in which to count documents (may include schema)</param>
|
||||
/// <returns>A query to count documents</returns>
|
||||
/// <remarks>This query has no <tt>WHERE</tt> clause</remarks>
|
||||
/// <remarks>This query has no <c>WHERE</c> clause</remarks>
|
||||
[<CompiledName "Count">]
|
||||
let count tableName =
|
||||
$"SELECT COUNT(*) AS it FROM %s{tableName}"
|
||||
|
||||
|
||||
/// <summary>Query to check for document existence in a table</summary>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="where">The <tt>WHERE</tt> clause with the existence criteria</param>
|
||||
/// <param name="where">The <c>WHERE</c> clause with the existence criteria</param>
|
||||
/// <returns>A query to check document existence</returns>
|
||||
[<CompiledName "Exists">]
|
||||
let exists tableName where =
|
||||
$"SELECT EXISTS (SELECT 1 FROM %s{tableName} WHERE %s{where}) AS it"
|
||||
|
||||
|
||||
/// <summary>Query to select documents from a table</summary>
|
||||
/// <param name="tableName">The table from which documents should be found (may include schema)</param>
|
||||
/// <returns>A query to retrieve documents</returns>
|
||||
/// <remarks>This query has no <tt>WHERE</tt> clause</remarks>
|
||||
/// <remarks>This query has no <c>WHERE</c> clause</remarks>
|
||||
[<CompiledName "Find">]
|
||||
let find tableName =
|
||||
$"SELECT data FROM %s{tableName}"
|
||||
|
||||
|
||||
/// <summary>Query to update (replace) a document</summary>
|
||||
/// <param name="tableName">The table in which documents should be replaced (may include schema)</param>
|
||||
/// <returns>A query to update documents</returns>
|
||||
/// <remarks>This query has no <tt>WHERE</tt> clause</remarks>
|
||||
/// <remarks>This query has no <c>WHERE</c> clause</remarks>
|
||||
[<CompiledName "Update">]
|
||||
let update tableName =
|
||||
$"UPDATE %s{tableName} SET data = @data"
|
||||
|
||||
|
||||
/// <summary>Query to delete documents from a table</summary>
|
||||
/// <param name="tableName">The table in which documents should be deleted (may include schema)</param>
|
||||
/// <returns>A query to delete documents</returns>
|
||||
/// <remarks>This query has no <tt>WHERE</tt> clause</remarks>
|
||||
/// <remarks>This query has no <c>WHERE</c> clause</remarks>
|
||||
[<CompiledName "Delete">]
|
||||
let delete tableName =
|
||||
$"DELETE FROM %s{tableName}"
|
||||
|
||||
|
||||
/// <summary>Create a SELECT clause to retrieve the document data from the given table</summary>
|
||||
/// <param name="tableName">The table from which documents should be found (may include schema)</param>
|
||||
/// <returns>A query to retrieve documents</returns>
|
||||
@@ -603,11 +604,11 @@ module Query =
|
||||
[<System.Obsolete "Use Find instead">]
|
||||
let selectFromTable tableName =
|
||||
find tableName
|
||||
|
||||
/// <summary>Create an <tt>ORDER BY</tt> clause for the given fields</summary>
|
||||
|
||||
/// <summary>Create an <c>ORDER BY</c> clause for the given fields</summary>
|
||||
/// <param name="fields">One or more fields by which to order</param>
|
||||
/// <param name="dialect">The SQL dialect for the generated clause</param>
|
||||
/// <returns>An <tt>ORDER BY</tt> clause for the given fields</returns>
|
||||
/// <returns>An <c>ORDER BY</c> clause for the given fields</returns>
|
||||
[<CompiledName "OrderBy">]
|
||||
let orderBy fields dialect =
|
||||
if Seq.isEmpty fields then ""
|
||||
@@ -631,3 +632,49 @@ module Query =
|
||||
|> function path -> path + defaultArg direction "")
|
||||
|> String.concat ", "
|
||||
|> function it -> $" ORDER BY {it}"
|
||||
|
||||
|
||||
#nowarn "FS3511" // "let rec" is not statically compilable
|
||||
|
||||
open System.IO.Pipelines
|
||||
|
||||
/// <summary>Functions that manipulate <c>PipeWriter</c>s</summary>
|
||||
[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
|
||||
module PipeWriter =
|
||||
|
||||
/// <summary>Write a UTF-8 string to this pipe</summary>
|
||||
/// <param name="writer">The PipeWriter to which the string should be written</param>
|
||||
/// <param name="text">The string to be written to the pipe</param>
|
||||
/// <returns><c>true</c> if the pipe is still open, <c>false</c> if not</returns>
|
||||
[<CompiledName "WriteString">]
|
||||
let writeString (writer: PipeWriter) (text: string) = backgroundTask {
|
||||
try
|
||||
let! writeResult = writer.WriteAsync(Encoding.UTF8.GetBytes text)
|
||||
return not writeResult.IsCompleted
|
||||
with :? System.ObjectDisposedException -> return false
|
||||
}
|
||||
|
||||
/// <summary>Write an array of strings, abandoning the sequence if the pipe is closed</summary>
|
||||
/// <param name="writer">The PipeWriter to which the strings should be written</param>
|
||||
/// <param name="items">The strings to be written</param>
|
||||
/// <returns><c>true</c> if the pipe is still open, <c>false</c> if not</returns>
|
||||
[<CompiledName "WriteStrings">]
|
||||
let writeStrings writer items = backgroundTask {
|
||||
let theItems = Seq.cache items
|
||||
let rec writeNext idx = backgroundTask {
|
||||
match theItems |> Seq.tryItem idx with
|
||||
| Some item ->
|
||||
if idx > 0 then
|
||||
let! _ = writeString writer ","
|
||||
()
|
||||
match! writeString writer item with
|
||||
| true -> return! writeNext (idx + 1)
|
||||
| false -> return false
|
||||
| None -> return true
|
||||
}
|
||||
let! _ = writeString writer "["
|
||||
let! isCleanFinish = writeNext 0
|
||||
if isCleanFinish then
|
||||
let! _ = writeString writer "]"
|
||||
()
|
||||
}
|
||||
|
||||
@@ -8,11 +8,11 @@ This package provides common definitions and functionality for `BitBadger.Docume
|
||||
|
||||
- Select, insert, update, save (upsert), delete, count, and check existence of documents, and create tables and indexes for these documents
|
||||
- Automatically generate IDs for documents (numeric IDs, GUIDs, or random strings)
|
||||
- Addresses documents via ID and via comparison on any field (for PostgreSQL, also via equality on any property by using JSON containment, or via condition on any property using JSON Path queries)
|
||||
- Accesses documents as your domain models (<abbr title="Plain Old CLR Objects">POCO</abbr>s)
|
||||
- Uses `Task`-based async for all data access functions
|
||||
- Uses building blocks for more complex queries
|
||||
- Address documents via ID and via comparison on any field (for PostgreSQL, also via equality on any property by using JSON containment, or via condition on any property using JSON Path queries)
|
||||
- Access documents as your domain models (<abbr title="Plain Old CLR Objects">POCO</abbr>s), as JSON strings, or as JSON written directly to a `PipeWriter`
|
||||
- Use `Task`-based async for all data access functions
|
||||
- Use building blocks for more complex queries
|
||||
|
||||
## Getting Started
|
||||
|
||||
Install the library of your choice and follow its README; also, the [project site](https://bitbadger.solutions/open-source/relational-documents/) has complete documentation.
|
||||
Install the library of your choice and follow its README; also, the [project site](https://relationaldocs.bitbadger.solutions/dotnet/) has complete documentation.
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
<TargetFrameworks>net8.0;net9.0</TargetFrameworks>
|
||||
<DebugType>embedded</DebugType>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<AssemblyVersion>4.0.1.0</AssemblyVersion>
|
||||
<FileVersion>4.0.1.0</FileVersion>
|
||||
<VersionPrefix>4.0.1</VersionPrefix>
|
||||
<PackageReleaseNotes>From v4.0: Add XML documention (IDE support)
|
||||
From v3.1: See 4.0 release for breaking changes and compatibility</PackageReleaseNotes>
|
||||
<AssemblyVersion>4.1.0.0</AssemblyVersion>
|
||||
<FileVersion>4.1.0.0</FileVersion>
|
||||
<VersionPrefix>4.1.0</VersionPrefix>
|
||||
<PackageReleaseNotes>Add JSON retrieval and pipe-writing functions; update project URL to site with public API docs</PackageReleaseNotes>
|
||||
<Authors>danieljsummers</Authors>
|
||||
<Company>Bit Badger Solutions</Company>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
<PackageIcon>icon.png</PackageIcon>
|
||||
<PackageProjectUrl>https://bitbadger.solutions/open-source/relational-documents/</PackageProjectUrl>
|
||||
<PackageProjectUrl>https://relationaldocs.bitbadger.solutions/dotnet/</PackageProjectUrl>
|
||||
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
|
||||
<RepositoryUrl>https://git.bitbadger.solutions/bit-badger/BitBadger.Documents</RepositoryUrl>
|
||||
<RepositoryType>Git</RepositoryType>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -21,11 +21,45 @@ module Custom =
|
||||
let List<'TDoc>(query, parameters, mapFunc: System.Func<RowReader, 'TDoc>) =
|
||||
WithProps.Custom.List<'TDoc>(query, parameters, mapFunc, fromDataSource ())
|
||||
|
||||
/// <summary>Execute a query that returns a JSON array of results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>A JSON array of results for the given query</returns>
|
||||
[<CompiledName "FSharpJsonArray">]
|
||||
let jsonArray query parameters mapFunc =
|
||||
WithProps.Custom.jsonArray query parameters mapFunc (fromDataSource ())
|
||||
|
||||
/// <summary>Execute a query that returns a JSON array of results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>A JSON array of results for the given query</returns>
|
||||
let JsonArray(query, parameters, mapFunc) =
|
||||
WithProps.Custom.JsonArray(query, parameters, mapFunc, fromDataSource ())
|
||||
|
||||
/// <summary>Execute a query, writing its results to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
[<CompiledName "FSharpWriteJsonArray">]
|
||||
let writeJsonArray query parameters writer mapFunc =
|
||||
WithProps.Custom.writeJsonArray query parameters writer mapFunc (fromDataSource ())
|
||||
|
||||
/// <summary>Execute a query, writing its results to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
let WriteJsonArray(query, parameters, writer, mapFunc) =
|
||||
WithProps.Custom.WriteJsonArray(query, parameters, writer, mapFunc, fromDataSource ())
|
||||
|
||||
/// <summary>Execute a query that returns one or no results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <returns><tt>Some</tt> with the first matching result, or <tt>None</tt> if not found</returns>
|
||||
/// <returns><c>Some</c> with the first matching result, or <c>None</c> if not found</returns>
|
||||
[<CompiledName "FSharpSingle">]
|
||||
let single<'TDoc> query parameters (mapFunc: RowReader -> 'TDoc) =
|
||||
WithProps.Custom.single<'TDoc> query parameters mapFunc (fromDataSource ())
|
||||
@@ -34,11 +68,28 @@ module Custom =
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <returns>The first matching result, or <tt>null</tt> if not found</returns>
|
||||
/// <returns>The first matching result, or <c>null</c> if not found</returns>
|
||||
let Single<'TDoc when 'TDoc: null and 'TDoc: not struct>(
|
||||
query, parameters, mapFunc: System.Func<RowReader, 'TDoc>) =
|
||||
WithProps.Custom.Single<'TDoc>(query, parameters, mapFunc, fromDataSource ())
|
||||
|
||||
/// <summary>Execute a query that returns one or no JSON documents</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>The JSON document with the first matching result, or an empty document if not found</returns>
|
||||
[<CompiledName "FSharpJsonSingle">]
|
||||
let jsonSingle query parameters mapFunc =
|
||||
WithProps.Custom.jsonSingle query parameters mapFunc (fromDataSource ())
|
||||
|
||||
/// <summary>Execute a query that returns one or no JSON documents</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>The JSON document with the first matching result, or an empty document if not found</returns>
|
||||
let JsonSingle(query, parameters, mapFunc) =
|
||||
WithProps.Custom.JsonSingle(query, parameters, mapFunc, fromDataSource ())
|
||||
|
||||
/// <summary>Execute a query that returns no results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
@@ -120,7 +171,7 @@ module Count =
|
||||
let all tableName =
|
||||
WithProps.Count.all tableName (fromDataSource ())
|
||||
|
||||
/// <summary>Count matching documents using JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Count matching documents using JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which documents should be counted (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
@@ -129,7 +180,7 @@ module Count =
|
||||
let byFields tableName howMatched fields =
|
||||
WithProps.Count.byFields tableName howMatched fields (fromDataSource ())
|
||||
|
||||
/// <summary>Count matching documents using a JSON containment query (<tt>@></tt>)</summary>
|
||||
/// <summary>Count matching documents using a JSON containment query (<c>@></c>)</summary>
|
||||
/// <param name="tableName">The table in which documents should be counted (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <returns>The count of the documents in the table</returns>
|
||||
@@ -137,7 +188,7 @@ module Count =
|
||||
let byContains tableName criteria =
|
||||
WithProps.Count.byContains tableName criteria (fromDataSource ())
|
||||
|
||||
/// <summary>Count matching documents using a JSON Path match query (<tt>@?</tt>)</summary>
|
||||
/// <summary>Count matching documents using a JSON Path match query (<c>@?</c>)</summary>
|
||||
/// <param name="tableName">The table in which documents should be counted (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to be matched</param>
|
||||
/// <returns>The count of the documents in the table</returns>
|
||||
@@ -158,7 +209,7 @@ module Exists =
|
||||
let byId tableName docId =
|
||||
WithProps.Exists.byId tableName docId (fromDataSource ())
|
||||
|
||||
/// <summary>Determine if a document exists using JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Determine if a document exists using JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
@@ -167,7 +218,7 @@ module Exists =
|
||||
let byFields tableName howMatched fields =
|
||||
WithProps.Exists.byFields tableName howMatched fields (fromDataSource ())
|
||||
|
||||
/// <summary>Determine if a document exists using a JSON containment query (<tt>@></tt>)</summary>
|
||||
/// <summary>Determine if a document exists using a JSON containment query (<c>@></c>)</summary>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <returns>True if any matching documents exist, false if not</returns>
|
||||
@@ -175,7 +226,7 @@ module Exists =
|
||||
let byContains tableName criteria =
|
||||
WithProps.Exists.byContains tableName criteria (fromDataSource ())
|
||||
|
||||
/// <summary>Determine if a document exists using a JSON Path match query (<tt>@?</tt>)</summary>
|
||||
/// <summary>Determine if a document exists using a JSON Path match query (<c>@?</c>)</summary>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to be matched</param>
|
||||
/// <returns>True if any matching documents exist, false if not</returns>
|
||||
@@ -184,7 +235,7 @@ module Exists =
|
||||
WithProps.Exists.byJsonPath tableName jsonPath (fromDataSource ())
|
||||
|
||||
|
||||
/// <summary>Commands to retrieve documents</summary>
|
||||
/// <summary>Commands to retrieve documents as domain objects</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Find =
|
||||
|
||||
@@ -219,7 +270,7 @@ module Find =
|
||||
/// <summary>Retrieve a document by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <returns><tt>Some</tt> with the document if found, <tt>None</tt> otherwise</returns>
|
||||
/// <returns><c>Some</c> with the document if found, <c>None</c> otherwise</returns>
|
||||
[<CompiledName "FSharpById">]
|
||||
let byId<'TKey, 'TDoc> tableName docId =
|
||||
WithProps.Find.byId<'TKey, 'TDoc> tableName docId (fromDataSource ())
|
||||
@@ -227,11 +278,11 @@ module Find =
|
||||
/// <summary>Retrieve a document by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <returns>The document if found, <tt>null</tt> otherwise</returns>
|
||||
/// <returns>The document if found, <c>null</c> otherwise</returns>
|
||||
let ById<'TKey, 'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, docId: 'TKey) =
|
||||
WithProps.Find.ById<'TKey, 'TDoc>(tableName, docId, fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
@@ -240,7 +291,7 @@ module Find =
|
||||
let byFields<'TDoc> tableName howMatched fields =
|
||||
WithProps.Find.byFields<'TDoc> tableName howMatched fields (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
@@ -249,8 +300,8 @@ module Find =
|
||||
WithProps.Find.ByFields<'TDoc>(tableName, howMatched, fields, fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching JSON field comparisons (<tt>->> =</tt>, etc.) ordered by the given fields in
|
||||
/// the document
|
||||
/// Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
@@ -262,8 +313,8 @@ module Find =
|
||||
WithProps.Find.byFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching JSON field comparisons (<tt>->> =</tt>, etc.) ordered by the given fields in
|
||||
/// the document
|
||||
/// Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
@@ -273,7 +324,7 @@ module Find =
|
||||
let ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields) =
|
||||
WithProps.Find.ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve documents matching a JSON containment query (<tt>@></tt>)</summary>
|
||||
/// <summary>Retrieve documents matching a JSON containment query (<c>@></c>)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <returns>All documents matching the given containment query</returns>
|
||||
@@ -281,7 +332,7 @@ module Find =
|
||||
let byContains<'TDoc> tableName (criteria: obj) =
|
||||
WithProps.Find.byContains<'TDoc> tableName criteria (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve documents matching a JSON containment query (<tt>@></tt>)</summary>
|
||||
/// <summary>Retrieve documents matching a JSON containment query (<c>@></c>)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <returns>All documents matching the given containment query</returns>
|
||||
@@ -289,8 +340,7 @@ module Find =
|
||||
WithProps.Find.ByContains<'TDoc>(tableName, criteria, fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching a JSON containment query (<tt>@></tt>) ordered by the given fields in the
|
||||
/// document
|
||||
/// Retrieve documents matching a JSON containment query (<c>@></c>) ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
@@ -301,8 +351,7 @@ module Find =
|
||||
WithProps.Find.byContainsOrdered<'TDoc> tableName criteria orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching a JSON containment query (<tt>@></tt>) ordered by the given fields in the
|
||||
/// document
|
||||
/// Retrieve documents matching a JSON containment query (<c>@></c>) ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
@@ -311,7 +360,7 @@ module Find =
|
||||
let ByContainsOrdered<'TDoc>(tableName, criteria: obj, orderFields) =
|
||||
WithProps.Find.ByContainsOrdered<'TDoc>(tableName, criteria, orderFields, fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve documents matching a JSON Path match query (<tt>@?</tt>)</summary>
|
||||
/// <summary>Retrieve documents matching a JSON Path match query (<c>@?</c>)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <returns>All documents matching the given JSON Path expression</returns>
|
||||
@@ -319,7 +368,7 @@ module Find =
|
||||
let byJsonPath<'TDoc> tableName jsonPath =
|
||||
WithProps.Find.byJsonPath<'TDoc> tableName jsonPath (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve documents matching a JSON Path match query (<tt>@?</tt>)</summary>
|
||||
/// <summary>Retrieve documents matching a JSON Path match query (<c>@?</c>)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <returns>All documents matching the given JSON Path expression</returns>
|
||||
@@ -327,7 +376,7 @@ module Find =
|
||||
WithProps.Find.ByJsonPath<'TDoc>(tableName, jsonPath, fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching a JSON Path match query (<tt>@?</tt>) ordered by the given fields in the document
|
||||
/// Retrieve documents matching a JSON Path match query (<c>@?</c>) ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
@@ -338,7 +387,7 @@ module Find =
|
||||
WithProps.Find.byJsonPathOrdered<'TDoc> tableName jsonPath orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching a JSON Path match query (<tt>@?</tt>) ordered by the given fields in the document
|
||||
/// Retrieve documents matching a JSON Path match query (<c>@?</c>) ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
@@ -347,132 +396,442 @@ module Find =
|
||||
let ByJsonPathOrdered<'TDoc>(tableName, jsonPath, orderFields) =
|
||||
WithProps.Find.ByJsonPathOrdered<'TDoc>(tableName, jsonPath, orderFields, fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns><tt>Some</tt> with the first document, or <tt>None</tt> if not found</returns>
|
||||
/// <returns><c>Some</c> with the first document, or <c>None</c> if not found</returns>
|
||||
[<CompiledName "FSharpFirstByFields">]
|
||||
let firstByFields<'TDoc> tableName howMatched fields =
|
||||
WithProps.Find.firstByFields<'TDoc> tableName howMatched fields (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>The first document, or <tt>null</tt> if not found</returns>
|
||||
/// <returns>The first document, or <c>null</c> if not found</returns>
|
||||
let FirstByFields<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, howMatched, fields) =
|
||||
WithProps.Find.FirstByFields<'TDoc>(tableName, howMatched, fields, fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching JSON field comparisons (<tt>->> =</tt>, etc.) ordered by the given
|
||||
/// Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>
|
||||
/// <tt>Some</tt> with the first document ordered by the given fields, or <tt>None</tt> if not found
|
||||
/// </returns>
|
||||
/// <returns><c>Some</c> with the first document ordered by the given fields, or <c>None</c> if not found</returns>
|
||||
[<CompiledName "FSharpFirstByFieldsOrdered">]
|
||||
let firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields =
|
||||
WithProps.Find.firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching JSON field comparisons (<tt>->> =</tt>, etc.) ordered by the given
|
||||
/// Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>The first document ordered by the given fields, or <tt>null</tt> if not found</returns>
|
||||
/// <returns>The first document ordered by the given fields, or <c>null</c> if not found</returns>
|
||||
let FirstByFieldsOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>(
|
||||
tableName, howMatched, queryFields, orderFields) =
|
||||
WithProps.Find.FirstByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve the first document matching a JSON containment query (<tt>@></tt>)</summary>
|
||||
/// <summary>Retrieve the first document matching a JSON containment query (<c>@></c>)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <returns><tt>Some</tt> with the first document, or <tt>None</tt> if not found</returns>
|
||||
/// <returns><c>Some</c> with the first document, or <c>None</c> if not found</returns>
|
||||
[<CompiledName "FSharpFirstByContains">]
|
||||
let firstByContains<'TDoc> tableName (criteria: obj) =
|
||||
WithProps.Find.firstByContains<'TDoc> tableName criteria (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve the first document matching a JSON containment query (<tt>@></tt>)</summary>
|
||||
/// <summary>Retrieve the first document matching a JSON containment query (<c>@></c>)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <returns>The first document, or <tt>null</tt> if not found</returns>
|
||||
/// <returns>The first document, or <c>null</c> if not found</returns>
|
||||
let FirstByContains<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, criteria: obj) =
|
||||
WithProps.Find.FirstByContains<'TDoc>(tableName, criteria, fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching a JSON containment query (<tt>@></tt>) ordered by the given fields in
|
||||
/// the document
|
||||
/// Retrieve the first document matching a JSON containment query (<c>@></c>) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>
|
||||
/// <tt>Some</tt> with the first document ordered by the given fields, or <tt>None</tt> if not found
|
||||
/// </returns>
|
||||
/// <returns><c>Some</c> with the first document ordered by the given fields, or <c>None</c> if not found</returns>
|
||||
[<CompiledName "FSharpFirstByContainsOrdered">]
|
||||
let firstByContainsOrdered<'TDoc> tableName (criteria: obj) orderFields =
|
||||
WithProps.Find.firstByContainsOrdered<'TDoc> tableName criteria orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching a JSON containment query (<tt>@></tt>) ordered by the given fields in
|
||||
/// the document
|
||||
/// Retrieve the first document matching a JSON containment query (<c>@></c>) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>The first document ordered by the given fields, or <tt>null</tt> if not found</returns>
|
||||
/// <returns>The first document ordered by the given fields, or <c>null</c> if not found</returns>
|
||||
let FirstByContainsOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, criteria: obj, orderFields) =
|
||||
WithProps.Find.FirstByContainsOrdered<'TDoc>(tableName, criteria, orderFields, fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve the first document matching a JSON Path match query (<tt>@?</tt>)</summary>
|
||||
/// <summary>Retrieve the first document matching a JSON Path match query (<c>@?</c>)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <returns><tt>Some</tt> with the first document, or <tt>None</tt> if not found</returns>
|
||||
/// <returns><c>Some</c> with the first document, or <c>None</c> if not found</returns>
|
||||
[<CompiledName "FSharpFirstByJsonPath">]
|
||||
let firstByJsonPath<'TDoc> tableName jsonPath =
|
||||
WithProps.Find.firstByJsonPath<'TDoc> tableName jsonPath (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve the first document matching a JSON Path match query (<tt>@?</tt>)</summary>
|
||||
/// <summary>Retrieve the first document matching a JSON Path match query (<c>@?</c>)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <returns>The first document, or <tt>null</tt> if not found</returns>
|
||||
/// <returns>The first document, or <c>null</c> if not found</returns>
|
||||
let FirstByJsonPath<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, jsonPath) =
|
||||
WithProps.Find.FirstByJsonPath<'TDoc>(tableName, jsonPath, fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching a JSON Path match query (<tt>@?</tt>) ordered by the given fields in the
|
||||
/// Retrieve the first document matching a JSON Path match query (<c>@?</c>) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>
|
||||
/// <tt>Some</tt> with the first document ordered by the given fields, or <tt>None</tt> if not found
|
||||
/// </returns>
|
||||
/// <returns><c>Some</c> with the first document ordered by the given fields, or <c>None</c> if not found</returns>
|
||||
[<CompiledName "FSharpFirstByJsonPathOrdered">]
|
||||
let firstByJsonPathOrdered<'TDoc> tableName jsonPath orderFields =
|
||||
WithProps.Find.firstByJsonPathOrdered<'TDoc> tableName jsonPath orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching a JSON Path match query (<tt>@?</tt>) ordered by the given fields in the
|
||||
/// Retrieve the first document matching a JSON Path match query (<c>@?</c>) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>The first document ordered by the given fields, or <tt>null</tt> if not found</returns>
|
||||
/// <returns>The first document ordered by the given fields, or <c>null</c> if not found</returns>
|
||||
let FirstByJsonPathOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, jsonPath, orderFields) =
|
||||
WithProps.Find.FirstByJsonPathOrdered<'TDoc>(tableName, jsonPath, orderFields, fromDataSource ())
|
||||
|
||||
|
||||
/// <summary>Commands to retrieve documents as JSON</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Json =
|
||||
|
||||
/// <summary>Retrieve all documents in the given table as a JSON array</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <returns>All documents from the given table as a JSON array</returns>
|
||||
[<CompiledName "All">]
|
||||
let all tableName =
|
||||
WithProps.Json.all tableName (fromDataSource ())
|
||||
|
||||
/// <summary>Write all documents in the given table to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
[<CompiledName "WriteAll">]
|
||||
let writeAll tableName writer =
|
||||
WithProps.Json.writeAll tableName writer (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve all documents in the given table as a JSON array, ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All documents from the given table as a JSON array, ordered by the given fields</returns>
|
||||
[<CompiledName "AllOrdered">]
|
||||
let allOrdered tableName orderFields =
|
||||
WithProps.Json.allOrdered tableName orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write all documents in the given table to the given <c>PipeWriter</c>, ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<CompiledName "WriteAllOrdered">]
|
||||
let writeAllOrdered tableName writer orderFields =
|
||||
WithProps.Json.writeAllOrdered tableName writer orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve a JSON document by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <returns>The JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "ById">]
|
||||
let byId<'TKey> tableName (docId: 'TKey) =
|
||||
WithProps.Json.byId tableName docId (fromDataSource ())
|
||||
|
||||
/// <summary>Write a JSON document to the given <c>PipeWriter</c> by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
[<CompiledName "WriteById">]
|
||||
let writeById<'TKey> tableName writer (docId: 'TKey) =
|
||||
WithProps.Json.writeById tableName writer docId (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve JSON documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>All JSON documents matching the given fields</returns>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields =
|
||||
WithProps.Json.byFields tableName howMatched fields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching JSON field comparisons (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
[<CompiledName "WriteByFields">]
|
||||
let writeByFields tableName writer howMatched fields =
|
||||
WithProps.Json.writeByFields tableName writer howMatched fields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve JSON documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields
|
||||
/// in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All JSON documents matching the given fields, ordered by the other given fields</returns>
|
||||
[<CompiledName "ByFieldsOrdered">]
|
||||
let byFieldsOrdered tableName howMatched queryFields orderFields =
|
||||
WithProps.Json.byFieldsOrdered tableName howMatched queryFields orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching JSON field comparisons (<c>->> =</c>, etc.)
|
||||
/// ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<CompiledName "WriteByFieldsOrdered">]
|
||||
let writeByFieldsOrdered tableName writer howMatched queryFields orderFields =
|
||||
WithProps.Json.writeByFieldsOrdered tableName writer howMatched queryFields orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve JSON documents matching a JSON containment query (<c>@></c>)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <returns>All JSON documents matching the given containment query</returns>
|
||||
[<CompiledName "ByContains">]
|
||||
let byContains tableName (criteria: obj) =
|
||||
WithProps.Json.byContains tableName criteria (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching a JSON containment query (<c>@></c>)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
[<CompiledName "WriteByContains">]
|
||||
let writeByContains tableName writer (criteria: obj) =
|
||||
WithProps.Json.writeByContains tableName writer criteria (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve JSON documents matching a JSON containment query (<c>@></c>) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All documents matching the given containment query, ordered by the given fields</returns>
|
||||
[<CompiledName "ByContainsOrdered">]
|
||||
let byContainsOrdered tableName (criteria: obj) orderFields =
|
||||
WithProps.Json.byContainsOrdered tableName criteria orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching a JSON containment query (<c>@></c>) ordered by
|
||||
/// the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<CompiledName "WriteByContainsOrdered">]
|
||||
let writeByContainsOrdered tableName writer (criteria: obj) orderFields =
|
||||
WithProps.Json.writeByContainsOrdered tableName writer criteria orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve JSON documents matching a JSON Path match query (<c>@?</c>)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <returns>All JSON documents matching the given JSON Path expression</returns>
|
||||
[<CompiledName "ByJsonPath">]
|
||||
let byJsonPath tableName jsonPath =
|
||||
WithProps.Json.byJsonPath tableName jsonPath (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching a JSON Path match query (<c>@?</c>)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
[<CompiledName "WriteByJsonPath">]
|
||||
let writeByJsonPath tableName writer jsonPath =
|
||||
WithProps.Json.writeByJsonPath tableName writer jsonPath (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve JSON documents matching a JSON Path match query (<c>@?</c>) ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All JSON documents matching the given JSON Path expression, ordered by the given fields</returns>
|
||||
[<CompiledName "ByJsonPathOrdered">]
|
||||
let byJsonPathOrdered tableName jsonPath orderFields =
|
||||
WithProps.Json.byJsonPathOrdered tableName jsonPath orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching a JSON Path match query (<c>@?</c>) ordered by the
|
||||
/// given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<CompiledName "WriteByJsonPathOrdered">]
|
||||
let writeByJsonPathOrdered tableName writer jsonPath orderFields =
|
||||
WithProps.Json.writeByJsonPathOrdered tableName writer jsonPath orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve the first JSON document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>The first matching JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "FirstByFields">]
|
||||
let firstByFields tableName howMatched fields =
|
||||
WithProps.Json.firstByFields tableName howMatched fields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching JSON field comparisons
|
||||
/// (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
[<CompiledName "WriteFirstByFields">]
|
||||
let writeFirstByFields tableName writer howMatched fields =
|
||||
WithProps.Json.writeFirstByFields tableName writer howMatched fields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first JSON document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>The first matching JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "FirstByFieldsOrdered">]
|
||||
let firstByFieldsOrdered tableName howMatched queryFields orderFields =
|
||||
WithProps.Json.firstByFieldsOrdered tableName howMatched queryFields orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching JSON field comparisons
|
||||
/// (<c>->> =</c>, etc.) ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<CompiledName "WriteFirstByFieldsOrdered">]
|
||||
let writeFirstByFieldsOrdered tableName writer howMatched queryFields orderFields =
|
||||
WithProps.Json.writeFirstByFieldsOrdered tableName writer howMatched queryFields orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve the first JSON document matching a JSON containment query (<c>@></c>)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <returns>The first matching JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "FirstByContains">]
|
||||
let firstByContains tableName (criteria: obj) =
|
||||
WithProps.Json.firstByContains tableName criteria (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching a JSON containment query (<c>@></c>)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
[<CompiledName "WriteFirstByContains">]
|
||||
let writeFirstByContains tableName writer (criteria: obj) =
|
||||
WithProps.Json.writeFirstByContains tableName writer criteria (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first JSON document matching a JSON containment query (<c>@></c>) ordered by the given fields in
|
||||
/// the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>The first matching JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "FirstByContainsOrdered">]
|
||||
let firstByContainsOrdered tableName (criteria: obj) orderFields =
|
||||
WithProps.Json.firstByContainsOrdered tableName criteria orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching a JSON containment query (<c>@></c>)
|
||||
/// ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="criteria">The document to match with the containment query</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<CompiledName "WriteFirstByContainsOrdered">]
|
||||
let writeFirstByContainsOrdered tableName writer (criteria: obj) orderFields =
|
||||
WithProps.Json.writeFirstByContainsOrdered tableName writer criteria orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>Retrieve the first JSON document matching a JSON Path match query (<c>@?</c>)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <returns>The first matching JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "FirstByJsonPath">]
|
||||
let firstByJsonPath tableName jsonPath =
|
||||
WithProps.Json.firstByJsonPath tableName jsonPath (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching a JSON Path match query (<c>@?</c>)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
[<CompiledName "WriteFirstByJsonPath">]
|
||||
let writeFirstByJsonPath tableName writer jsonPath =
|
||||
WithProps.Json.writeFirstByJsonPath tableName writer jsonPath (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first JSON document matching a JSON Path match query (<c>@?</c>) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>The first matching JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "FirstByJsonPathOrdered">]
|
||||
let firstByJsonPathOrdered tableName jsonPath orderFields =
|
||||
WithProps.Json.firstByJsonPathOrdered tableName jsonPath orderFields (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching a JSON Path match query (<c>@?</c>)
|
||||
/// ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<CompiledName "WriteFirstByJsonPathOrdered">]
|
||||
let writeFirstByJsonPathOrdered tableName writer jsonPath orderFields =
|
||||
WithProps.Json.writeFirstByJsonPathOrdered tableName writer jsonPath orderFields (fromDataSource ())
|
||||
|
||||
|
||||
/// <summary>Commands to update documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Update =
|
||||
@@ -518,7 +877,7 @@ module Patch =
|
||||
WithProps.Patch.byId tableName docId patch (fromDataSource ())
|
||||
|
||||
/// <summary>
|
||||
/// Patch documents using a JSON field comparison query in the <tt>WHERE</tt> clause (<tt>->> =</tt>, etc.)
|
||||
/// Patch documents using a JSON field comparison query in the <c>WHERE</c> clause (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table in which documents should be patched (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
@@ -528,7 +887,7 @@ module Patch =
|
||||
let byFields tableName howMatched fields (patch: 'TPatch) =
|
||||
WithProps.Patch.byFields tableName howMatched fields patch (fromDataSource ())
|
||||
|
||||
/// <summary>Patch documents using a JSON containment query in the <tt>WHERE</tt> clause (<tt>@></tt>)</summary>
|
||||
/// <summary>Patch documents using a JSON containment query in the <c>WHERE</c> clause (<c>@></c>)</summary>
|
||||
/// <param name="tableName">The table in which documents should be patched (may include schema)</param>
|
||||
/// <param name="criteria">The document to match the containment query</param>
|
||||
/// <param name="patch">The partial document to patch the existing document</param>
|
||||
@@ -536,7 +895,7 @@ module Patch =
|
||||
let byContains tableName (criteria: 'TCriteria) (patch: 'TPatch) =
|
||||
WithProps.Patch.byContains tableName criteria patch (fromDataSource ())
|
||||
|
||||
/// <summary>Patch documents using a JSON Path match query in the <tt>WHERE</tt> clause (<tt>@?</tt>)</summary>
|
||||
/// <summary>Patch documents using a JSON Path match query in the <c>WHERE</c> clause (<c>@?</c>)</summary>
|
||||
/// <param name="tableName">The table in which documents should be patched (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <param name="patch">The partial document to patch the existing document</param>
|
||||
@@ -566,7 +925,7 @@ module RemoveFields =
|
||||
let byFields tableName howMatched fields fieldNames =
|
||||
WithProps.RemoveFields.byFields tableName howMatched fields fieldNames (fromDataSource ())
|
||||
|
||||
/// <summary>Remove fields from documents via a JSON containment query (<tt>@></tt>)</summary>
|
||||
/// <summary>Remove fields from documents via a JSON containment query (<c>@></c>)</summary>
|
||||
/// <param name="tableName">The table in which documents should be modified (may include schema)</param>
|
||||
/// <param name="criteria">The document to match the containment query</param>
|
||||
/// <param name="fieldNames">One or more field names to remove from the matching documents</param>
|
||||
@@ -574,7 +933,7 @@ module RemoveFields =
|
||||
let byContains tableName (criteria: 'TContains) fieldNames =
|
||||
WithProps.RemoveFields.byContains tableName criteria fieldNames (fromDataSource ())
|
||||
|
||||
/// <summary>Remove fields from documents via a JSON Path match query (<tt>@?</tt>)</summary>
|
||||
/// <summary>Remove fields from documents via a JSON Path match query (<c>@?</c>)</summary>
|
||||
/// <param name="tableName">The table in which documents should be modified (may include schema)</param>
|
||||
/// <param name="jsonPath">The JSON Path expression to match</param>
|
||||
/// <param name="fieldNames">One or more field names to remove from the matching documents</param>
|
||||
@@ -594,7 +953,7 @@ module Delete =
|
||||
let byId tableName (docId: 'TKey) =
|
||||
WithProps.Delete.byId tableName docId (fromDataSource ())
|
||||
|
||||
/// <summary>Delete documents by matching a JSON field comparison query (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Delete documents by matching a JSON field comparison query (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which documents should be deleted (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
@@ -602,7 +961,7 @@ module Delete =
|
||||
let byFields tableName howMatched fields =
|
||||
WithProps.Delete.byFields tableName howMatched fields (fromDataSource ())
|
||||
|
||||
/// <summary>Delete documents by matching a JSON contains query (<tt>@></tt>)</summary>
|
||||
/// <summary>Delete documents by matching a JSON contains query (<c>@></c>)</summary>
|
||||
/// <param name="tableName">The table in which documents should be deleted (may include schema)</param>
|
||||
/// <param name="criteria">The document to match the containment query</param>
|
||||
[<CompiledName "ByContains">]
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
[<Struct>]
|
||||
type DocumentIndex =
|
||||
|
||||
/// <summary>A <tt>GIN</tt> index with standard operations (all operators supported)</summary>
|
||||
/// <summary>A <c>GIN</c> index with standard operations (all operators supported)</summary>
|
||||
| Full
|
||||
|
||||
/// <summary>
|
||||
/// A <tt>GIN</tt> index with JSONPath operations (optimized for <tt>@></tt>, <tt>@?</tt>, <tt>@@</tt> operators)
|
||||
/// A <c>GIN</c> index with JSON Path operations (optimized for <c>@></c>, <c>@?</c>, <c>@@</c> operators)
|
||||
/// </summary>
|
||||
| Optimized
|
||||
|
||||
@@ -94,7 +94,7 @@ module Parameters =
|
||||
name, Sql.jsonb (Configuration.serializer().Serialize it)
|
||||
|
||||
/// <summary>Create JSON field parameters</summary>
|
||||
/// <param name="fields">The <tt>Field</tt>s to convert to parameters</param>
|
||||
/// <param name="fields">The <c>Field</c>s to convert to parameters</param>
|
||||
/// <param name="parameters">The current parameters for the query</param>
|
||||
/// <returns>A unified sequence of parameter names and values</returns>
|
||||
[<CompiledName "AddFields">]
|
||||
@@ -129,7 +129,7 @@ module Parameters =
|
||||
|
||||
/// <summary>Append JSON field name parameters for the given field names to the given parameters</summary>
|
||||
/// <param name="fieldNames">The names of fields to be addressed</param>
|
||||
/// <returns>The name (<tt>@name</tt>) and parameter value for the field names</returns>
|
||||
/// <returns>The name (<c>@name</c>) and parameter value for the field names</returns>
|
||||
[<CompiledName "FieldNames">]
|
||||
let fieldNameParams (fieldNames: string seq) =
|
||||
if Seq.length fieldNames = 1 then "@name", Sql.string (Seq.head fieldNames)
|
||||
@@ -145,12 +145,10 @@ module Parameters =
|
||||
[<RequireQualifiedAccess>]
|
||||
module Query =
|
||||
|
||||
/// <summary>
|
||||
/// Create a <tt>WHERE</tt> clause fragment to implement a comparison on fields in a JSON document
|
||||
/// </summary>
|
||||
/// <summary>Create a <c>WHERE</c> clause fragment to implement a comparison on fields in a JSON document</summary>
|
||||
/// <param name="howMatched">How the fields should be matched</param>
|
||||
/// <param name="fields">The fields for the comparisons</param>
|
||||
/// <returns>A <tt>WHERE</tt> clause implementing the comparisons for the given fields</returns>
|
||||
/// <returns>A <c>WHERE</c> clause implementing the comparisons for the given fields</returns>
|
||||
[<CompiledName "WhereByFields">]
|
||||
let whereByFields (howMatched: FieldMatch) fields =
|
||||
let name = ParameterName()
|
||||
@@ -179,9 +177,9 @@ module Query =
|
||||
else $"{it.Path PostgreSQL AsSql} {it.Comparison.OpSql} {param}")
|
||||
|> String.concat $" {howMatched} "
|
||||
|
||||
/// <summary>Create a <tt>WHERE</tt> clause fragment to implement an ID-based query</summary>
|
||||
/// <summary>Create a <c>WHERE</c> clause fragment to implement an ID-based query</summary>
|
||||
/// <param name="docId">The ID of the document</param>
|
||||
/// <returns>A <tt>WHERE</tt> clause fragment identifying a document by its ID</returns>
|
||||
/// <returns>A <c>WHERE</c> clause fragment identifying a document by its ID</returns>
|
||||
[<CompiledName "WhereById">]
|
||||
let whereById<'TKey> (docId: 'TKey) =
|
||||
whereByFields Any [ { Field.Equal (Configuration.idField ()) docId with ParameterName = Some "@id" } ]
|
||||
@@ -206,32 +204,28 @@ module Query =
|
||||
let tableName = name.Split '.' |> Array.last
|
||||
$"CREATE INDEX IF NOT EXISTS idx_{tableName}_document ON {name} USING GIN (data{extraOps})"
|
||||
|
||||
/// <summary>
|
||||
/// Create a <tt>WHERE</tt> clause fragment to implement a <tt>@></tt> (JSON contains) condition
|
||||
/// </summary>
|
||||
/// <summary>Create a <c>WHERE</c> clause fragment to implement a <c>@></c> (JSON contains) condition</summary>
|
||||
/// <param name="paramName">The parameter name for the query</param>
|
||||
/// <returns>A <tt>WHERE</tt> clause fragment for the contains condition</returns>
|
||||
/// <returns>A <c>WHERE</c> clause fragment for the contains condition</returns>
|
||||
[<CompiledName "WhereDataContains">]
|
||||
let whereDataContains paramName =
|
||||
$"data @> %s{paramName}"
|
||||
|
||||
/// <summary>
|
||||
/// Create a <tt>WHERE</tt> clause fragment to implement a <tt>@?</tt> (JSON Path match) condition
|
||||
/// </summary>
|
||||
/// <summary>Create a <c>WHERE</c> clause fragment to implement a <c>@?</c> (JSON Path match) condition</summary>
|
||||
/// <param name="paramName">The parameter name for the query</param>
|
||||
/// <returns>A <tt>WHERE</tt> clause fragment for the JSON Path match condition</returns>
|
||||
/// <returns>A <c>WHERE</c> clause fragment for the JSON Path match condition</returns>
|
||||
[<CompiledName "WhereJsonPathMatches">]
|
||||
let whereJsonPathMatches paramName =
|
||||
$"data @? %s{paramName}::jsonpath"
|
||||
|
||||
/// <summary>Create an <tt>UPDATE</tt> statement to patch documents</summary>
|
||||
/// <summary>Create an <c>UPDATE</c> statement to patch documents</summary>
|
||||
/// <param name="tableName">The table to be updated</param>
|
||||
/// <returns>A query to patch documents</returns>
|
||||
[<CompiledName "Patch">]
|
||||
let patch tableName =
|
||||
$"UPDATE %s{tableName} SET data = data || @data"
|
||||
|
||||
/// <summary>Create an <tt>UPDATE</tt> statement to remove fields from documents</summary>
|
||||
/// <summary>Create an <c>UPDATE</c> statement to remove fields from documents</summary>
|
||||
/// <param name="tableName">The table to be updated</param>
|
||||
/// <returns>A query to remove fields from documents</returns>
|
||||
[<CompiledName "RemoveFields">]
|
||||
@@ -270,6 +264,8 @@ module Query =
|
||||
Query.statementWhere statement (whereJsonPathMatches "@path")
|
||||
|
||||
|
||||
open System.Text
|
||||
|
||||
/// <summary>Functions for dealing with results</summary>
|
||||
[<AutoOpen>]
|
||||
module Results =
|
||||
@@ -289,16 +285,67 @@ module Results =
|
||||
let fromData<'T> row : 'T =
|
||||
fromDocument "data" row
|
||||
|
||||
/// <summary>Extract a count from the column <tt>it</tt></summary>
|
||||
/// <summary>Extract a count from the column <c>it</c></summary>
|
||||
/// <param name="row">A row reader set to the row with the count to retrieve</param>
|
||||
/// <returns>The count from the row</returns>
|
||||
[<CompiledName "ToCount">]
|
||||
let toCount (row: RowReader) =
|
||||
row.int "it"
|
||||
|
||||
/// <summary>Extract a true/false value from the column <tt>it</tt></summary>
|
||||
/// <summary>Extract a true/false value from the column <c>it</c></summary>
|
||||
/// <param name="row">A row reader set to the row with the true/false value to retrieve</param>
|
||||
/// <returns>The true/false value from the row</returns>
|
||||
[<CompiledName "ToExists">]
|
||||
let toExists (row: RowReader) =
|
||||
row.bool "it"
|
||||
|
||||
/// <summary>Extract a JSON document, specifying the field in which the document is found</summary>
|
||||
/// <param name="field">The field name containing the JSON document</param>
|
||||
/// <param name="row">A row reader set to the row with the document to be extracted</param>
|
||||
/// <returns>The JSON from the given field (an empty object if no field exists)</returns>
|
||||
[<CompiledName "JsonFromDocument">]
|
||||
let jsonFromDocument field (row: RowReader) =
|
||||
row.stringOrNone field |> Option.defaultValue "{}"
|
||||
|
||||
/// <summary>Extract a JSON document</summary>
|
||||
/// <param name="row">A row reader set to the row with the document to be extracted</param>
|
||||
/// <returns>The JSON from the row (an empty object if no field exists)</returns>
|
||||
[<CompiledName "JsonFromData">]
|
||||
let jsonFromData row =
|
||||
jsonFromDocument "data" row
|
||||
|
||||
/// <summary>Create a JSON array of items for the results of a query</summary>
|
||||
/// <param name="mapFunc">The mapping function to extract JSON from the query's results</param>
|
||||
/// <param name="sqlProps">The query from which JSON should be extracted</param>
|
||||
/// <returns>A JSON array as a string; no results will produce an empty array (<c>"[]"</c>)</returns>
|
||||
[<CompiledName "FSharpToJsonArray">]
|
||||
let toJsonArray (mapFunc: RowReader -> string) sqlProps = backgroundTask {
|
||||
let output = StringBuilder("[")
|
||||
do! sqlProps
|
||||
|> Sql.iterAsync (fun it ->
|
||||
if output.Length > 2 then ignore (output.Append ",")
|
||||
mapFunc it |> output.Append |> ignore)
|
||||
return output.Append("]").ToString()
|
||||
}
|
||||
|
||||
/// <summary>Create a JSON array of items for the results of a query</summary>
|
||||
/// <param name="mapFunc">The mapping function to extract JSON from the query's results</param>
|
||||
/// <param name="sqlProps">The query from which JSON should be extracted</param>
|
||||
/// <returns>A JSON array as a string; no results will produce an empty array (<c>"[]"</c>)</returns>
|
||||
let ToJsonArray(mapFunc: System.Func<RowReader, string>, sqlProps) =
|
||||
toJsonArray mapFunc.Invoke sqlProps
|
||||
|
||||
/// <summary>Write a JSON array of items for the results of a query to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="writer">The PipeWriter to which results should be written</param>
|
||||
/// <param name="mapFunc">The mapping function to extract JSON from the query's results</param>
|
||||
/// <param name="sqlProps">The query from which JSON should be extracted</param>
|
||||
[<CompiledName "FSharpWriteJsonArray">]
|
||||
let writeJsonArray writer (mapFunc: RowReader -> string) sqlProps =
|
||||
sqlProps |> Sql.toSeq mapFunc |> PipeWriter.writeStrings writer
|
||||
|
||||
/// <summary>Write a JSON array of items for the results of a query to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="writer">The PipeWriter to which results should be written</param>
|
||||
/// <param name="mapFunc">The mapping function to extract JSON from the query's results</param>
|
||||
/// <param name="sqlProps">The query from which JSON should be extracted</param>
|
||||
let WriteJsonArray(writer, mapFunc: System.Func<RowReader, string>, sqlProps) =
|
||||
writeJsonArray writer mapFunc.Invoke sqlProps
|
||||
|
||||
@@ -13,7 +13,7 @@ This package provides a lightweight document library backed by [PostgreSQL](http
|
||||
|
||||
## Upgrading from v3
|
||||
|
||||
There is a breaking API change for `ByField` (C#) / `byField` (F#), along with a compatibility namespace that can mitigate the impact of these changes. See [the migration guide](https://bitbadger.solutions/open-source/relational-documents/upgrade-from-v3-to-v4.html) for full details.
|
||||
There is a breaking API change for `ByField` (C#) / `byField` (F#), along with a compatibility namespace that can mitigate the impact of these changes. See [the migration guide](https://relationaldocs.bitbadger.solutions/dotnet/upgrade/v4.html) for full details.
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -71,7 +71,7 @@ var customer = await Find.ById<string, Customer>("customer", "123");
|
||||
// Find.byId type signature is string -> 'TKey -> Task<'TDoc option>
|
||||
let! customer = Find.byId<string, Customer> "customer" "123"
|
||||
```
|
||||
_(keys are treated as strings or numbers depending on their defintion; however, they are indexed as strings)_
|
||||
_(keys are treated as strings or numbers depending on their definition; however, they are indexed as strings)_
|
||||
|
||||
Count customers in Atlanta (using JSON containment):
|
||||
|
||||
@@ -103,4 +103,4 @@ do! Delete.byJsonPath "customer" """$.City ? (@ == "Chicago")"""
|
||||
|
||||
## More Information
|
||||
|
||||
The [project site](https://bitbadger.solutions/open-source/relational-documents/) has full details on how to use this library.
|
||||
The [project site](https://relationaldocs.bitbadger.solutions/dotnet/) has full details on how to use this library.
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,6 +8,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="Library.fs" />
|
||||
<Compile Include="WithConn.fs" />
|
||||
<Compile Include="Functions.fs" />
|
||||
<Compile Include="Extensions.fs" />
|
||||
<Compile Include="Compat.fs" />
|
||||
<None Include="README.md" Pack="true" PackagePath="\" />
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
namespace BitBadger.Documents.Sqlite
|
||||
|
||||
open Microsoft.Data.Sqlite
|
||||
open WithConn
|
||||
|
||||
/// <summary>F# extensions for the SqliteConnection type</summary>
|
||||
[<AutoOpen>]
|
||||
@@ -14,21 +15,45 @@ module Extensions =
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <returns>A list of results for the given query</returns>
|
||||
member conn.customList<'TDoc> query parameters mapFunc =
|
||||
WithConn.Custom.list<'TDoc> query parameters mapFunc conn
|
||||
Custom.list<'TDoc> query parameters mapFunc conn
|
||||
|
||||
/// <summary>Execute a query that returns a JSON array of results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>A JSON array of results for the given query</returns>
|
||||
member conn.customJsonArray query parameters mapFunc =
|
||||
Custom.jsonArray query parameters mapFunc conn
|
||||
|
||||
/// <summary>Execute a query, writing its results to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
member conn.writeCustomJsonArray query parameters writer mapFunc =
|
||||
Custom.writeJsonArray query parameters writer mapFunc conn
|
||||
|
||||
/// <summary>Execute a query that returns one or no results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <returns><tt>Some</tt> with the first matching result, or <tt>None</tt> if not found</returns>
|
||||
/// <returns><c>Some</c> with the first matching result, or <c>None</c> if not found</returns>
|
||||
member conn.customSingle<'TDoc> query parameters mapFunc =
|
||||
WithConn.Custom.single<'TDoc> query parameters mapFunc conn
|
||||
Custom.single<'TDoc> query parameters mapFunc conn
|
||||
|
||||
/// <summary>Execute a query that returns one or no JSON documents</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>The JSON document with the first matching result, or an empty document if not found</returns>
|
||||
member conn.customJsonSingle query parameters mapFunc =
|
||||
Custom.jsonSingle query parameters mapFunc conn
|
||||
|
||||
/// <summary>Execute a query that returns no results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
member conn.customNonQuery query parameters =
|
||||
WithConn.Custom.nonQuery query parameters conn
|
||||
Custom.nonQuery query parameters conn
|
||||
|
||||
/// <summary>Execute a query that returns a scalar value</summary>
|
||||
/// <param name="query">The query to retrieve the value</param>
|
||||
@@ -36,25 +61,25 @@ module Extensions =
|
||||
/// <param name="mapFunc">The mapping function to obtain the value</param>
|
||||
/// <returns>The scalar value for the query</returns>
|
||||
member conn.customScalar<'T when 'T: struct> query parameters mapFunc =
|
||||
WithConn.Custom.scalar<'T> query parameters mapFunc conn
|
||||
Custom.scalar<'T> query parameters mapFunc conn
|
||||
|
||||
/// <summary>Create a document table</summary>
|
||||
/// <param name="name">The table whose existence should be ensured (may include schema)</param>
|
||||
member conn.ensureTable name =
|
||||
WithConn.Definition.ensureTable name conn
|
||||
Definition.ensureTable name conn
|
||||
|
||||
/// <summary>Create an index on field(s) within documents in the specified table</summary>
|
||||
/// <param name="tableName">The table to be indexed (may include schema)</param>
|
||||
/// <param name="indexName">The name of the index to create</param>
|
||||
/// <param name="fields">One or more fields to be indexed</param>
|
||||
member conn.ensureFieldIndex tableName indexName fields =
|
||||
WithConn.Definition.ensureFieldIndex tableName indexName fields conn
|
||||
Definition.ensureFieldIndex tableName indexName fields conn
|
||||
|
||||
/// <summary>Insert a new document</summary>
|
||||
/// <param name="tableName">The table into which the document should be inserted (may include schema)</param>
|
||||
/// <param name="document">The document to be inserted</param>
|
||||
member conn.insert<'TDoc> tableName (document: 'TDoc) =
|
||||
WithConn.Document.insert<'TDoc> tableName document conn
|
||||
insert<'TDoc> tableName document conn
|
||||
|
||||
/// <summary>
|
||||
/// Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")
|
||||
@@ -62,68 +87,68 @@ module Extensions =
|
||||
/// <param name="tableName">The table into which the document should be saved (may include schema)</param>
|
||||
/// <param name="document">The document to be saved</param>
|
||||
member conn.save<'TDoc> tableName (document: 'TDoc) =
|
||||
WithConn.Document.save tableName document conn
|
||||
save tableName document conn
|
||||
|
||||
/// <summary>Count all documents in a table</summary>
|
||||
/// <param name="tableName">The table in which documents should be counted (may include schema)</param>
|
||||
/// <returns>The count of the documents in the table</returns>
|
||||
member conn.countAll tableName =
|
||||
WithConn.Count.all tableName conn
|
||||
Count.all tableName conn
|
||||
|
||||
/// <summary>Count matching documents using JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Count matching documents using JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which documents should be counted (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>The count of matching documents in the table</returns>
|
||||
member conn.countByFields tableName howMatched fields =
|
||||
WithConn.Count.byFields tableName howMatched fields conn
|
||||
Count.byFields tableName howMatched fields conn
|
||||
|
||||
/// <summary>Determine if a document exists for the given ID</summary>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document whose existence should be checked</param>
|
||||
/// <returns>True if a document exists, false if not</returns>
|
||||
member conn.existsById tableName (docId: 'TKey) =
|
||||
WithConn.Exists.byId tableName docId conn
|
||||
Exists.byId tableName docId conn
|
||||
|
||||
/// <summary>Determine if a document exists using JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Determine if a document exists using JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>True if any matching documents exist, false if not</returns>
|
||||
member conn.existsByFields tableName howMatched fields =
|
||||
WithConn.Exists.byFields tableName howMatched fields conn
|
||||
Exists.byFields tableName howMatched fields conn
|
||||
|
||||
/// <summary>Retrieve all documents in the given table</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <returns>All documents from the given table</returns>
|
||||
member conn.findAll<'TDoc> tableName =
|
||||
WithConn.Find.all<'TDoc> tableName conn
|
||||
Find.all<'TDoc> tableName conn
|
||||
|
||||
/// <summary>Retrieve all documents in the given table ordered by the given fields in the document</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All documents from the given table, ordered by the given fields</returns>
|
||||
member conn.findAllOrdered<'TDoc> tableName orderFields =
|
||||
WithConn.Find.allOrdered<'TDoc> tableName orderFields conn
|
||||
Find.allOrdered<'TDoc> tableName orderFields conn
|
||||
|
||||
/// <summary>Retrieve a document by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <returns><tt>Some</tt> with the document if found, <tt>None</tt> otherwise</returns>
|
||||
/// <returns><c>Some</c> with the document if found, <c>None</c> otherwise</returns>
|
||||
member conn.findById<'TKey, 'TDoc> tableName (docId: 'TKey) =
|
||||
WithConn.Find.byId<'TKey, 'TDoc> tableName docId conn
|
||||
Find.byId<'TKey, 'TDoc> tableName docId conn
|
||||
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>All documents matching the given fields</returns>
|
||||
member conn.findByFields<'TDoc> tableName howMatched fields =
|
||||
WithConn.Find.byFields<'TDoc> tableName howMatched fields conn
|
||||
Find.byFields<'TDoc> tableName howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching JSON field comparisons (<tt>->> =</tt>, etc.) ordered by the given fields
|
||||
/// in the document
|
||||
/// Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields in
|
||||
/// the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
@@ -131,18 +156,18 @@ module Extensions =
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All documents matching the given fields, ordered by the other given fields</returns>
|
||||
member conn.findByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields =
|
||||
WithConn.Find.byFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn
|
||||
Find.byFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns><tt>Some</tt> with the first document, or <tt>None</tt> if not found</returns>
|
||||
/// <returns><c>Some</c> with the first document, or <c>None</c> if not found</returns>
|
||||
member conn.findFirstByFields<'TDoc> tableName howMatched fields =
|
||||
WithConn.Find.firstByFields<'TDoc> tableName howMatched fields conn
|
||||
Find.firstByFields<'TDoc> tableName howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching JSON field comparisons (<tt>->> =</tt>, etc.) ordered by the
|
||||
/// Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the
|
||||
/// given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
@@ -150,17 +175,148 @@ module Extensions =
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>
|
||||
/// <tt>Some</tt> with the first document ordered by the given fields, or <tt>None</tt> if not found
|
||||
/// <c>Some</c> with the first document ordered by the given fields, or <c>None</c> if not found
|
||||
/// </returns>
|
||||
member conn.findFirstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields =
|
||||
WithConn.Find.firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn
|
||||
Find.firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>Retrieve all JSON documents in the given table</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <returns>All JSON documents from the given table</returns>
|
||||
member conn.jsonAll tableName =
|
||||
Json.all tableName conn
|
||||
|
||||
/// <summary>Retrieve all JSON documents in the given table ordered by the given fields in the document</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All JSON documents from the given table, ordered by the given fields</returns>
|
||||
member conn.jsonAllOrdered tableName orderFields =
|
||||
Json.allOrdered tableName orderFields conn
|
||||
|
||||
/// <summary>Retrieve a JSON document by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <returns>The JSON document if found, an empty JSON document otherwise</returns>
|
||||
member conn.jsonById<'TKey> tableName (docId: 'TKey) =
|
||||
Json.byId tableName docId conn
|
||||
|
||||
/// <summary>Retrieve JSON documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>All JSON documents matching the given fields</returns>
|
||||
member conn.jsonByFields tableName howMatched fields =
|
||||
Json.byFields tableName howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve JSON documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All JSON documents matching the given fields, ordered by the other given fields</returns>
|
||||
member conn.jsonByFieldsOrdered tableName howMatched queryFields orderFields =
|
||||
Json.byFieldsOrdered tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first JSON document matching JSON field comparisons (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>The first JSON document if found, an empty JSON document otherwise</returns>
|
||||
member conn.jsonFirstByFields tableName howMatched fields =
|
||||
Json.firstByFields tableName howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first JSON document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the
|
||||
/// given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>The first JSON document (in order) if found, an empty JSON document otherwise</returns>
|
||||
member conn.jsonFirstByFieldsOrdered tableName howMatched queryFields orderFields =
|
||||
Json.firstByFieldsOrdered tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>Write all JSON documents in the given table to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
member conn.writeJsonAll tableName writer =
|
||||
Json.writeAll tableName writer conn
|
||||
|
||||
/// <summary>
|
||||
/// Write all JSON all documents in the given table to the given <c>PipeWriter</c>, ordered by the given fields
|
||||
/// in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
member conn.writeJsonAllOrdered tableName writer orderFields =
|
||||
Json.writeAllOrdered tableName writer orderFields conn
|
||||
|
||||
/// <summary>Write a JSON document to the given <c>PipeWriter</c> by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
member conn.writeJsonById<'TKey> tableName writer (docId: 'TKey) =
|
||||
Json.writeById tableName writer docId conn
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching JSON field comparisons (<c>->> =</c>,
|
||||
/// etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
member conn.writeJsonByFields tableName writer howMatched fields =
|
||||
Json.writeByFields tableName writer howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching JSON field comparisons (<c>->> =</c>,
|
||||
/// etc.) ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
member conn.writeJsonByFieldsOrdered tableName writer howMatched queryFields orderFields =
|
||||
Json.writeByFieldsOrdered tableName writer howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching JSON field comparisons
|
||||
/// (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
member conn.writeJsonFirstByFields tableName writer howMatched fields =
|
||||
Json.writeFirstByFields tableName writer howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching JSON field comparisons
|
||||
/// (<c>->> =</c>, etc.) ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
member conn.writeJsonFirstByFieldsOrdered tableName writer howMatched queryFields orderFields =
|
||||
Json.writeFirstByFieldsOrdered tableName writer howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>Update (replace) an entire document by its ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be updated (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to be updated (replaced)</param>
|
||||
/// <param name="document">The new document</param>
|
||||
member conn.updateById tableName (docId: 'TKey) (document: 'TDoc) =
|
||||
WithConn.Update.byId tableName docId document conn
|
||||
Update.byId tableName docId document conn
|
||||
|
||||
/// <summary>
|
||||
/// Update (replace) an entire document by its ID, using the provided function to obtain the ID from the
|
||||
@@ -170,32 +326,31 @@ module Extensions =
|
||||
/// <param name="idFunc">The function to obtain the ID of the document</param>
|
||||
/// <param name="document">The new document</param>
|
||||
member conn.updateByFunc tableName (idFunc: 'TDoc -> 'TKey) (document: 'TDoc) =
|
||||
WithConn.Update.byFunc tableName idFunc document conn
|
||||
Update.byFunc tableName idFunc document conn
|
||||
|
||||
/// <summary>Patch a document by its ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be patched (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to patch</param>
|
||||
/// <param name="patch">The partial document to patch the existing document</param>
|
||||
member conn.patchById tableName (docId: 'TKey) (patch: 'TPatch) =
|
||||
WithConn.Patch.byId tableName docId patch conn
|
||||
Patch.byId tableName docId patch conn
|
||||
|
||||
/// <summary>
|
||||
/// Patch documents using a JSON field comparison query in the <tt>WHERE</tt> clause (<tt>->> =</tt>,
|
||||
/// etc.)
|
||||
/// Patch documents using a JSON field comparison query in the <c>WHERE</c> clause (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table in which documents should be patched (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="patch">The partial document to patch the existing document</param>
|
||||
member conn.patchByFields tableName howMatched fields (patch: 'TPatch) =
|
||||
WithConn.Patch.byFields tableName howMatched fields patch conn
|
||||
Patch.byFields tableName howMatched fields patch conn
|
||||
|
||||
/// <summary>Remove fields from a document by the document's ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be modified (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to modify</param>
|
||||
/// <param name="fieldNames">One or more field names to remove from the document</param>
|
||||
member conn.removeFieldsById tableName (docId: 'TKey) fieldNames =
|
||||
WithConn.RemoveFields.byId tableName docId fieldNames conn
|
||||
RemoveFields.byId tableName docId fieldNames conn
|
||||
|
||||
/// <summary>Remove fields from documents via a comparison on JSON fields in the document</summary>
|
||||
/// <param name="tableName">The table in which documents should be modified (may include schema)</param>
|
||||
@@ -203,20 +358,20 @@ module Extensions =
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="fieldNames">One or more field names to remove from the matching documents</param>
|
||||
member conn.removeFieldsByFields tableName howMatched fields fieldNames =
|
||||
WithConn.RemoveFields.byFields tableName howMatched fields fieldNames conn
|
||||
RemoveFields.byFields tableName howMatched fields fieldNames conn
|
||||
|
||||
/// <summary>Delete a document by its ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be deleted (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to delete</param>
|
||||
member conn.deleteById tableName (docId: 'TKey) =
|
||||
WithConn.Delete.byId tableName docId conn
|
||||
Delete.byId tableName docId conn
|
||||
|
||||
/// <summary>Delete documents by matching a JSON field comparison query (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <summary>Delete documents by matching a JSON field comparison query (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which documents should be deleted (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
member conn.deleteByFields tableName howMatched fields =
|
||||
WithConn.Delete.byFields tableName howMatched fields conn
|
||||
Delete.byFields tableName howMatched fields conn
|
||||
|
||||
|
||||
open System.Runtime.CompilerServices
|
||||
@@ -225,36 +380,66 @@ open System.Runtime.CompilerServices
|
||||
type SqliteConnectionCSharpExtensions =
|
||||
|
||||
/// <summary>Execute a query that returns a list of results</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <returns>A list of results for the given query</returns>
|
||||
[<Extension>]
|
||||
static member inline CustomList<'TDoc>(conn, query, parameters, mapFunc: System.Func<SqliteDataReader, 'TDoc>) =
|
||||
WithConn.Custom.List<'TDoc>(query, parameters, mapFunc, conn)
|
||||
Custom.List<'TDoc>(query, parameters, mapFunc, conn)
|
||||
|
||||
/// <summary>Execute a query that returns a JSON array of results</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>A JSON array of results for the given query</returns>
|
||||
[<Extension>]
|
||||
static member inline CustomJsonArray(conn, query, parameters, mapFunc) =
|
||||
Custom.JsonArray(query, parameters, mapFunc, conn)
|
||||
|
||||
/// <summary>Execute a query, writing its results to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
[<Extension>]
|
||||
static member inline WriteCustomJsonArray(conn, query, parameters, writer, mapFunc) =
|
||||
Custom.WriteJsonArray(query, parameters, writer, mapFunc, conn)
|
||||
|
||||
/// <summary>Execute a query that returns one or no results</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <returns>The first matching result, or <tt>null</tt> if not found</returns>
|
||||
/// <returns>The first matching result, or <c>null</c> if not found</returns>
|
||||
[<Extension>]
|
||||
static member inline CustomSingle<'TDoc when 'TDoc: null and 'TDoc: not struct>(
|
||||
conn, query, parameters, mapFunc: System.Func<SqliteDataReader, 'TDoc>) =
|
||||
WithConn.Custom.Single<'TDoc>(query, parameters, mapFunc, conn)
|
||||
Custom.Single<'TDoc>(query, parameters, mapFunc, conn)
|
||||
|
||||
/// <summary>Execute a query that returns one or no JSON documents</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>The JSON document with the first matching result, or an empty document if not found</returns>
|
||||
[<Extension>]
|
||||
static member inline CustomJsonSingle(conn, query, parameters, mapFunc) =
|
||||
Custom.JsonSingle(query, parameters, mapFunc, conn)
|
||||
|
||||
/// <summary>Execute a query that returns no results</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
[<Extension>]
|
||||
static member inline CustomNonQuery(conn, query, parameters) =
|
||||
WithConn.Custom.nonQuery query parameters conn
|
||||
Custom.nonQuery query parameters conn
|
||||
|
||||
/// <summary>Execute a query that returns a scalar value</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="query">The query to retrieve the value</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to obtain the value</param>
|
||||
@@ -262,118 +447,118 @@ type SqliteConnectionCSharpExtensions =
|
||||
[<Extension>]
|
||||
static member inline CustomScalar<'T when 'T: struct>(
|
||||
conn, query, parameters, mapFunc: System.Func<SqliteDataReader, 'T>) =
|
||||
WithConn.Custom.Scalar<'T>(query, parameters, mapFunc, conn)
|
||||
Custom.Scalar<'T>(query, parameters, mapFunc, conn)
|
||||
|
||||
/// <summary>Create a document table</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="name">The table whose existence should be ensured (may include schema)</param>
|
||||
[<Extension>]
|
||||
static member inline EnsureTable(conn, name) =
|
||||
WithConn.Definition.ensureTable name conn
|
||||
Definition.ensureTable name conn
|
||||
|
||||
/// <summary>Create an index on field(s) within documents in the specified table</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table to be indexed (may include schema)</param>
|
||||
/// <param name="indexName">The name of the index to create</param>
|
||||
/// <param name="fields">One or more fields to be indexed</param>
|
||||
[<Extension>]
|
||||
static member inline EnsureFieldIndex(conn, tableName, indexName, fields) =
|
||||
WithConn.Definition.ensureFieldIndex tableName indexName fields conn
|
||||
Definition.ensureFieldIndex tableName indexName fields conn
|
||||
|
||||
/// <summary>Insert a new document</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table into which the document should be inserted (may include schema)</param>
|
||||
/// <param name="document">The document to be inserted</param>
|
||||
[<Extension>]
|
||||
static member inline Insert<'TDoc>(conn, tableName, document: 'TDoc) =
|
||||
WithConn.Document.insert<'TDoc> tableName document conn
|
||||
insert<'TDoc> tableName document conn
|
||||
|
||||
/// <summary>Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table into which the document should be saved (may include schema)</param>
|
||||
/// <param name="document">The document to be saved</param>
|
||||
[<Extension>]
|
||||
static member inline Save<'TDoc>(conn, tableName, document: 'TDoc) =
|
||||
WithConn.Document.save<'TDoc> tableName document conn
|
||||
save<'TDoc> tableName document conn
|
||||
|
||||
/// <summary>Count all documents in a table</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which documents should be counted (may include schema)</param>
|
||||
/// <returns>The count of the documents in the table</returns>
|
||||
[<Extension>]
|
||||
static member inline CountAll(conn, tableName) =
|
||||
WithConn.Count.all tableName conn
|
||||
Count.all tableName conn
|
||||
|
||||
/// <summary>Count matching documents using JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <summary>Count matching documents using JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which documents should be counted (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>The count of matching documents in the table</returns>
|
||||
[<Extension>]
|
||||
static member inline CountByFields(conn, tableName, howMatched, fields) =
|
||||
WithConn.Count.byFields tableName howMatched fields conn
|
||||
Count.byFields tableName howMatched fields conn
|
||||
|
||||
/// <summary>Determine if a document exists for the given ID</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document whose existence should be checked</param>
|
||||
/// <returns>True if a document exists, false if not</returns>
|
||||
[<Extension>]
|
||||
static member inline ExistsById<'TKey>(conn, tableName, docId: 'TKey) =
|
||||
WithConn.Exists.byId tableName docId conn
|
||||
Exists.byId tableName docId conn
|
||||
|
||||
/// <summary>Determine if a document exists using JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <summary>Determine if a document exists using JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>True if any matching documents exist, false if not</returns>
|
||||
[<Extension>]
|
||||
static member inline ExistsByFields(conn, tableName, howMatched, fields) =
|
||||
WithConn.Exists.byFields tableName howMatched fields conn
|
||||
Exists.byFields tableName howMatched fields conn
|
||||
|
||||
/// <summary>Retrieve all documents in the given table</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <returns>All documents from the given table</returns>
|
||||
[<Extension>]
|
||||
static member inline FindAll<'TDoc>(conn, tableName) =
|
||||
WithConn.Find.All<'TDoc>(tableName, conn)
|
||||
Find.All<'TDoc>(tableName, conn)
|
||||
|
||||
/// <summary>Retrieve all documents in the given table ordered by the given fields in the document</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All documents from the given table, ordered by the given fields</returns>
|
||||
[<Extension>]
|
||||
static member inline FindAllOrdered<'TDoc>(conn, tableName, orderFields) =
|
||||
WithConn.Find.AllOrdered<'TDoc>(tableName, orderFields, conn)
|
||||
Find.AllOrdered<'TDoc>(tableName, orderFields, conn)
|
||||
|
||||
/// <summary>Retrieve a document by its ID</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <returns>The document if found, <tt>null</tt> otherwise</returns>
|
||||
/// <returns>The document if found, <c>null</c> otherwise</returns>
|
||||
[<Extension>]
|
||||
static member inline FindById<'TKey, 'TDoc when 'TDoc: null and 'TDoc: not struct>(conn, tableName, docId: 'TKey) =
|
||||
WithConn.Find.ById<'TKey, 'TDoc>(tableName, docId, conn)
|
||||
Find.ById<'TKey, 'TDoc>(tableName, docId, conn)
|
||||
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>All documents matching the given fields</returns>
|
||||
[<Extension>]
|
||||
static member inline FindByFields<'TDoc>(conn, tableName, howMatched, fields) =
|
||||
WithConn.Find.ByFields<'TDoc>(tableName, howMatched, fields, conn)
|
||||
Find.ByFields<'TDoc>(tableName, howMatched, fields, conn)
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching JSON field comparisons (<tt>->> =</tt>, etc.) ordered by the given fields in
|
||||
/// Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields in
|
||||
/// the document
|
||||
/// </summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
@@ -381,108 +566,264 @@ type SqliteConnectionCSharpExtensions =
|
||||
/// <returns>All documents matching the given fields, ordered by the other given fields</returns>
|
||||
[<Extension>]
|
||||
static member inline FindByFieldsOrdered<'TDoc>(conn, tableName, howMatched, queryFields, orderFields) =
|
||||
WithConn.Find.ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, conn)
|
||||
Find.ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, conn)
|
||||
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>The first document, or <tt>null</tt> if not found</returns>
|
||||
/// <returns>The first document, or <c>null</c> if not found</returns>
|
||||
[<Extension>]
|
||||
static member inline FindFirstByFields<'TDoc when 'TDoc: null and 'TDoc: not struct>(
|
||||
conn, tableName, howMatched, fields) =
|
||||
WithConn.Find.FirstByFields<'TDoc>(tableName, howMatched, fields, conn)
|
||||
Find.FirstByFields<'TDoc>(tableName, howMatched, fields, conn)
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching JSON field comparisons (<tt>->> =</tt>, etc.) ordered by the given
|
||||
/// Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>The first document ordered by the given fields, or <tt>null</tt> if not found</returns>
|
||||
/// <returns>The first document ordered by the given fields, or <c>null</c> if not found</returns>
|
||||
[<Extension>]
|
||||
static member inline FindFirstByFieldsOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>(
|
||||
conn, tableName, howMatched, queryFields, orderFields) =
|
||||
WithConn.Find.FirstByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, conn)
|
||||
Find.FirstByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, conn)
|
||||
|
||||
/// <summary>Retrieve all JSON documents in the given table</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <returns>All JSON documents from the given table</returns>
|
||||
[<Extension>]
|
||||
static member inline JsonAll(conn, tableName) =
|
||||
Json.all tableName conn
|
||||
|
||||
/// <summary>Retrieve all JSON documents in the given table ordered by the given fields in the document</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All JSON documents from the given table, ordered by the given fields</returns>
|
||||
[<Extension>]
|
||||
static member inline JsonAllOrdered(conn, tableName, orderFields) =
|
||||
Json.allOrdered tableName orderFields conn
|
||||
|
||||
/// <summary>Retrieve a JSON document by its ID</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <returns>The JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<Extension>]
|
||||
static member inline JsonById<'TKey>(conn, tableName, docId: 'TKey) =
|
||||
Json.byId tableName docId conn
|
||||
|
||||
/// <summary>Retrieve JSON documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>All JSON documents matching the given fields</returns>
|
||||
[<Extension>]
|
||||
static member inline JsonByFields(conn, tableName, howMatched, fields) =
|
||||
Json.byFields tableName howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve JSON documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields
|
||||
/// in the document
|
||||
/// </summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All JSON documents matching the given fields, ordered by the other given fields</returns>
|
||||
[<Extension>]
|
||||
static member inline JsonByFieldsOrdered(conn, tableName, howMatched, queryFields, orderFields) =
|
||||
Json.byFieldsOrdered tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>Retrieve the first JSON document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>The first JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<Extension>]
|
||||
static member inline JsonFirstByFields(conn, tableName, howMatched, fields) =
|
||||
Json.firstByFields tableName howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first JSON document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>The first JSON document (in order) if found, an empty JSON document otherwise</returns>
|
||||
[<Extension>]
|
||||
static member inline JsonFirstByFieldsOrdered(conn, tableName, howMatched, queryFields, orderFields) =
|
||||
Json.firstByFieldsOrdered tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>Write all JSON documents in the given table to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
[<Extension>]
|
||||
static member inline WriteJsonAll(conn, tableName, writer) =
|
||||
Json.writeAll tableName writer conn
|
||||
|
||||
/// <summary>
|
||||
/// Write all JSON all documents in the given table to the given <c>PipeWriter</c>, ordered by the given fields in
|
||||
/// the document
|
||||
/// </summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<Extension>]
|
||||
static member inline WriteJsonAllOrdered(conn, tableName, writer, orderFields) =
|
||||
Json.writeAllOrdered tableName writer orderFields conn
|
||||
|
||||
/// <summary>Write a JSON document to the given <c>PipeWriter</c> by its ID</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
[<Extension>]
|
||||
static member inline WriteJsonById<'TKey>(conn, tableName, writer, docId: 'TKey) =
|
||||
Json.writeById tableName writer docId conn
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching JSON field comparisons (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
[<Extension>]
|
||||
static member inline WriteJsonByFields(conn, tableName, writer, howMatched, fields) =
|
||||
Json.writeByFields tableName writer howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching JSON field comparisons (<c>->> =</c>, etc.)
|
||||
/// ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<Extension>]
|
||||
static member inline WriteJsonByFieldsOrdered(conn, tableName, writer, howMatched, queryFields, orderFields) =
|
||||
Json.writeByFieldsOrdered tableName writer howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching JSON field comparisons
|
||||
/// (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
[<Extension>]
|
||||
static member inline WriteJsonFirstByFields(conn, tableName, writer, howMatched, fields) =
|
||||
Json.writeFirstByFields tableName writer howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching JSON field comparisons
|
||||
/// (<c>->> =</c>, etc.) ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<Extension>]
|
||||
static member inline WriteJsonFirstByFieldsOrdered(conn, tableName, writer, howMatched, queryFields, orderFields) =
|
||||
Json.writeFirstByFieldsOrdered tableName writer howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>Update (replace) an entire document by its ID</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which a document should be updated (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to be updated (replaced)</param>
|
||||
/// <param name="document">The new document</param>
|
||||
[<Extension>]
|
||||
static member inline UpdateById<'TKey, 'TDoc>(conn, tableName, docId: 'TKey, document: 'TDoc) =
|
||||
WithConn.Update.byId tableName docId document conn
|
||||
Update.byId tableName docId document conn
|
||||
|
||||
/// <summary>
|
||||
/// Update (replace) an entire document by its ID, using the provided function to obtain the ID from the document
|
||||
/// </summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which a document should be updated (may include schema)</param>
|
||||
/// <param name="idFunc">The function to obtain the ID of the document</param>
|
||||
/// <param name="document">The new document</param>
|
||||
[<Extension>]
|
||||
static member inline UpdateByFunc<'TKey, 'TDoc>(
|
||||
conn, tableName, idFunc: System.Func<'TDoc, 'TKey>, document: 'TDoc) =
|
||||
WithConn.Update.ByFunc(tableName, idFunc, document, conn)
|
||||
Update.ByFunc(tableName, idFunc, document, conn)
|
||||
|
||||
/// <summary>Patch a document by its ID</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which a document should be patched (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to patch</param>
|
||||
/// <param name="patch">The partial document to patch the existing document</param>
|
||||
[<Extension>]
|
||||
static member inline PatchById<'TKey, 'TPatch>(conn, tableName, docId: 'TKey, patch: 'TPatch) =
|
||||
WithConn.Patch.byId tableName docId patch conn
|
||||
Patch.byId tableName docId patch conn
|
||||
|
||||
/// <summary>
|
||||
/// Patch documents using a JSON field comparison query in the <tt>WHERE</tt> clause (<tt>->> =</tt>, etc.)
|
||||
/// Patch documents using a JSON field comparison query in the <c>WHERE</c> clause (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which documents should be patched (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="patch">The partial document to patch the existing document</param>
|
||||
[<Extension>]
|
||||
static member inline PatchByFields<'TPatch>(conn, tableName, howMatched, fields, patch: 'TPatch) =
|
||||
WithConn.Patch.byFields tableName howMatched fields patch conn
|
||||
Patch.byFields tableName howMatched fields patch conn
|
||||
|
||||
/// <summary>Remove fields from a document by the document's ID</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which a document should be modified (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to modify</param>
|
||||
/// <param name="fieldNames">One or more field names to remove from the document</param>
|
||||
[<Extension>]
|
||||
static member inline RemoveFieldsById<'TKey>(conn, tableName, docId: 'TKey, fieldNames) =
|
||||
WithConn.RemoveFields.byId tableName docId fieldNames conn
|
||||
RemoveFields.byId tableName docId fieldNames conn
|
||||
|
||||
/// <summary>Remove fields from documents via a comparison on JSON fields in the document</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which documents should be modified (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="fieldNames">One or more field names to remove from the matching documents</param>
|
||||
[<Extension>]
|
||||
static member inline RemoveFieldsByFields(conn, tableName, howMatched, fields, fieldNames) =
|
||||
WithConn.RemoveFields.byFields tableName howMatched fields fieldNames conn
|
||||
RemoveFields.byFields tableName howMatched fields fieldNames conn
|
||||
|
||||
/// <summary>Delete a document by its ID</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which a document should be deleted (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to delete</param>
|
||||
[<Extension>]
|
||||
static member inline DeleteById<'TKey>(conn, tableName, docId: 'TKey) =
|
||||
WithConn.Delete.byId tableName docId conn
|
||||
Delete.byId tableName docId conn
|
||||
|
||||
/// <summary>Delete documents by matching a JSON field comparison query (<tt>->> =</tt>, etc.)</summary>
|
||||
/// <param name="conn">The <tt>SqliteConnection</tt> on which to run the query</param>
|
||||
/// <summary>Delete documents by matching a JSON field comparison query (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> on which to run the query</param>
|
||||
/// <param name="tableName">The table in which documents should be deleted (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
[<Extension>]
|
||||
static member inline DeleteByFields(conn, tableName, howMatched, fields) =
|
||||
WithConn.Delete.byFields tableName howMatched fields conn
|
||||
Delete.byFields tableName howMatched fields conn
|
||||
|
||||
636
src/Sqlite/Functions.fs
Normal file
636
src/Sqlite/Functions.fs
Normal file
@@ -0,0 +1,636 @@
|
||||
namespace BitBadger.Documents.Sqlite
|
||||
|
||||
open Microsoft.Data.Sqlite
|
||||
|
||||
/// <summary>Commands to execute custom SQL queries</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Custom =
|
||||
|
||||
/// <summary>Execute a query that returns a list of results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <returns>A list of results for the given query</returns>
|
||||
[<CompiledName "FSharpList">]
|
||||
let list<'TDoc> query parameters (mapFunc: SqliteDataReader -> 'TDoc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.list<'TDoc> query parameters mapFunc conn
|
||||
|
||||
/// <summary>Execute a query that returns a list of results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <returns>A list of results for the given query</returns>
|
||||
let List<'TDoc>(query, parameters, mapFunc: System.Func<SqliteDataReader, 'TDoc>) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.List<'TDoc>(query, parameters, mapFunc, conn)
|
||||
|
||||
/// <summary>Execute a query that returns a JSON array of results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>A JSON array of results for the given query</returns>
|
||||
[<CompiledName "FSharpJsonArray">]
|
||||
let jsonArray query parameters mapFunc =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.jsonArray query parameters mapFunc conn
|
||||
|
||||
/// <summary>Execute a query that returns a JSON array of results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>A JSON array of results for the given query</returns>
|
||||
let JsonArray(query, parameters, mapFunc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.JsonArray(query, parameters, mapFunc, conn)
|
||||
|
||||
/// <summary>Execute a query, writing its results to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
[<CompiledName "FSharpWriteJsonArray">]
|
||||
let writeJsonArray query parameters writer mapFunc =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.writeJsonArray query parameters writer mapFunc conn
|
||||
|
||||
/// <summary>Execute a query, writing its results to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
let WriteJsonArray(query, parameters, writer, mapFunc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.WriteJsonArray(query, parameters, writer, mapFunc, conn)
|
||||
|
||||
/// <summary>Execute a query that returns one or no results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <returns><c>Some</c> with the first matching result, or <c>None</c> if not found</returns>
|
||||
[<CompiledName "FSharpSingle">]
|
||||
let single<'TDoc> query parameters (mapFunc: SqliteDataReader -> 'TDoc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.single<'TDoc> query parameters mapFunc conn
|
||||
|
||||
/// <summary>Execute a query that returns one or no results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <returns>The first matching result, or <c>null</c> if not found</returns>
|
||||
let Single<'TDoc when 'TDoc: null and 'TDoc: not struct>(
|
||||
query, parameters, mapFunc: System.Func<SqliteDataReader, 'TDoc>) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.Single<'TDoc>(query, parameters, mapFunc, conn)
|
||||
|
||||
/// <summary>Execute a query that returns one or no JSON documents</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>The JSON document with the first matching result, or an empty document if not found</returns>
|
||||
[<CompiledName "FSharpJsonSingle">]
|
||||
let jsonSingle query parameters mapFunc =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.jsonSingle query parameters mapFunc conn
|
||||
|
||||
/// <summary>Execute a query that returns one or no JSON documents</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <returns>The JSON document with the first matching result, or an empty document if not found</returns>
|
||||
let JsonSingle(query, parameters, mapFunc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.JsonSingle(query, parameters, mapFunc, conn)
|
||||
|
||||
/// <summary>Execute a query that returns no results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
[<CompiledName "NonQuery">]
|
||||
let nonQuery query parameters =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.nonQuery query parameters conn
|
||||
|
||||
/// <summary>Execute a query that returns a scalar value</summary>
|
||||
/// <param name="query">The query to retrieve the value</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to obtain the value</param>
|
||||
/// <returns>The scalar value for the query</returns>
|
||||
[<CompiledName "FSharpScalar">]
|
||||
let scalar<'T when 'T: struct> query parameters (mapFunc: SqliteDataReader -> 'T) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.scalar<'T> query parameters mapFunc conn
|
||||
|
||||
/// <summary>Execute a query that returns a scalar value</summary>
|
||||
/// <param name="query">The query to retrieve the value</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to obtain the value</param>
|
||||
/// <returns>The scalar value for the query</returns>
|
||||
let Scalar<'T when 'T: struct>(query, parameters, mapFunc: System.Func<SqliteDataReader, 'T>) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Custom.Scalar<'T>(query, parameters, mapFunc, conn)
|
||||
|
||||
|
||||
/// <summary>Functions to create tables and indexes</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Definition =
|
||||
|
||||
/// <summary>Create a document table</summary>
|
||||
/// <param name="name">The table whose existence should be ensured (may include schema)</param>
|
||||
[<CompiledName "EnsureTable">]
|
||||
let ensureTable name =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Definition.ensureTable name conn
|
||||
|
||||
/// <summary>Create an index on field(s) within documents in the specified table</summary>
|
||||
/// <param name="tableName">The table to be indexed (may include schema)</param>
|
||||
/// <param name="indexName">The name of the index to create</param>
|
||||
/// <param name="fields">One or more fields to be indexed</param>
|
||||
[<CompiledName "EnsureFieldIndex">]
|
||||
let ensureFieldIndex tableName indexName fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Definition.ensureFieldIndex tableName indexName fields conn
|
||||
|
||||
|
||||
/// <summary>Document insert/save functions</summary>
|
||||
[<AutoOpen>]
|
||||
module Document =
|
||||
|
||||
/// <summary>Insert a new document</summary>
|
||||
/// <param name="tableName">The table into which the document should be inserted (may include schema)</param>
|
||||
/// <param name="document">The document to be inserted</param>
|
||||
[<CompiledName "Insert">]
|
||||
let insert<'TDoc> tableName (document: 'TDoc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Document.insert tableName document conn
|
||||
|
||||
/// <summary>Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")</summary>
|
||||
/// <param name="tableName">The table into which the document should be saved (may include schema)</param>
|
||||
/// <param name="document">The document to be saved</param>
|
||||
[<CompiledName "Save">]
|
||||
let save<'TDoc> tableName (document: 'TDoc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Document.save tableName document conn
|
||||
|
||||
|
||||
/// <summary>Commands to count documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Count =
|
||||
|
||||
/// <summary>Count all documents in a table</summary>
|
||||
/// <param name="tableName">The table in which documents should be counted (may include schema)</param>
|
||||
/// <returns>The count of the documents in the table</returns>
|
||||
[<CompiledName "All">]
|
||||
let all tableName =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Count.all tableName conn
|
||||
|
||||
/// <summary>Count matching documents using JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which documents should be counted (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>The count of matching documents in the table</returns>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Count.byFields tableName howMatched fields conn
|
||||
|
||||
|
||||
/// <summary>Commands to determine if documents exist</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Exists =
|
||||
|
||||
/// <summary>Determine if a document exists for the given ID</summary>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document whose existence should be checked</param>
|
||||
/// <returns>True if a document exists, false if not</returns>
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Exists.byId tableName docId conn
|
||||
|
||||
/// <summary>Determine if a document exists using JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>True if any matching documents exist, false if not</returns>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Exists.byFields tableName howMatched fields conn
|
||||
|
||||
|
||||
/// <summary>Commands to retrieve documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Find =
|
||||
|
||||
/// <summary>Retrieve all documents in the given table</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <returns>All documents from the given table</returns>
|
||||
[<CompiledName "FSharpAll">]
|
||||
let all<'TDoc> tableName =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.all<'TDoc> tableName conn
|
||||
|
||||
/// <summary>Retrieve all documents in the given table</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <returns>All documents from the given table</returns>
|
||||
let All<'TDoc> tableName =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.All<'TDoc>(tableName, conn)
|
||||
|
||||
/// <summary>Retrieve all documents in the given table ordered by the given fields in the document</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All documents from the given table, ordered by the given fields</returns>
|
||||
[<CompiledName "FSharpAllOrdered">]
|
||||
let allOrdered<'TDoc> tableName orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.allOrdered<'TDoc> tableName orderFields conn
|
||||
|
||||
/// <summary>Retrieve all documents in the given table ordered by the given fields in the document</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All documents from the given table, ordered by the given fields</returns>
|
||||
let AllOrdered<'TDoc> tableName orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.AllOrdered<'TDoc>(tableName, orderFields, conn)
|
||||
|
||||
/// <summary>Retrieve a document by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <returns><c>Some</c> with the document if found, <c>None</c> otherwise</returns>
|
||||
[<CompiledName "FSharpById">]
|
||||
let byId<'TKey, 'TDoc> tableName docId =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.byId<'TKey, 'TDoc> tableName docId conn
|
||||
|
||||
/// <summary>Retrieve a document by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <returns>The document if found, <c>null</c> otherwise</returns>
|
||||
let ById<'TKey, 'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, docId) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.ById<'TKey, 'TDoc>(tableName, docId, conn)
|
||||
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>All documents matching the given fields</returns>
|
||||
[<CompiledName "FSharpByFields">]
|
||||
let byFields<'TDoc> tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.byFields<'TDoc> tableName howMatched fields conn
|
||||
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>All documents matching the given fields</returns>
|
||||
let ByFields<'TDoc>(tableName, howMatched, fields) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.ByFields<'TDoc>(tableName, howMatched, fields, conn)
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All documents matching the given fields, ordered by the other given fields</returns>
|
||||
[<CompiledName "FSharpByFieldsOrdered">]
|
||||
let byFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.byFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All documents matching the given fields, ordered by the other given fields</returns>
|
||||
let ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.ByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, conn)
|
||||
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns><c>Some</c> with the first document, or <c>None</c> if not found</returns>
|
||||
[<CompiledName "FSharpFirstByFields">]
|
||||
let firstByFields<'TDoc> tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.firstByFields<'TDoc> tableName howMatched fields conn
|
||||
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>The first document, or <c>null</c> if not found</returns>
|
||||
let FirstByFields<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, howMatched, fields) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.FirstByFields<'TDoc>(tableName, howMatched, fields, conn)
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>
|
||||
/// <c>Some</c> with the first document ordered by the given fields, or <c>None</c> if not found
|
||||
/// </returns>
|
||||
[<CompiledName "FSharpFirstByFieldsOrdered">]
|
||||
let firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.firstByFieldsOrdered<'TDoc> tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>The first document ordered by the given fields, or <c>null</c> if not found</returns>
|
||||
let FirstByFieldsOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>(
|
||||
tableName, howMatched, queryFields, orderFields) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Find.FirstByFieldsOrdered<'TDoc>(tableName, howMatched, queryFields, orderFields, conn)
|
||||
|
||||
|
||||
/// <summary>Commands to retrieve documents as raw JSON</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Json =
|
||||
|
||||
/// <summary>Retrieve all JSON documents in the given table</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <returns>All JSON documents from the given table</returns>
|
||||
[<CompiledName "All">]
|
||||
let all tableName =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.all tableName conn
|
||||
|
||||
/// <summary>Retrieve all JSON documents in the given table ordered by the given fields in the document</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All JSON documents from the given table, ordered by the given fields</returns>
|
||||
[<CompiledName "AllOrdered">]
|
||||
let allOrdered tableName orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.allOrdered tableName orderFields conn
|
||||
|
||||
/// <summary>Retrieve a JSON document by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <returns>The JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "ById">]
|
||||
let byId<'TKey> tableName (docId: 'TKey) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.byId tableName docId conn
|
||||
|
||||
/// <summary>Retrieve JSON documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>All JSON documents matching the given fields</returns>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.byFields tableName howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve JSON documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields
|
||||
/// in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>All JSON documents matching the given fields, ordered by the other given fields</returns>
|
||||
[<CompiledName "ByFieldsOrdered">]
|
||||
let byFieldsOrdered tableName howMatched queryFields orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.byFieldsOrdered tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>Retrieve the first JSON document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <returns>The first JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "FirstByFields">]
|
||||
let firstByFields tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.firstByFields tableName howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first JSON document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <returns>The first JSON document (in order) if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "FirstByFieldsOrdered">]
|
||||
let firstByFieldsOrdered tableName howMatched queryFields orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.firstByFieldsOrdered tableName howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>Write all JSON documents in the given table to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
[<CompiledName "WriteAll">]
|
||||
let writeAll tableName writer =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.writeAll tableName writer conn
|
||||
|
||||
/// <summary>
|
||||
/// Write all JSON all documents in the given table to the given <c>PipeWriter</c>, ordered by the given fields in
|
||||
/// the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<CompiledName "WriteAllOrdered">]
|
||||
let writeAllOrdered tableName writer orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.writeAllOrdered tableName writer orderFields conn
|
||||
|
||||
/// <summary>Write a JSON document to the given <c>PipeWriter</c> by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
[<CompiledName "WriteById">]
|
||||
let writeById<'TKey> tableName writer (docId: 'TKey) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.writeById tableName writer docId conn
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching JSON field comparisons (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
[<CompiledName "WriteByFields">]
|
||||
let writeByFields tableName writer howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.writeByFields tableName writer howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching JSON field comparisons (<c>->> =</c>, etc.)
|
||||
/// ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<CompiledName "WriteByFieldsOrdered">]
|
||||
let writeByFieldsOrdered tableName writer howMatched queryFields orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.writeByFieldsOrdered tableName writer howMatched queryFields orderFields conn
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching JSON field comparisons
|
||||
/// (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
[<CompiledName "WriteFirstByFields">]
|
||||
let writeFirstByFields tableName writer howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.writeFirstByFields tableName writer howMatched fields conn
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching JSON field comparisons
|
||||
/// (<c>->> =</c>, etc.) ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
[<CompiledName "WriteFirstByFieldsOrdered">]
|
||||
let writeFirstByFieldsOrdered tableName writer howMatched queryFields orderFields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Json.writeFirstByFieldsOrdered tableName writer howMatched queryFields orderFields conn
|
||||
|
||||
|
||||
/// <summary>Commands to update documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Update =
|
||||
|
||||
/// <summary>Update (replace) an entire document by its ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be updated (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to be updated (replaced)</param>
|
||||
/// <param name="document">The new document</param>
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) (document: 'TDoc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Update.byId tableName docId document conn
|
||||
|
||||
/// <summary>
|
||||
/// Update (replace) an entire document by its ID, using the provided function to obtain the ID from the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table in which a document should be updated (may include schema)</param>
|
||||
/// <param name="idFunc">The function to obtain the ID of the document</param>
|
||||
/// <param name="document">The new document</param>
|
||||
[<CompiledName "FSharpByFunc">]
|
||||
let byFunc tableName (idFunc: 'TDoc -> 'TKey) (document: 'TDoc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Update.byFunc tableName idFunc document conn
|
||||
|
||||
/// <summary>
|
||||
/// Update (replace) an entire document by its ID, using the provided function to obtain the ID from the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table in which a document should be updated (may include schema)</param>
|
||||
/// <param name="idFunc">The function to obtain the ID of the document</param>
|
||||
/// <param name="document">The new document</param>
|
||||
let ByFunc(tableName, idFunc: System.Func<'TDoc, 'TKey>, document: 'TDoc) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Update.ByFunc(tableName, idFunc, document, conn)
|
||||
|
||||
|
||||
/// <summary>Commands to patch (partially update) documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Patch =
|
||||
|
||||
/// <summary>Patch a document by its ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be patched (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to patch</param>
|
||||
/// <param name="patch">The partial document to patch the existing document</param>
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) (patch: 'TPatch) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Patch.byId tableName docId patch conn
|
||||
|
||||
/// <summary>
|
||||
/// Patch documents using a JSON field comparison query in the <c>WHERE</c> clause (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table in which documents should be patched (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="patch">The partial document to patch the existing document</param>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields (patch: 'TPatch) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Patch.byFields tableName howMatched fields patch conn
|
||||
|
||||
|
||||
/// <summary>Commands to remove fields from documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module RemoveFields =
|
||||
|
||||
/// <summary>Remove fields from a document by the document's ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be modified (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to modify</param>
|
||||
/// <param name="fieldNames">One or more field names to remove from the document</param>
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) fieldNames =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.RemoveFields.byId tableName docId fieldNames conn
|
||||
|
||||
/// <summary>Remove fields from documents via a comparison on JSON fields in the document</summary>
|
||||
/// <param name="tableName">The table in which documents should be modified (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="fieldNames">One or more field names to remove from the matching documents</param>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields fieldNames =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.RemoveFields.byFields tableName howMatched fields fieldNames conn
|
||||
|
||||
|
||||
/// <summary>Commands to delete documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Delete =
|
||||
|
||||
/// <summary>Delete a document by its ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be deleted (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to delete</param>
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Delete.byId tableName docId conn
|
||||
|
||||
/// <summary>Delete documents by matching a JSON field comparison query (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which documents should be deleted (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields =
|
||||
use conn = Configuration.dbConn ()
|
||||
WithConn.Delete.byFields tableName howMatched fields conn
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,7 +13,7 @@ This package provides a lightweight document library backed by [SQLite](https://
|
||||
|
||||
## Upgrading from v3
|
||||
|
||||
There is a breaking API change for `ByField` (C#) / `byField` (F#), along with a compatibility namespace that can mitigate the impact of these changes. See [the migration guide](https://bitbadger.solutions/open-source/relational-documents/upgrade-from-v3-to-v4.html) for full details.
|
||||
There is a breaking API change for `ByField` (C#) / `byField` (F#), along with a compatibility namespace that can mitigate the impact of these changes. See [the migration guide](https://relationaldocs.bitbadger.solutions/dotnet/upgrade/v4.html) for full details.
|
||||
|
||||
## Getting Started
|
||||
|
||||
@@ -103,4 +103,4 @@ do! Delete.byFields "customer" Any [ Field.Equal "City" "Chicago" ]
|
||||
|
||||
## More Information
|
||||
|
||||
The [project site](https://bitbadger.solutions/open-source/relational-documents/) has full details on how to use this library.
|
||||
The [project site](https://relationaldocs.bitbadger.solutions/dotnet/) has full details on how to use this library.
|
||||
|
||||
784
src/Sqlite/WithConn.fs
Normal file
784
src/Sqlite/WithConn.fs
Normal file
@@ -0,0 +1,784 @@
|
||||
/// <summary>Versions of queries that accept a <c>SqliteConnection</c> as the last parameter</summary>
|
||||
module BitBadger.Documents.Sqlite.WithConn
|
||||
|
||||
open BitBadger.Documents
|
||||
open Microsoft.Data.Sqlite
|
||||
|
||||
/// <summary>Commands to execute custom SQL queries</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Custom =
|
||||
|
||||
/// <summary>Execute a query that returns a list of results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>A list of results for the given query</returns>
|
||||
[<CompiledName "FSharpList">]
|
||||
let list<'TDoc> query (parameters: SqliteParameter seq) (mapFunc: SqliteDataReader -> 'TDoc)
|
||||
(conn: SqliteConnection) =
|
||||
use cmd = conn.CreateCommand()
|
||||
cmd.CommandText <- query
|
||||
cmd.Parameters.AddRange parameters
|
||||
toCustomList<'TDoc> cmd mapFunc
|
||||
|
||||
/// <summary>Execute a query that returns a list of results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>A list of results for the given query</returns>
|
||||
let List<'TDoc>(
|
||||
query, parameters: SqliteParameter seq, mapFunc: System.Func<SqliteDataReader, 'TDoc>,
|
||||
conn: SqliteConnection
|
||||
) =
|
||||
use cmd = conn.CreateCommand()
|
||||
cmd.CommandText <- query
|
||||
cmd.Parameters.AddRange parameters
|
||||
ToCustomList<'TDoc>(cmd, mapFunc)
|
||||
|
||||
/// <summary>Execute a query that returns a JSON array of results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>A JSON array of results for the given query</returns>
|
||||
[<CompiledName "FSharpJsonArray">]
|
||||
let jsonArray
|
||||
query
|
||||
(parameters: SqliteParameter seq)
|
||||
(mapFunc: SqliteDataReader -> string)
|
||||
(conn: SqliteConnection) =
|
||||
use cmd = conn.CreateCommand()
|
||||
cmd.CommandText <- query
|
||||
cmd.Parameters.AddRange parameters
|
||||
toJsonArray cmd mapFunc
|
||||
|
||||
/// <summary>Execute a query that returns a JSON array of results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>A JSON array of results for the given query</returns>
|
||||
let JsonArray(query, parameters, mapFunc: System.Func<SqliteDataReader, string>, conn) =
|
||||
jsonArray query parameters mapFunc.Invoke conn
|
||||
|
||||
/// <summary>Execute a query, writing its results to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "FSharpWriteJsonArray">]
|
||||
let writeJsonArray
|
||||
query
|
||||
(parameters: SqliteParameter seq)
|
||||
writer
|
||||
(mapFunc: SqliteDataReader -> string)
|
||||
(conn: SqliteConnection) =
|
||||
use cmd = conn.CreateCommand()
|
||||
cmd.CommandText <- query
|
||||
cmd.Parameters.AddRange parameters
|
||||
writeJsonArray cmd writer mapFunc
|
||||
|
||||
/// <summary>Execute a query, writing its results to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
let WriteJsonArray(query, parameters, writer, mapFunc: System.Func<SqliteDataReader, string>, conn) =
|
||||
writeJsonArray query parameters writer mapFunc.Invoke conn
|
||||
|
||||
/// <summary>Execute a query that returns one or no results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns><c>Some</c> with the first matching result, or <c>None</c> if not found</returns>
|
||||
[<CompiledName "FSharpSingle">]
|
||||
let single<'TDoc> query parameters (mapFunc: SqliteDataReader -> 'TDoc) conn = backgroundTask {
|
||||
let! results = list query parameters mapFunc conn
|
||||
return FSharp.Collections.List.tryHead results
|
||||
}
|
||||
|
||||
/// <summary>Execute a query that returns one or no results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function between the document and the domain item</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The first matching result, or <c>null</c> if not found</returns>
|
||||
let Single<'TDoc when 'TDoc: null and 'TDoc: not struct>(
|
||||
query, parameters, mapFunc: System.Func<SqliteDataReader, 'TDoc>, conn
|
||||
) = backgroundTask {
|
||||
let! result = single<'TDoc> query parameters mapFunc.Invoke conn
|
||||
return Option.toObj result
|
||||
}
|
||||
|
||||
/// <summary>Execute a query that returns one or no JSON documents</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The JSON document with the first matching result, or an empty document if not found</returns>
|
||||
[<CompiledName "FSharpJsonSingle">]
|
||||
let jsonSingle query parameters mapFunc conn = backgroundTask {
|
||||
let! results = jsonArray $"%s{query} LIMIT 1" parameters mapFunc conn
|
||||
return if results = "[]" then "{}" else results[1..results.Length - 2]
|
||||
}
|
||||
|
||||
/// <summary>Execute a query that returns one or no JSON documents</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to extract the document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The JSON document with the first matching result, or an empty document if not found</returns>
|
||||
let JsonSingle(query, parameters, mapFunc: System.Func<SqliteDataReader, string>, conn) =
|
||||
jsonSingle query parameters mapFunc.Invoke conn
|
||||
|
||||
/// <summary>Execute a query that returns no results</summary>
|
||||
/// <param name="query">The query to retrieve the results</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "NonQuery">]
|
||||
let nonQuery query (parameters: SqliteParameter seq) (conn: SqliteConnection) =
|
||||
use cmd = conn.CreateCommand()
|
||||
cmd.CommandText <- query
|
||||
cmd.Parameters.AddRange parameters
|
||||
write cmd
|
||||
|
||||
/// <summary>Execute a query that returns a scalar value</summary>
|
||||
/// <param name="query">The query to retrieve the value</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to obtain the value</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The scalar value for the query</returns>
|
||||
[<CompiledName "FSharpScalar">]
|
||||
let scalar<'T when 'T : struct> query (parameters: SqliteParameter seq) (mapFunc: SqliteDataReader -> 'T)
|
||||
(conn: SqliteConnection) = backgroundTask {
|
||||
use cmd = conn.CreateCommand()
|
||||
cmd.CommandText <- query
|
||||
cmd.Parameters.AddRange parameters
|
||||
use! rdr = cmd.ExecuteReaderAsync()
|
||||
let! isFound = rdr.ReadAsync()
|
||||
return if isFound then mapFunc rdr else Unchecked.defaultof<'T>
|
||||
}
|
||||
|
||||
/// <summary>Execute a query that returns a scalar value</summary>
|
||||
/// <param name="query">The query to retrieve the value</param>
|
||||
/// <param name="parameters">Parameters to use for the query</param>
|
||||
/// <param name="mapFunc">The mapping function to obtain the value</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The scalar value for the query</returns>
|
||||
let Scalar<'T when 'T: struct>(query, parameters, mapFunc: System.Func<SqliteDataReader, 'T>, conn) =
|
||||
scalar<'T> query parameters mapFunc.Invoke conn
|
||||
|
||||
|
||||
/// <summary>Functions to create tables and indexes</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Definition =
|
||||
|
||||
/// <summary>Create a document table</summary>
|
||||
/// <param name="name">The table whose existence should be ensured (may include schema)</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "EnsureTable">]
|
||||
let ensureTable name conn = backgroundTask {
|
||||
do! Custom.nonQuery (Query.Definition.ensureTable name) [] conn
|
||||
do! Custom.nonQuery (Query.Definition.ensureKey name SQLite) [] conn
|
||||
}
|
||||
|
||||
/// <summary>Create an index on field(s) within documents in the specified table</summary>
|
||||
/// <param name="tableName">The table to be indexed (may include schema)</param>
|
||||
/// <param name="indexName">The name of the index to create</param>
|
||||
/// <param name="fields">One or more fields to be indexed</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "EnsureFieldIndex">]
|
||||
let ensureFieldIndex tableName indexName fields conn =
|
||||
Custom.nonQuery (Query.Definition.ensureIndexOn tableName indexName fields SQLite) [] conn
|
||||
|
||||
/// <summary>Commands to add documents</summary>
|
||||
[<AutoOpen>]
|
||||
module Document =
|
||||
|
||||
/// <summary>Insert a new document</summary>
|
||||
/// <param name="tableName">The table into which the document should be inserted (may include schema)</param>
|
||||
/// <param name="document">The document to be inserted</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<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
|
||||
|
||||
/// <summary>Save a document, inserting it if it does not exist and updating it if it does (AKA "upsert")</summary>
|
||||
/// <param name="tableName">The table into which the document should be saved (may include schema)</param>
|
||||
/// <param name="document">The document to be saved</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "Save">]
|
||||
let save<'TDoc> tableName (document: 'TDoc) conn =
|
||||
Custom.nonQuery (Query.save tableName) [ jsonParam "@data" document ] conn
|
||||
|
||||
|
||||
/// <summary>Commands to count documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Count =
|
||||
|
||||
/// <summary>Count all documents in a table</summary>
|
||||
/// <param name="tableName">The table in which documents should be counted (may include schema)</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The count of the documents in the table</returns>
|
||||
[<CompiledName "All">]
|
||||
let all tableName conn =
|
||||
Custom.scalar (Query.count tableName) [] toCount conn
|
||||
|
||||
/// <summary>Count matching documents using JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which documents should be counted (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The count of matching documents in the table</returns>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields conn =
|
||||
Custom.scalar
|
||||
(Query.byFields (Query.count tableName) howMatched fields) (addFieldParams fields []) toCount conn
|
||||
|
||||
|
||||
/// <summary>Commands to determine if documents exist</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Exists =
|
||||
|
||||
/// <summary>Determine if a document exists for the given ID</summary>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document whose existence should be checked</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>True if a document exists, false if not</returns>
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) conn =
|
||||
Custom.scalar (Query.exists tableName (Query.whereById docId)) [ idParam docId ] toExists conn
|
||||
|
||||
/// <summary>Determine if a document exists using JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which existence should be checked (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>True if any matching documents exist, false if not</returns>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields conn =
|
||||
Custom.scalar
|
||||
(Query.exists tableName (Query.whereByFields howMatched fields))
|
||||
(addFieldParams fields [])
|
||||
toExists
|
||||
conn
|
||||
|
||||
|
||||
/// <summary>Commands to retrieve documents as domain items</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Find =
|
||||
|
||||
/// <summary>Retrieve all documents in the given table</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All documents from the given table</returns>
|
||||
[<CompiledName "FSharpAll">]
|
||||
let all<'TDoc> tableName conn =
|
||||
Custom.list<'TDoc> (Query.find tableName) [] fromData<'TDoc> conn
|
||||
|
||||
/// <summary>Retrieve all documents in the given table</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All documents from the given table</returns>
|
||||
let All<'TDoc>(tableName, conn) =
|
||||
Custom.List(Query.find tableName, [], fromData<'TDoc>, conn)
|
||||
|
||||
/// <summary>Retrieve all documents in the given table ordered by the given fields in the document</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All documents from the given table, ordered by the given fields</returns>
|
||||
[<CompiledName "FSharpAllOrdered">]
|
||||
let allOrdered<'TDoc> tableName orderFields conn =
|
||||
Custom.list<'TDoc> (Query.find tableName + Query.orderBy orderFields SQLite) [] fromData<'TDoc> conn
|
||||
|
||||
/// <summary>Retrieve all documents in the given table ordered by the given fields in the document</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All documents from the given table, ordered by the given fields</returns>
|
||||
let AllOrdered<'TDoc>(tableName, orderFields, conn) =
|
||||
Custom.List(Query.find tableName + Query.orderBy orderFields SQLite, [], fromData<'TDoc>, conn)
|
||||
|
||||
/// <summary>Retrieve a document by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns><c>Some</c> with the document if found, <c>None</c> otherwise</returns>
|
||||
[<CompiledName "FSharpById">]
|
||||
let byId<'TKey, 'TDoc> tableName (docId: 'TKey) conn =
|
||||
Custom.single<'TDoc> (Query.byId (Query.find tableName) docId) [ idParam docId ] fromData<'TDoc> conn
|
||||
|
||||
/// <summary>Retrieve a document by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The document if found, <c>null</c> otherwise</returns>
|
||||
let ById<'TKey, 'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, docId: 'TKey, conn) =
|
||||
Custom.Single<'TDoc>(Query.byId (Query.find tableName) docId, [ idParam docId ], fromData<'TDoc>, conn)
|
||||
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All documents matching the given fields</returns>
|
||||
[<CompiledName "FSharpByFields">]
|
||||
let byFields<'TDoc> tableName howMatched fields conn =
|
||||
Custom.list<'TDoc>
|
||||
(Query.byFields (Query.find tableName) howMatched fields)
|
||||
(addFieldParams fields [])
|
||||
fromData<'TDoc>
|
||||
conn
|
||||
|
||||
/// <summary>Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All documents matching the given fields</returns>
|
||||
let ByFields<'TDoc>(tableName, howMatched, fields, conn) =
|
||||
Custom.List<'TDoc>(
|
||||
Query.byFields (Query.find tableName) howMatched fields,
|
||||
addFieldParams fields [],
|
||||
fromData<'TDoc>,
|
||||
conn)
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All documents matching the given fields, ordered by the other given fields</returns>
|
||||
[<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
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields in the
|
||||
/// document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All documents matching the given fields, ordered by the other given fields</returns>
|
||||
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)
|
||||
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns><c>Some</c> with the first document, or <c>None</c> if not found</returns>
|
||||
[<CompiledName "FSharpFirstByFields">]
|
||||
let firstByFields<'TDoc> tableName howMatched fields conn =
|
||||
Custom.single
|
||||
$"{Query.byFields (Query.find tableName) howMatched fields} LIMIT 1"
|
||||
(addFieldParams fields [])
|
||||
fromData<'TDoc>
|
||||
conn
|
||||
|
||||
/// <summary>Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The first document, or <c>null</c> if not found</returns>
|
||||
let FirstByFields<'TDoc when 'TDoc: null and 'TDoc: not struct>(tableName, howMatched, fields, conn) =
|
||||
Custom.Single(
|
||||
$"{Query.byFields (Query.find tableName) howMatched fields} LIMIT 1",
|
||||
addFieldParams fields [],
|
||||
fromData<'TDoc>,
|
||||
conn)
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>
|
||||
/// <c>Some</c> with the first document ordered by the given fields, or <c>None</c> if not found
|
||||
/// </returns>
|
||||
[<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
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The first document ordered by the given fields, or <c>null</c> if not found</returns>
|
||||
let FirstByFieldsOrdered<'TDoc when 'TDoc: null and 'TDoc: not struct>(
|
||||
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)
|
||||
|
||||
|
||||
/// <summary>Commands to retrieve documents as raw JSON</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Json =
|
||||
|
||||
/// <summary>Retrieve all JSON documents in the given table</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All JSON documents from the given table</returns>
|
||||
[<CompiledName "All">]
|
||||
let all tableName conn =
|
||||
Custom.jsonArray (Query.find tableName) [] jsonFromData conn
|
||||
|
||||
/// <summary>Retrieve all JSON documents in the given table ordered by the given fields in the document</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All JSON documents from the given table, ordered by the given fields</returns>
|
||||
[<CompiledName "AllOrdered">]
|
||||
let allOrdered tableName orderFields conn =
|
||||
Custom.jsonArray (Query.find tableName + Query.orderBy orderFields SQLite) [] jsonFromData conn
|
||||
|
||||
/// <summary>Retrieve a JSON document by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "ById">]
|
||||
let byId<'TKey> tableName (docId: 'TKey) conn =
|
||||
Custom.jsonSingle (Query.byId (Query.find tableName) docId) [ idParam docId ] jsonFromData conn
|
||||
|
||||
/// <summary>Retrieve JSON documents matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All JSON documents matching the given fields</returns>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields conn =
|
||||
Custom.jsonArray
|
||||
(Query.byFields (Query.find tableName) howMatched fields) (addFieldParams fields []) jsonFromData conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve JSON documents matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given fields
|
||||
/// in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>All JSON documents matching the given fields, ordered by the other given fields</returns>
|
||||
[<CompiledName "ByFieldsOrdered">]
|
||||
let byFieldsOrdered tableName howMatched queryFields orderFields conn =
|
||||
Custom.jsonArray
|
||||
(Query.byFields (Query.find tableName) howMatched queryFields + Query.orderBy orderFields SQLite)
|
||||
(addFieldParams queryFields [])
|
||||
jsonFromData
|
||||
conn
|
||||
|
||||
/// <summary>Retrieve the first JSON document matching JSON field comparisons (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The first JSON document if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "FirstByFields">]
|
||||
let firstByFields tableName howMatched fields conn =
|
||||
Custom.jsonSingle
|
||||
(Query.byFields (Query.find tableName) howMatched fields) (addFieldParams fields []) jsonFromData conn
|
||||
|
||||
/// <summary>
|
||||
/// Retrieve the first JSON document matching JSON field comparisons (<c>->> =</c>, etc.) ordered by the given
|
||||
/// fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
/// <returns>The first JSON document (in order) if found, an empty JSON document otherwise</returns>
|
||||
[<CompiledName "FirstByFieldsOrdered">]
|
||||
let firstByFieldsOrdered tableName howMatched queryFields orderFields conn =
|
||||
Custom.jsonSingle
|
||||
(Query.byFields (Query.find tableName) howMatched queryFields + Query.orderBy orderFields SQLite)
|
||||
(addFieldParams queryFields [])
|
||||
jsonFromData
|
||||
conn
|
||||
|
||||
/// <summary>Write all JSON documents in the given table to the given <c>PipeWriter</c></summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "WriteAll">]
|
||||
let writeAll tableName writer conn =
|
||||
Custom.writeJsonArray (Query.find tableName) [] writer jsonFromData conn
|
||||
|
||||
/// <summary>
|
||||
/// Write all JSON all documents in the given table to the given <c>PipeWriter</c>, ordered by the given fields in
|
||||
/// the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "WriteAllOrdered">]
|
||||
let writeAllOrdered tableName writer orderFields conn =
|
||||
Custom.writeJsonArray (Query.find tableName + Query.orderBy orderFields SQLite) [] writer jsonFromData conn
|
||||
|
||||
/// <summary>Write a JSON document to the given <c>PipeWriter</c> by its ID</summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="docId">The ID of the document to retrieve</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "WriteById">]
|
||||
let writeById<'TKey> tableName writer (docId: 'TKey) conn = backgroundTask {
|
||||
let! json = Custom.jsonSingle (Query.byId (Query.find tableName) docId) [ idParam docId ] jsonFromData conn
|
||||
let! _ = PipeWriter.writeString writer json
|
||||
()
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching JSON field comparisons (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "WriteByFields">]
|
||||
let writeByFields tableName writer howMatched fields conn =
|
||||
Custom.writeJsonArray
|
||||
(Query.byFields (Query.find tableName) howMatched fields)
|
||||
(addFieldParams fields [])
|
||||
writer
|
||||
jsonFromData
|
||||
conn
|
||||
|
||||
/// <summary>
|
||||
/// Write JSON documents to the given <c>PipeWriter</c> matching JSON field comparisons (<c>->> =</c>, etc.)
|
||||
/// ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which documents should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "WriteByFieldsOrdered">]
|
||||
let writeByFieldsOrdered tableName writer howMatched queryFields orderFields conn =
|
||||
Custom.writeJsonArray
|
||||
(Query.byFields (Query.find tableName) howMatched queryFields + Query.orderBy orderFields SQLite)
|
||||
(addFieldParams queryFields [])
|
||||
writer
|
||||
jsonFromData
|
||||
conn
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching JSON field comparisons
|
||||
/// (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "WriteFirstByFields">]
|
||||
let writeFirstByFields tableName writer howMatched fields conn = backgroundTask {
|
||||
let! json =
|
||||
Custom.jsonSingle
|
||||
(Query.byFields (Query.find tableName) howMatched fields) (addFieldParams fields []) jsonFromData conn
|
||||
let! _ = PipeWriter.writeString writer json
|
||||
()
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write the first JSON document to the given <c>PipeWriter</c> matching JSON field comparisons
|
||||
/// (<c>->> =</c>, etc.) ordered by the given fields in the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table from which a document should be retrieved (may include schema)</param>
|
||||
/// <param name="writer">The PipeWriter to which the results should be written</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="queryFields">The field conditions to match</param>
|
||||
/// <param name="orderFields">Fields by which the results should be ordered</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "WriteFirstByFieldsOrdered">]
|
||||
let writeFirstByFieldsOrdered tableName writer howMatched queryFields orderFields conn = backgroundTask {
|
||||
let! json =
|
||||
Custom.jsonSingle
|
||||
(Query.byFields (Query.find tableName) howMatched queryFields + Query.orderBy orderFields SQLite)
|
||||
(addFieldParams queryFields [])
|
||||
jsonFromData
|
||||
conn
|
||||
let! _ = PipeWriter.writeString writer json
|
||||
()
|
||||
}
|
||||
|
||||
|
||||
/// <summary>Commands to update documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Update =
|
||||
|
||||
/// <summary>Update (replace) an entire document by its ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be updated (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to be updated (replaced)</param>
|
||||
/// <param name="document">The new document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) (document: 'TDoc) conn =
|
||||
Custom.nonQuery
|
||||
(Query.statementWhere (Query.update tableName) (Query.whereById docId))
|
||||
[ idParam docId; jsonParam "@data" document ]
|
||||
conn
|
||||
|
||||
/// <summary>
|
||||
/// Update (replace) an entire document by its ID, using the provided function to obtain the ID from the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table in which a document should be updated (may include schema)</param>
|
||||
/// <param name="idFunc">The function to obtain the ID of the document</param>
|
||||
/// <param name="document">The new document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "FSharpByFunc">]
|
||||
let byFunc tableName (idFunc: 'TDoc -> 'TKey) (document: 'TDoc) conn =
|
||||
byId tableName (idFunc document) document conn
|
||||
|
||||
/// <summary>
|
||||
/// Update (replace) an entire document by its ID, using the provided function to obtain the ID from the document
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table in which a document should be updated (may include schema)</param>
|
||||
/// <param name="idFunc">The function to obtain the ID of the document</param>
|
||||
/// <param name="document">The new document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
let ByFunc(tableName, idFunc: System.Func<'TDoc, 'TKey>, document: 'TDoc, conn) =
|
||||
byFunc tableName idFunc.Invoke document conn
|
||||
|
||||
|
||||
/// <summary>Commands to patch (partially update) documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Patch =
|
||||
|
||||
/// <summary>Patch a document by its ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be patched (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to patch</param>
|
||||
/// <param name="patch">The partial document to patch the existing document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) (patch: 'TPatch) conn =
|
||||
Custom.nonQuery
|
||||
(Query.byId (Query.patch tableName) docId) [ idParam docId; jsonParam "@data" patch ] conn
|
||||
|
||||
/// <summary>
|
||||
/// Patch documents using a JSON field comparison query in the <c>WHERE</c> clause (<c>->> =</c>, etc.)
|
||||
/// </summary>
|
||||
/// <param name="tableName">The table in which documents should be patched (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="patch">The partial document to patch the existing document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<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
|
||||
|
||||
|
||||
/// <summary>Commands to remove fields from documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module RemoveFields =
|
||||
|
||||
/// <summary>Remove fields from a document by the document's ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be modified (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to modify</param>
|
||||
/// <param name="fieldNames">One or more field names to remove from the document</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) fieldNames conn =
|
||||
let nameParams = fieldNameParams "@name" fieldNames
|
||||
Custom.nonQuery
|
||||
(Query.byId (Query.removeFields tableName nameParams) docId)
|
||||
(idParam docId |> Seq.singleton |> Seq.append nameParams)
|
||||
conn
|
||||
|
||||
/// <summary>Remove fields from documents via a comparison on JSON fields in the document</summary>
|
||||
/// <param name="tableName">The table in which documents should be modified (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="fieldNames">One or more field names to remove from the matching documents</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields fieldNames conn =
|
||||
let nameParams = fieldNameParams "@name" fieldNames
|
||||
Custom.nonQuery
|
||||
(Query.byFields (Query.removeFields tableName nameParams) howMatched fields)
|
||||
(addFieldParams fields nameParams)
|
||||
conn
|
||||
|
||||
|
||||
/// <summary>Commands to delete documents</summary>
|
||||
[<RequireQualifiedAccess>]
|
||||
module Delete =
|
||||
|
||||
/// <summary>Delete a document by its ID</summary>
|
||||
/// <param name="tableName">The table in which a document should be deleted (may include schema)</param>
|
||||
/// <param name="docId">The ID of the document to delete</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "ById">]
|
||||
let byId tableName (docId: 'TKey) conn =
|
||||
Custom.nonQuery (Query.byId (Query.delete tableName) docId) [ idParam docId ] conn
|
||||
|
||||
/// <summary>Delete documents by matching a JSON field comparison query (<c>->> =</c>, etc.)</summary>
|
||||
/// <param name="tableName">The table in which documents should be deleted (may include schema)</param>
|
||||
/// <param name="howMatched">Whether to match any or all of the field conditions</param>
|
||||
/// <param name="fields">The field conditions to match</param>
|
||||
/// <param name="conn">The <c>SqliteConnection</c> to use to execute the query</param>
|
||||
[<CompiledName "ByFields">]
|
||||
let byFields tableName howMatched fields conn =
|
||||
Custom.nonQuery (Query.byFields (Query.delete tableName) howMatched fields) (addFieldParams fields []) conn
|
||||
@@ -4,6 +4,7 @@
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<NoWarn>1591</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.IO.Pipelines;
|
||||
using Expecto.CSharp;
|
||||
using Expecto;
|
||||
using Microsoft.FSharp.Core;
|
||||
@@ -16,7 +17,7 @@ internal class TestSerializer : IDocumentSerializer
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// C# Tests for common functionality in <tt>BitBadger.Documents</tt>
|
||||
/// C# Tests for common functionality in <c>BitBadger.Documents</c>
|
||||
/// </summary>
|
||||
public static class CommonCSharpTests
|
||||
{
|
||||
@@ -417,7 +418,7 @@ public static class CommonCSharpTests
|
||||
})
|
||||
])
|
||||
]);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for the Configuration static class
|
||||
/// </summary>
|
||||
@@ -647,7 +648,115 @@ public static class CommonCSharpTests
|
||||
})
|
||||
])
|
||||
]);
|
||||
|
||||
|
||||
private static string StreamText(Stream stream)
|
||||
{
|
||||
stream.Position = 0L;
|
||||
using StreamReader reader = new(stream);
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
|
||||
/// <summary>Unit tests for the PipeWriter module</summary>
|
||||
private static readonly Test PipeWriterTests = TestList("PipeWriterModule",
|
||||
[
|
||||
TestList("WriteString",
|
||||
[
|
||||
TestCase("succeeds when writer is open", async () =>
|
||||
{
|
||||
await using MemoryStream stream = new();
|
||||
var writer = PipeWriter.Create(stream, new StreamPipeWriterOptions(leaveOpen: true));
|
||||
try
|
||||
{
|
||||
var result = await PipeWriterModule.WriteString(writer, "abc");
|
||||
Expect.isTrue(result, "The write operation should have been successful");
|
||||
Expect.equal(StreamText(stream), "abc", "The string was not written correctly");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when writer is completed", async () =>
|
||||
{
|
||||
await using MemoryStream stream = new();
|
||||
var writer = PipeWriter.Create(stream, new StreamPipeWriterOptions(leaveOpen: true));
|
||||
await writer.CompleteAsync();
|
||||
|
||||
var result = await PipeWriterModule.WriteString(writer, "abc");
|
||||
Expect.isFalse(result, "The write operation should have returned false");
|
||||
Expect.equal(StreamText(stream), "", "No text should have been written");
|
||||
})
|
||||
]),
|
||||
TestList("WriteStrings",
|
||||
[
|
||||
TestCase("succeeds with no strings", async () =>
|
||||
{
|
||||
await using MemoryStream stream = new();
|
||||
var writer = PipeWriter.Create(stream, new StreamPipeWriterOptions(leaveOpen: true));
|
||||
try
|
||||
{
|
||||
await PipeWriterModule.WriteStrings(writer, []);
|
||||
Expect.equal(StreamText(stream), "[]", "An empty sequence of strings was not written correctly");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds with one strings", async () =>
|
||||
{
|
||||
await using MemoryStream stream = new();
|
||||
var writer = PipeWriter.Create(stream, new StreamPipeWriterOptions(leaveOpen: true));
|
||||
try
|
||||
{
|
||||
await PipeWriterModule.WriteStrings(writer, ["le-test"]);
|
||||
Expect.equal(StreamText(stream), "[le-test]", "A sequence of one string was not written correctly");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds with many strings", async () =>
|
||||
{
|
||||
await using MemoryStream stream = new();
|
||||
var writer = PipeWriter.Create(stream, new StreamPipeWriterOptions(leaveOpen: true));
|
||||
|
||||
try
|
||||
{
|
||||
await PipeWriterModule.WriteStrings(writer, ["z", "y", "x", "c", "b", "a"]);
|
||||
Expect.equal(StreamText(stream), "[z,y,x,c,b,a]",
|
||||
"A sequence of many strings was not written correctly");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when the writer is completed early", async () =>
|
||||
{
|
||||
await using MemoryStream stream = new();
|
||||
var writer = PipeWriter.Create(stream, new StreamPipeWriterOptions(leaveOpen: true));
|
||||
|
||||
await PipeWriterModule.WriteStrings(writer, Items());
|
||||
Expect.equal(StreamText(stream), "[a,b,c", "The writing should have stopped when the writer completed");
|
||||
return;
|
||||
|
||||
IEnumerable<string> Items()
|
||||
{
|
||||
yield return "a";
|
||||
yield return "b";
|
||||
yield return "c";
|
||||
writer.Complete();
|
||||
yield return "d";
|
||||
yield return "e";
|
||||
yield return "f";
|
||||
}
|
||||
})
|
||||
])
|
||||
]);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests
|
||||
/// </summary>
|
||||
@@ -660,6 +769,7 @@ public static class CommonCSharpTests
|
||||
ParameterNameTests,
|
||||
AutoIdTests,
|
||||
QueryTests,
|
||||
PipeWriterTests,
|
||||
TestSequenced(ConfigurationTests)
|
||||
]);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,9 @@
|
||||
using Expecto.CSharp;
|
||||
using System.IO.Pipelines;
|
||||
using Expecto.CSharp;
|
||||
using Expecto;
|
||||
using Microsoft.FSharp.Core;
|
||||
using BitBadger.Documents.Sqlite;
|
||||
using Microsoft.Data.Sqlite;
|
||||
|
||||
namespace BitBadger.Documents.Tests.CSharp;
|
||||
|
||||
@@ -147,7 +149,7 @@ public static class SqliteCSharpTests
|
||||
/// <summary>
|
||||
/// Add the test documents to the database
|
||||
/// </summary>
|
||||
internal static async Task LoadDocs()
|
||||
private static async Task LoadDocs()
|
||||
{
|
||||
foreach (var doc in JsonDocument.TestDocuments) await Document.Insert(SqliteDb.TableName, doc);
|
||||
}
|
||||
@@ -169,11 +171,139 @@ public static class SqliteCSharpTests
|
||||
}
|
||||
});
|
||||
|
||||
/// <summary>Verify a JSON array begins with "[" and ends with "]"</summary>
|
||||
private static void VerifyBeginEnd(string json)
|
||||
{
|
||||
Expect.stringStarts(json, "[", "The array should have started with `[`");
|
||||
Expect.stringEnds(json, "]", "The array should have ended with `]`");
|
||||
}
|
||||
|
||||
/// <summary>Verify an empty JSON array</summary>
|
||||
private static void VerifyEmpty(string json) =>
|
||||
Expect.equal(json, "[]", "There should be no documents returned");
|
||||
|
||||
/// <summary>Verify an empty JSON document</summary>
|
||||
private static void VerifyNoDoc(string json) =>
|
||||
Expect.equal(json, "{}", "There should be no document returned");
|
||||
|
||||
/// <summary>Set up a stream writer for a test</summary>
|
||||
private static PipeWriter WriteStream(Stream stream) =>
|
||||
PipeWriter.Create(stream, new StreamPipeWriterOptions(leaveOpen: true));
|
||||
|
||||
/// <summary>Get the text of the given stream</summary>
|
||||
private static string StreamText(Stream stream)
|
||||
{
|
||||
stream.Position = 0L;
|
||||
using StreamReader reader = new(stream);
|
||||
return reader.ReadToEnd();
|
||||
}
|
||||
|
||||
/// Verify the presence of any of the given documents in the given JSON
|
||||
private static void VerifyAny(string json, IEnumerable<string> docs)
|
||||
{
|
||||
var theDocs = docs.ToList();
|
||||
if (theDocs.Any(json.Contains)) return;
|
||||
var anyDocs = string.Join(" | ", theDocs);
|
||||
Expect.isTrue(false, $"Could not find any of |{anyDocs}| in {json}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Integration tests for the Custom module of the SQLite library
|
||||
/// </summary>
|
||||
private static readonly Test CustomTests = TestList("Custom",
|
||||
[
|
||||
TestList("List",
|
||||
[
|
||||
TestCase("succeeds when data is found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
var docs = await Custom.List(Query.Find(SqliteDb.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 = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
var docs = await Custom.List(
|
||||
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value", [new("@value", 100)],
|
||||
Results.FromData<JsonDocument>);
|
||||
Expect.isEmpty(docs, "There should have been no documents returned");
|
||||
})
|
||||
]),
|
||||
TestList("JsonArray",
|
||||
[
|
||||
TestCase("succeeds when data is found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
var json = await Custom.JsonArray(Query.Find(SqliteDb.TableName), [], Results.JsonFromData);
|
||||
VerifyBeginEnd(json);
|
||||
Expect.stringContains(json, JsonDocument.One, "Document ID `one` should have been found");
|
||||
Expect.stringContains(json, JsonDocument.Two,"Document ID `two` should have been found");
|
||||
Expect.stringContains(json, JsonDocument.Three, "Document ID `three` should have been found");
|
||||
Expect.stringContains(json, JsonDocument.Four, "Document ID `four` should have been found");
|
||||
Expect.stringContains(json, JsonDocument.Five, "Document ID `five` should have been found");
|
||||
}),
|
||||
TestCase("succeeds when data is not found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
VerifyEmpty(await Custom.JsonArray(
|
||||
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value",
|
||||
[new SqliteParameter("@value", 100)], Results.JsonFromData));
|
||||
})
|
||||
]),
|
||||
TestList("WriteJsonArray",
|
||||
[
|
||||
TestCase("succeeds when data is found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Custom.WriteJsonArray(Query.Find(SqliteDb.TableName), [], writer, Results.JsonFromData);
|
||||
var json = StreamText(stream);
|
||||
VerifyBeginEnd(json);
|
||||
Expect.stringContains(json, JsonDocument.One, "Document ID `one` should have been found");
|
||||
Expect.stringContains(json, JsonDocument.Two, "Document ID `two` should have been found");
|
||||
Expect.stringContains(json, JsonDocument.Three, "Document ID `three` should have been found");
|
||||
Expect.stringContains(json, JsonDocument.Four, "Document ID `four` should have been found");
|
||||
Expect.stringContains(json, JsonDocument.Five, "Document ID `five` should have been found");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when data is not found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Custom.WriteJsonArray(
|
||||
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value",
|
||||
[new SqliteParameter("@value", 100)], writer, Results.JsonFromData);
|
||||
VerifyEmpty(StreamText(stream));
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
})
|
||||
]),
|
||||
TestList("Single",
|
||||
[
|
||||
TestCase("succeeds when a row is found", async () =>
|
||||
@@ -196,26 +326,24 @@ public static class SqliteCSharpTests
|
||||
Expect.isNull(doc, "There should not have been a document returned");
|
||||
})
|
||||
]),
|
||||
TestList("List",
|
||||
TestList("JsonSingle",
|
||||
[
|
||||
TestCase("succeeds when data is found", async () =>
|
||||
TestCase("succeeds when a row is found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
var docs = await Custom.List(Query.Find(SqliteDb.TableName), Parameters.None,
|
||||
Results.FromData<JsonDocument>);
|
||||
Expect.equal(docs.Count, 5, "There should have been 5 documents returned");
|
||||
var json = await Custom.JsonSingle($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
|
||||
[new SqliteParameter("@id", "one")], Results.JsonFromData);
|
||||
Expect.equal(json, JsonDocument.One, "The JSON document is incorrect");
|
||||
}),
|
||||
TestCase("succeeds when data is not found", async () =>
|
||||
TestCase("succeeds when a row is not found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
var docs = await Custom.List(
|
||||
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value", [new("@value", 100)],
|
||||
Results.FromData<JsonDocument>);
|
||||
Expect.isEmpty(docs, "There should have been no documents returned");
|
||||
VerifyNoDoc(await Custom.JsonSingle($"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id",
|
||||
[new SqliteParameter("@id", "eighty")], Results.JsonFromData));
|
||||
})
|
||||
]),
|
||||
TestList("NonQuery",
|
||||
@@ -757,6 +885,635 @@ public static class SqliteCSharpTests
|
||||
])
|
||||
]);
|
||||
|
||||
/// Integration tests for the Json module of the SQLite library
|
||||
private static readonly Test JsonTests = TestList("Json",
|
||||
[
|
||||
TestList("All",
|
||||
[
|
||||
TestCase("succeeds when there is data", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
|
||||
await Document.Insert(SqliteDb.TableName, new SubDocument { Foo = "one", Bar = "two" });
|
||||
await Document.Insert(SqliteDb.TableName, new SubDocument { Foo = "three", Bar = "four" });
|
||||
await Document.Insert(SqliteDb.TableName, new SubDocument { Foo = "five", Bar = "six" });
|
||||
|
||||
var json = await Json.All(SqliteDb.TableName);
|
||||
VerifyBeginEnd(json);
|
||||
Expect.stringContains(json, """{"Foo":"one","Bar":"two"}""", "The first document was not found");
|
||||
Expect.stringContains(json, """{"Foo":"three","Bar":"four"}""", "The second document was not found");
|
||||
Expect.stringContains(json, """{"Foo":"five","Bar":"six"}""", "The third document was not found");
|
||||
}),
|
||||
TestCase("succeeds when there is no data", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
VerifyEmpty(await Json.All(SqliteDb.TableName));
|
||||
})
|
||||
]),
|
||||
TestList("AllOrdered",
|
||||
[
|
||||
TestCase("succeeds when ordering numerically", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(await Json.AllOrdered(SqliteDb.TableName, [Field.Named("n:NumValue")]),
|
||||
$"[{JsonDocument.One},{JsonDocument.Three},{JsonDocument.Two},{JsonDocument.Four},{JsonDocument.Five}]",
|
||||
"The documents were not ordered correctly");
|
||||
}),
|
||||
TestCase("succeeds when ordering numerically descending", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(await Json.AllOrdered(SqliteDb.TableName, [Field.Named("n:NumValue DESC")]),
|
||||
$"[{JsonDocument.Five},{JsonDocument.Four},{JsonDocument.Two},{JsonDocument.Three},{JsonDocument.One}]",
|
||||
"The documents were not ordered correctly");
|
||||
}),
|
||||
TestCase("succeeds when ordering alphabetically", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(await Json.AllOrdered(SqliteDb.TableName, [Field.Named("Id DESC")]),
|
||||
$"[{JsonDocument.Two},{JsonDocument.Three},{JsonDocument.One},{JsonDocument.Four},{JsonDocument.Five}]",
|
||||
"The documents were not ordered correctly");
|
||||
})
|
||||
]),
|
||||
TestList("ById",
|
||||
[
|
||||
TestCase("succeeds when a document is found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(await Json.ById(SqliteDb.TableName, "two"), JsonDocument.Two,
|
||||
"The incorrect document was returned");
|
||||
}),
|
||||
TestCase("succeeds when a document is not found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
VerifyNoDoc(await Json.ById(SqliteDb.TableName, "three hundred eighty-seven"));
|
||||
})
|
||||
]),
|
||||
TestList("ByFields",
|
||||
[
|
||||
TestCase("succeeds when documents are found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
var json = await Json.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Greater("NumValue", 15)]);
|
||||
VerifyBeginEnd(json);
|
||||
Expect.stringContains(json, JsonDocument.Four, "Document `four` should have been returned");
|
||||
Expect.stringContains(json, JsonDocument.Five, "Document `five` should have been returned");
|
||||
}),
|
||||
TestCase("succeeds when documents are found using IN with numeric field", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(
|
||||
await Json.ByFields(SqliteDb.TableName, FieldMatch.All, [Field.In("NumValue", [2, 4, 6, 8])]),
|
||||
$"[{JsonDocument.Three}]", "There should have been one document returned");
|
||||
}),
|
||||
TestCase("succeeds when documents are not found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
VerifyEmpty(await Json.ByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Greater("NumValue", 100)]));
|
||||
}),
|
||||
TestCase("succeeds for InArray when matching documents exist", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await Definition.EnsureTable(SqliteDb.TableName);
|
||||
foreach (var doc in ArrayDocument.TestDocuments) await Document.Insert(SqliteDb.TableName, doc);
|
||||
|
||||
var json = await Json.ByFields(SqliteDb.TableName, FieldMatch.All,
|
||||
[Field.InArray("Values", SqliteDb.TableName, ["c"])]);
|
||||
VerifyBeginEnd(json);
|
||||
Expect.stringContains(json, """{"Id":"first","Values":["a","b","c"]}""",
|
||||
"Document `first` should have been returned");
|
||||
Expect.stringContains(json, """{"Id":"second","Values":["c","d","e"]}""",
|
||||
"Document `second` should have been returned");
|
||||
}),
|
||||
TestCase("succeeds for InArray when no matching documents exist", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await Definition.EnsureTable(SqliteDb.TableName);
|
||||
foreach (var doc in ArrayDocument.TestDocuments) await Document.Insert(SqliteDb.TableName, doc);
|
||||
VerifyEmpty(await Json.ByFields(SqliteDb.TableName, FieldMatch.All,
|
||||
[Field.InArray("Values", SqliteDb.TableName, ["j"])]));
|
||||
})
|
||||
]),
|
||||
TestList("ByFieldsOrdered",
|
||||
[
|
||||
TestCase("succeeds when sorting ascending", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(
|
||||
await Json.ByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, [Field.Greater("NumValue", 15)],
|
||||
[Field.Named("Id")]), $"[{JsonDocument.Five},{JsonDocument.Four}]",
|
||||
"Incorrect documents were returned");
|
||||
}),
|
||||
TestCase("succeeds when sorting descending", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(
|
||||
await Json.ByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any, [Field.Greater("NumValue", 15)],
|
||||
[Field.Named("Id DESC")]), $"[{JsonDocument.Four},{JsonDocument.Five}]",
|
||||
"Incorrect documents were returned");
|
||||
}),
|
||||
TestCase("succeeds when sorting case-sensitively", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(
|
||||
await Json.ByFieldsOrdered(SqliteDb.TableName, FieldMatch.All, [Field.LessOrEqual("NumValue", 10)],
|
||||
[Field.Named("Value")]),
|
||||
$"[{JsonDocument.Three},{JsonDocument.One},{JsonDocument.Two}]", "Documents not ordered correctly");
|
||||
}),
|
||||
TestCase("succeeds when sorting case-insensitively", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(
|
||||
await Json.ByFieldsOrdered(SqliteDb.TableName, FieldMatch.All, [Field.LessOrEqual("NumValue", 10)],
|
||||
[Field.Named("i:Value")]),
|
||||
$"[{JsonDocument.Three},{JsonDocument.Two},{JsonDocument.One}]", "Documents not ordered correctly");
|
||||
})
|
||||
]),
|
||||
TestList("FirstByFields",
|
||||
[
|
||||
TestCase("succeeds when a document is found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(
|
||||
await Json.FirstByFields(SqliteDb.TableName, FieldMatch.Any, [Field.Equal("Value", "another")]),
|
||||
JsonDocument.Two, "The incorrect document was returned");
|
||||
}),
|
||||
TestCase("succeeds when multiple documents are found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
var json = await Json.FirstByFields(SqliteDb.TableName, FieldMatch.Any,
|
||||
[Field.Equal("Sub.Foo", "green")]);
|
||||
Expect.notEqual(json, "{}", "There should have been a document returned");
|
||||
VerifyAny(json, [JsonDocument.Two, JsonDocument.Four]);
|
||||
}),
|
||||
TestCase("succeeds when a document is not found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
VerifyNoDoc(await Json.FirstByFields(SqliteDb.TableName, FieldMatch.Any,
|
||||
[Field.Equal("Value", "absent")]));
|
||||
})
|
||||
]),
|
||||
TestList("FirstByFieldsOrdered",
|
||||
[
|
||||
TestCase("succeeds when sorting ascending", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(
|
||||
await Json.FirstByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any,
|
||||
[Field.Equal("Sub.Foo", "green")], [Field.Named("Sub.Bar")]), JsonDocument.Two,
|
||||
"An incorrect document was returned");
|
||||
}),
|
||||
TestCase("succeeds when sorting descending", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
Expect.equal(
|
||||
await Json.FirstByFieldsOrdered(SqliteDb.TableName, FieldMatch.Any,
|
||||
[Field.Equal("Sub.Foo", "green")], [Field.Named("Sub.Bar DESC")]), JsonDocument.Four,
|
||||
"An incorrect document was returned");
|
||||
})
|
||||
]),
|
||||
TestList("WriteAll",
|
||||
[
|
||||
TestCase("succeeds when there is data", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
|
||||
await Document.Insert(SqliteDb.TableName, new SubDocument { Foo = "one", Bar = "two" });
|
||||
await Document.Insert(SqliteDb.TableName, new SubDocument { Foo = "three", Bar = "four" });
|
||||
await Document.Insert(SqliteDb.TableName, new SubDocument { Foo = "five", Bar = "six" });
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteAll(SqliteDb.TableName, writer);
|
||||
var json = StreamText(stream);
|
||||
VerifyBeginEnd(json);
|
||||
Expect.stringContains(json, """{"Foo":"one","Bar":"two"}""", "The first document was not found");
|
||||
Expect.stringContains(json, """{"Foo":"three","Bar":"four"}""",
|
||||
"The second document was not found");
|
||||
Expect.stringContains(json, """{"Foo":"five","Bar":"six"}""", "The third document was not found");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when there is no data", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteAll(SqliteDb.TableName, writer);
|
||||
VerifyEmpty(StreamText(stream));
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
})
|
||||
]),
|
||||
TestList("WriteAllOrdered",
|
||||
[
|
||||
TestCase("succeeds when ordering numerically", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteAllOrdered(SqliteDb.TableName, writer, [Field.Named("n:NumValue")]);
|
||||
Expect.equal(StreamText(stream),
|
||||
$"[{JsonDocument.One},{JsonDocument.Three},{JsonDocument.Two},{JsonDocument.Four},{JsonDocument.Five}]",
|
||||
"The documents were not ordered correctly");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when ordering numerically descending", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteAllOrdered(SqliteDb.TableName, writer, [Field.Named("n:NumValue DESC")]);
|
||||
Expect.equal(StreamText(stream),
|
||||
$"[{JsonDocument.Five},{JsonDocument.Four},{JsonDocument.Two},{JsonDocument.Three},{JsonDocument.One}]",
|
||||
"The documents were not ordered correctly");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when ordering alphabetically", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteAllOrdered(SqliteDb.TableName, writer, [Field.Named("Id DESC")]);
|
||||
Expect.equal(StreamText(stream),
|
||||
$"[{JsonDocument.Two},{JsonDocument.Three},{JsonDocument.One},{JsonDocument.Four},{JsonDocument.Five}]",
|
||||
"The documents were not ordered correctly");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
})
|
||||
]),
|
||||
TestList("WriteById",
|
||||
[
|
||||
TestCase("succeeds when a document is found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteById(SqliteDb.TableName, writer, "two");
|
||||
Expect.equal(StreamText(stream), JsonDocument.Two, "The incorrect document was returned");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when a document is not found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteById(SqliteDb.TableName, writer, "three hundred eighty-seven");
|
||||
VerifyNoDoc(StreamText(stream));
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
})
|
||||
]),
|
||||
TestList("WriteByFields",
|
||||
[
|
||||
TestCase("succeeds when documents are found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteByFields(SqliteDb.TableName, writer, FieldMatch.Any,
|
||||
[Field.Greater("NumValue", 15)]);
|
||||
var json = StreamText(stream);
|
||||
VerifyBeginEnd(json);
|
||||
Expect.stringContains(json, JsonDocument.Four, "Document `four` should have been returned");
|
||||
Expect.stringContains(json, JsonDocument.Five, "Document `five` should have been returned");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when documents are found using IN with numeric field", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteByFields(SqliteDb.TableName, writer, FieldMatch.All,
|
||||
[Field.In("NumValue", [2, 4, 6, 8])]);
|
||||
Expect.equal(StreamText(stream), $"[{JsonDocument.Three}]",
|
||||
"There should have been one document returned");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when documents are not found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteByFields(SqliteDb.TableName, writer, FieldMatch.Any,
|
||||
[Field.Greater("NumValue", 100)]);
|
||||
VerifyEmpty(StreamText(stream));
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds for InArray when matching documents exist", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await Definition.EnsureTable(SqliteDb.TableName);
|
||||
foreach (var doc in ArrayDocument.TestDocuments) await Document.Insert(SqliteDb.TableName, doc);
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteByFields(SqliteDb.TableName, writer, FieldMatch.All,
|
||||
[Field.InArray("Values", SqliteDb.TableName, ["c"])]);
|
||||
var json = StreamText(stream);
|
||||
VerifyBeginEnd(json);
|
||||
Expect.stringContains(json, """{"Id":"first","Values":["a","b","c"]}""",
|
||||
"Document `first` should have been returned");
|
||||
Expect.stringContains(json, """{"Id":"second","Values":["c","d","e"]}""",
|
||||
"Document `second` should have been returned");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds for InArray when no matching documents exist", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await Definition.EnsureTable(SqliteDb.TableName);
|
||||
foreach (var doc in ArrayDocument.TestDocuments) await Document.Insert(SqliteDb.TableName, doc);
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteByFields(SqliteDb.TableName, writer, FieldMatch.All,
|
||||
[Field.InArray("Values", SqliteDb.TableName, ["j"])]);
|
||||
VerifyEmpty(StreamText(stream));
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
})
|
||||
]),
|
||||
TestList("WriteByFieldsOrdered",
|
||||
[
|
||||
TestCase("succeeds when sorting ascending", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteByFieldsOrdered(SqliteDb.TableName, writer, FieldMatch.Any,
|
||||
[Field.Greater("NumValue", 15)], [Field.Named("Id")]);
|
||||
Expect.equal(StreamText(stream), $"[{JsonDocument.Five},{JsonDocument.Four}]",
|
||||
"Incorrect documents were returned");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when sorting descending", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteByFieldsOrdered(SqliteDb.TableName, writer, FieldMatch.Any,
|
||||
[Field.Greater("NumValue", 15)], [Field.Named("Id DESC")]);
|
||||
Expect.equal(StreamText(stream), $"[{JsonDocument.Four},{JsonDocument.Five}]",
|
||||
"Incorrect documents were returned");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when sorting case-sensitively", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteByFieldsOrdered(SqliteDb.TableName, writer, FieldMatch.All,
|
||||
[Field.LessOrEqual("NumValue", 10)], [Field.Named("Value")]);
|
||||
Expect.equal(StreamText(stream), $"[{JsonDocument.Three},{JsonDocument.One},{JsonDocument.Two}]",
|
||||
"Documents not ordered correctly");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when sorting case-insensitively", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteByFieldsOrdered(SqliteDb.TableName, writer, FieldMatch.All,
|
||||
[Field.LessOrEqual("NumValue", 10)], [Field.Named("i:Value")]);
|
||||
Expect.equal(StreamText(stream), $"[{JsonDocument.Three},{JsonDocument.Two},{JsonDocument.One}]",
|
||||
"Documents not ordered correctly");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
})
|
||||
]),
|
||||
TestList("WriteFirstByFields",
|
||||
[
|
||||
TestCase("succeeds when a document is found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteFirstByFields(SqliteDb.TableName, writer, FieldMatch.Any,
|
||||
[Field.Equal("Value", "another")]);
|
||||
Expect.equal(StreamText(stream), JsonDocument.Two, "The incorrect document was returned");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when multiple documents are found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteFirstByFields(SqliteDb.TableName, writer, FieldMatch.Any,
|
||||
[Field.Equal("Sub.Foo", "green")]);
|
||||
var json = StreamText(stream);
|
||||
Expect.notEqual(json, "{}", "There should have been a document returned");
|
||||
VerifyAny(json, [JsonDocument.Two, JsonDocument.Four]);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when a document is not found", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteFirstByFields(SqliteDb.TableName, writer, FieldMatch.Any,
|
||||
[Field.Equal("Value", "absent")]);
|
||||
VerifyNoDoc(StreamText(stream));
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
})
|
||||
]),
|
||||
TestList("WriteFirstByFieldsOrdered",
|
||||
[
|
||||
TestCase("succeeds when sorting ascending", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteFirstByFieldsOrdered(SqliteDb.TableName, writer, FieldMatch.Any,
|
||||
[Field.Equal("Sub.Foo", "green")], [Field.Named("Sub.Bar")]);
|
||||
Expect.equal(StreamText(stream), JsonDocument.Two, "An incorrect document was returned");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
}),
|
||||
TestCase("succeeds when sorting descending", async () =>
|
||||
{
|
||||
await using var db = await SqliteDb.BuildDb();
|
||||
await LoadDocs();
|
||||
|
||||
using MemoryStream stream = new();
|
||||
var writer = WriteStream(stream);
|
||||
try
|
||||
{
|
||||
await Json.WriteFirstByFieldsOrdered(SqliteDb.TableName, writer, FieldMatch.Any,
|
||||
[Field.Equal("Sub.Foo", "green")], [Field.Named("Sub.Bar DESC")]);
|
||||
Expect.equal(StreamText(stream), JsonDocument.Four, "An incorrect document was returned");
|
||||
}
|
||||
finally
|
||||
{
|
||||
await writer.CompleteAsync();
|
||||
}
|
||||
})
|
||||
])
|
||||
]);
|
||||
|
||||
/// <summary>
|
||||
/// Integration tests for the Update module of the SQLite library
|
||||
/// </summary>
|
||||
@@ -1006,6 +1763,7 @@ public static class SqliteCSharpTests
|
||||
CountTests,
|
||||
ExistsTests,
|
||||
FindTests,
|
||||
JsonTests,
|
||||
UpdateTests,
|
||||
PatchTests,
|
||||
RemoveFieldsTests,
|
||||
|
||||
@@ -18,7 +18,7 @@ public class JsonDocument
|
||||
public string Value { get; set; } = "";
|
||||
public int NumValue { get; set; } = 0;
|
||||
public SubDocument? Sub { get; set; } = null;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// A set of documents used for integration tests
|
||||
/// </summary>
|
||||
@@ -30,6 +30,22 @@ public class JsonDocument
|
||||
new() { Id = "four", Value = "purple", NumValue = 17, Sub = new() { Foo = "green", Bar = "red" } },
|
||||
new() { Id = "five", Value = "purple", NumValue = 18 }
|
||||
];
|
||||
|
||||
/// <summary>The JSON for document ID `one`</summary>
|
||||
public static string One = """{"Id":"one","Value":"FIRST!","NumValue":0,"Sub":null}""";
|
||||
|
||||
/// <summary>The JSON for document ID `two`</summary>
|
||||
public static string Two = """{"Id":"two","Value":"another","NumValue":10,"Sub":{"Foo":"green","Bar":"blue"}}""";
|
||||
|
||||
/// <summary>The JSON for document ID `three`</summary>
|
||||
public static string Three = """{"Id":"three","Value":"","NumValue":4,"Sub":null}""";
|
||||
|
||||
/// <summary>The JSON for document ID `four`</summary>
|
||||
public static string Four = """{"Id":"four","Value":"purple","NumValue":17,"Sub":{"Foo":"green","Bar":"red"}}""";
|
||||
|
||||
/// <summary>The JSON for document ID `five`</summary>
|
||||
public static string Five = """{"Id":"five","Value":"purple","NumValue":18,"Sub":null}""";
|
||||
|
||||
}
|
||||
|
||||
public class ArrayDocument
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
module CommonTests
|
||||
|
||||
open System.IO
|
||||
open System.IO.Pipelines
|
||||
open BitBadger.Documents
|
||||
open Expecto
|
||||
|
||||
@@ -484,6 +486,81 @@ let queryTests = testList "Query" [
|
||||
]
|
||||
]
|
||||
|
||||
let private streamText (stream: Stream) =
|
||||
stream.Position <- 0L
|
||||
use reader = new StreamReader(stream)
|
||||
reader.ReadToEnd()
|
||||
|
||||
/// Unit tests for the PipeWriter module
|
||||
let pipeWriterTests = testList "Extensions.PipeWriter" [
|
||||
testList "writeString" [
|
||||
testTask "succeeds when writer is open" {
|
||||
use stream = new MemoryStream()
|
||||
let writer = PipeWriter.Create(stream, StreamPipeWriterOptions(leaveOpen = true))
|
||||
try
|
||||
let! result = PipeWriter.writeString writer "abc"
|
||||
Expect.isTrue result "The write operation should have been successful"
|
||||
Expect.equal (streamText stream) "abc" "The string was not written correctly"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when writer is completed" {
|
||||
use stream = new MemoryStream()
|
||||
let writer = PipeWriter.Create(stream, StreamPipeWriterOptions(leaveOpen = true))
|
||||
do! writer.CompleteAsync()
|
||||
|
||||
let! result = PipeWriter.writeString writer "abc"
|
||||
Expect.isFalse result "The write operation should have returned false"
|
||||
Expect.equal (streamText stream) "" "No text should have been written"
|
||||
}
|
||||
]
|
||||
testList "writeStrings" [
|
||||
testTask "succeeds with no strings" {
|
||||
use stream = new MemoryStream()
|
||||
let writer = PipeWriter.Create(stream, StreamPipeWriterOptions(leaveOpen = true))
|
||||
try
|
||||
do! PipeWriter.writeStrings writer []
|
||||
Expect.equal (streamText stream) "[]" "An empty sequence of strings was not written correctly"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds with one strings" {
|
||||
use stream = new MemoryStream()
|
||||
let writer = PipeWriter.Create(stream, StreamPipeWriterOptions(leaveOpen = true))
|
||||
try
|
||||
do! PipeWriter.writeStrings writer [ "le-test" ]
|
||||
Expect.equal (streamText stream) "[le-test]" "A sequence of one string was not written correctly"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds with many strings" {
|
||||
use stream = new MemoryStream()
|
||||
let writer = PipeWriter.Create(stream, StreamPipeWriterOptions(leaveOpen = true))
|
||||
try
|
||||
do! PipeWriter.writeStrings writer [ "z"; "y"; "x"; "c"; "b"; "a" ]
|
||||
Expect.equal (streamText stream) "[z,y,x,c,b,a]" "A sequence of many strings was not written correctly"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when the writer is completed early" {
|
||||
use stream = new MemoryStream()
|
||||
let writer = PipeWriter.Create(stream, StreamPipeWriterOptions(leaveOpen = true))
|
||||
let items = seq {
|
||||
"a"
|
||||
"b"
|
||||
"c"
|
||||
writer.Complete()
|
||||
"d"
|
||||
"e"
|
||||
"f"
|
||||
}
|
||||
|
||||
do! PipeWriter.writeStrings writer items
|
||||
Expect.equal (streamText stream) "[a,b,c" "The writing should have stopped when the writer completed"
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Tests which do not hit the database
|
||||
let all = testList "Common" [
|
||||
comparisonTests
|
||||
@@ -492,5 +569,6 @@ let all = testList "Common" [
|
||||
parameterNameTests
|
||||
autoIdTests
|
||||
queryTests
|
||||
pipeWriterTests
|
||||
testSequenced configurationTests
|
||||
]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,7 @@
|
||||
module SqliteTests
|
||||
|
||||
open System.IO
|
||||
open System.IO.Pipelines
|
||||
open System.Text.Json
|
||||
open BitBadger.Documents
|
||||
open BitBadger.Documents.Sqlite
|
||||
@@ -135,6 +137,17 @@ let loadDocs () = backgroundTask {
|
||||
for doc in testDocuments do do! insert SqliteDb.TableName doc
|
||||
}
|
||||
|
||||
/// Set up a stream writer for a test
|
||||
let writeStream (stream: Stream) =
|
||||
PipeWriter.Create(stream, StreamPipeWriterOptions(leaveOpen = true))
|
||||
|
||||
/// Get the text of the given stream
|
||||
let streamText (stream: Stream) =
|
||||
stream.Position <- 0L
|
||||
use reader = new StreamReader(stream)
|
||||
reader.ReadToEnd()
|
||||
|
||||
|
||||
/// Integration tests for the Configuration module of the SQLite library
|
||||
let configurationTests = testList "Configuration" [
|
||||
test "useConnectionString / connectionString succeed" {
|
||||
@@ -151,6 +164,89 @@ let configurationTests = testList "Configuration" [
|
||||
|
||||
/// Integration tests for the Custom module of the SQLite library
|
||||
let customTests = testList "Custom" [
|
||||
testList "list" [
|
||||
testTask "succeeds when data is found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! docs = Custom.list (Query.find SqliteDb.TableName) [] fromData<JsonDocument>
|
||||
Expect.hasCountOf docs 5u (fun _ -> true) "There should have been 5 documents returned"
|
||||
}
|
||||
testTask "succeeds when data is not found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! docs =
|
||||
Custom.list
|
||||
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value"
|
||||
[ SqliteParameter("@value", 100) ]
|
||||
fromData<JsonDocument>
|
||||
Expect.isEmpty docs "There should have been no documents returned"
|
||||
}
|
||||
]
|
||||
testList "jsonArray" [
|
||||
testTask "succeeds when data is found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Custom.jsonArray (Query.find SqliteDb.TableName) [] jsonFromData
|
||||
Expect.stringStarts json "[" "The JSON array should have started with `[`"
|
||||
Expect.stringContains json JsonDocument.one "Document ID `one` should have been found"
|
||||
Expect.stringContains json JsonDocument.two "Document ID `two` should have been found"
|
||||
Expect.stringContains json JsonDocument.three "Document ID `three` should have been found"
|
||||
Expect.stringContains json JsonDocument.four "Document ID `four` should have been found"
|
||||
Expect.stringContains json JsonDocument.five "Document ID `five` should have been found"
|
||||
Expect.stringEnds json "]" "The JSON array should have ended with `[`"
|
||||
}
|
||||
testTask "succeeds when data is not found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! docs =
|
||||
Custom.jsonArray
|
||||
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value"
|
||||
[ SqliteParameter("@value", 100) ]
|
||||
jsonFromData
|
||||
Expect.equal docs "[]" "There should have been no documents returned"
|
||||
}
|
||||
]
|
||||
testList "writeJsonArray" [
|
||||
testTask "succeeds when data is found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Custom.writeJsonArray (Query.find SqliteDb.TableName) [] writer jsonFromData
|
||||
let json = streamText stream
|
||||
Expect.stringStarts json "[" "The JSON array should have started with `[`"
|
||||
Expect.stringContains json JsonDocument.one "Document ID `one` should have been found"
|
||||
Expect.stringContains json JsonDocument.two "Document ID `two` should have been found"
|
||||
Expect.stringContains json JsonDocument.three "Document ID `three` should have been found"
|
||||
Expect.stringContains json JsonDocument.four "Document ID `four` should have been found"
|
||||
Expect.stringContains json JsonDocument.five "Document ID `five` should have been found"
|
||||
Expect.stringEnds json "]" "The JSON array should have ended with `[`"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when data is not found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Custom.writeJsonArray
|
||||
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value"
|
||||
[ SqliteParameter("@value", 100) ]
|
||||
writer
|
||||
jsonFromData
|
||||
Expect.equal (streamText stream) "[]" "There should have been no documents returned"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
]
|
||||
testList "single" [
|
||||
testTask "succeeds when a row is found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
@@ -176,24 +272,28 @@ let customTests = testList "Custom" [
|
||||
Expect.isNone doc "There should not have been a document returned"
|
||||
}
|
||||
]
|
||||
testList "list" [
|
||||
testTask "succeeds when data is found" {
|
||||
testList "jsonSingle" [
|
||||
testTask "succeeds when a row is found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! docs = Custom.list (Query.find SqliteDb.TableName) [] fromData<JsonDocument>
|
||||
Expect.hasCountOf docs 5u (fun _ -> true) "There should have been 5 documents returned"
|
||||
let! json =
|
||||
Custom.jsonSingle
|
||||
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id"
|
||||
[ SqliteParameter("@id", "one") ]
|
||||
jsonFromData
|
||||
Expect.equal json JsonDocument.one "The JSON document is incorrect"
|
||||
}
|
||||
testTask "succeeds when data is not found" {
|
||||
testTask "succeeds when a row is not found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! docs =
|
||||
Custom.list
|
||||
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'NumValue' > @value"
|
||||
[ SqliteParameter("@value", 100) ]
|
||||
fromData<JsonDocument>
|
||||
Expect.isEmpty docs "There should have been no documents returned"
|
||||
let! json =
|
||||
Custom.jsonSingle
|
||||
$"SELECT data FROM {SqliteDb.TableName} WHERE data ->> 'Id' = @id"
|
||||
[ SqliteParameter("@id", "eighty") ]
|
||||
jsonFromData
|
||||
Expect.equal json "{}" "There should not have been a document returned"
|
||||
}
|
||||
]
|
||||
testList "nonQuery" [
|
||||
@@ -653,6 +753,533 @@ let findTests = testList "Find" [
|
||||
]
|
||||
]
|
||||
|
||||
/// Verify a JSON array begins with "[" and ends with "]"
|
||||
let private verifyBeginEnd json =
|
||||
Expect.stringStarts json "[" "The array should have started with `[`"
|
||||
Expect.stringEnds json "]" "The array should have ended with `]`"
|
||||
|
||||
/// Verify an empty JSON array
|
||||
let private verifyEmpty json =
|
||||
Expect.equal json "[]" "There should be no documents returned"
|
||||
|
||||
/// Verify an empty JSON document
|
||||
let private verifyNoDoc json =
|
||||
Expect.equal json "{}" "There should be no document returned"
|
||||
|
||||
/// Verify the presence of any of the given documents in the given JSON
|
||||
let private verifyAny (json: string) (docs: string list) =
|
||||
match docs |> List.tryFind json.Contains with
|
||||
| Some _ -> ()
|
||||
| None ->
|
||||
let theDocs = docs |> String.concat " | "
|
||||
Expect.isTrue false $"Could not find any of |{theDocs}| in {json}"
|
||||
|
||||
/// Integration tests for the Json module of the SQLite library
|
||||
let jsonTests = testList "Json" [
|
||||
testList "all" [
|
||||
testTask "succeeds when there is data" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
|
||||
do! insert SqliteDb.TableName { Foo = "one"; Bar = "two" }
|
||||
do! insert SqliteDb.TableName { Foo = "three"; Bar = "four" }
|
||||
do! insert SqliteDb.TableName { Foo = "five"; Bar = "six" }
|
||||
|
||||
let! json = Json.all SqliteDb.TableName
|
||||
verifyBeginEnd json
|
||||
Expect.stringContains json """{"Foo":"one","Bar":"two"}""" "The first document was not found"
|
||||
Expect.stringContains json """{"Foo":"three","Bar":"four"}""" "The second document was not found"
|
||||
Expect.stringContains json """{"Foo":"five","Bar":"six"}""" "The third document was not found"
|
||||
}
|
||||
testTask "succeeds when there is no data" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
let! json = Json.all SqliteDb.TableName
|
||||
verifyEmpty json
|
||||
}
|
||||
]
|
||||
testList "allOrdered" [
|
||||
testTask "succeeds when ordering numerically" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.allOrdered SqliteDb.TableName [ Field.Named "n:NumValue" ]
|
||||
Expect.equal
|
||||
json
|
||||
$"[{JsonDocument.one},{JsonDocument.three},{JsonDocument.two},{JsonDocument.four},{JsonDocument.five}]"
|
||||
"The documents were not ordered correctly"
|
||||
}
|
||||
testTask "succeeds when ordering numerically descending" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.allOrdered SqliteDb.TableName [ Field.Named "n:NumValue DESC" ]
|
||||
Expect.equal
|
||||
json
|
||||
$"[{JsonDocument.five},{JsonDocument.four},{JsonDocument.two},{JsonDocument.three},{JsonDocument.one}]"
|
||||
"The documents were not ordered correctly"
|
||||
}
|
||||
testTask "succeeds when ordering alphabetically" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.allOrdered SqliteDb.TableName [ Field.Named "Id DESC" ]
|
||||
Expect.equal
|
||||
json
|
||||
$"[{JsonDocument.two},{JsonDocument.three},{JsonDocument.one},{JsonDocument.four},{JsonDocument.five}]"
|
||||
"The documents were not ordered correctly"
|
||||
}
|
||||
]
|
||||
testList "byId" [
|
||||
testTask "succeeds when a document is found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.byId SqliteDb.TableName "two"
|
||||
Expect.equal json JsonDocument.two "The incorrect document was returned"
|
||||
}
|
||||
testTask "succeeds when a document is not found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.byId SqliteDb.TableName "three hundred eighty-seven"
|
||||
verifyNoDoc json
|
||||
}
|
||||
]
|
||||
testList "byFields" [
|
||||
testTask "succeeds when documents are found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.byFields SqliteDb.TableName Any [ Field.Greater "NumValue" 15 ]
|
||||
verifyBeginEnd json
|
||||
Expect.stringContains json JsonDocument.four "Document `four` should have been returned"
|
||||
Expect.stringContains json JsonDocument.five "Document `five` should have been returned"
|
||||
}
|
||||
testTask "succeeds when documents are found using IN with numeric field" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.byFields SqliteDb.TableName All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ]
|
||||
Expect.equal json $"[{JsonDocument.three}]" "There should have been one document returned"
|
||||
}
|
||||
testTask "succeeds when documents are not found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.byFields SqliteDb.TableName Any [ Field.Greater "NumValue" 100 ]
|
||||
verifyEmpty json
|
||||
}
|
||||
testTask "succeeds for InArray when matching documents exist" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! Definition.ensureTable SqliteDb.TableName
|
||||
for doc in ArrayDocument.TestDocuments do do! insert SqliteDb.TableName doc
|
||||
|
||||
let! json = Json.byFields SqliteDb.TableName All [ Field.InArray "Values" SqliteDb.TableName [ "c" ] ]
|
||||
verifyBeginEnd json
|
||||
Expect.stringContains
|
||||
json """{"Id":"first","Values":["a","b","c"]}""" "Document `first` should have been returned"
|
||||
Expect.stringContains
|
||||
json """{"Id":"second","Values":["c","d","e"]}""" "Document `second` should have been returned"
|
||||
}
|
||||
testTask "succeeds for InArray when no matching documents exist" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! Definition.ensureTable SqliteDb.TableName
|
||||
for doc in ArrayDocument.TestDocuments do do! insert SqliteDb.TableName doc
|
||||
|
||||
let! json = Json.byFields SqliteDb.TableName All [ Field.InArray "Values" SqliteDb.TableName [ "j" ] ]
|
||||
verifyEmpty json
|
||||
}
|
||||
]
|
||||
testList "byFieldsOrdered" [
|
||||
testTask "succeeds when sorting ascending" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.byFieldsOrdered SqliteDb.TableName Any [ Field.Greater "NumValue" 15 ] [ Field.Named "Id" ]
|
||||
Expect.equal json $"[{JsonDocument.five},{JsonDocument.four}]" "Incorrect documents were returned"
|
||||
}
|
||||
testTask "succeeds when sorting descending" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json =
|
||||
Json.byFieldsOrdered SqliteDb.TableName Any [ Field.Greater "NumValue" 15 ] [ Field.Named "Id DESC" ]
|
||||
Expect.equal json $"[{JsonDocument.four},{JsonDocument.five}]" "Incorrect documents were returned"
|
||||
}
|
||||
testTask "succeeds when sorting case-sensitively" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json =
|
||||
Json.byFieldsOrdered SqliteDb.TableName All [ Field.LessOrEqual "NumValue" 10 ] [ Field.Named "Value" ]
|
||||
Expect.equal
|
||||
json $"[{JsonDocument.three},{JsonDocument.one},{JsonDocument.two}]" "Documents not ordered correctly"
|
||||
}
|
||||
testTask "succeeds when sorting case-insensitively" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json =
|
||||
Json.byFieldsOrdered
|
||||
SqliteDb.TableName All [ Field.LessOrEqual "NumValue" 10 ] [ Field.Named "i:Value" ]
|
||||
Expect.equal
|
||||
json $"[{JsonDocument.three},{JsonDocument.two},{JsonDocument.one}]" "Documents not ordered correctly"
|
||||
}
|
||||
]
|
||||
testList "firstByFields" [
|
||||
testTask "succeeds when a document is found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.firstByFields SqliteDb.TableName Any [ Field.Equal "Value" "another" ]
|
||||
Expect.equal json JsonDocument.two "The incorrect document was returned"
|
||||
}
|
||||
testTask "succeeds when multiple documents are found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.firstByFields SqliteDb.TableName Any [ Field.Equal "Sub.Foo" "green" ]
|
||||
Expect.notEqual json "{}" "There should have been a document returned"
|
||||
verifyAny json [ JsonDocument.two; JsonDocument.four ]
|
||||
}
|
||||
testTask "succeeds when a document is not found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json = Json.firstByFields SqliteDb.TableName Any [ Field.Equal "Value" "absent" ]
|
||||
verifyNoDoc json
|
||||
}
|
||||
]
|
||||
testList "firstByFieldsOrdered" [
|
||||
testTask "succeeds when sorting ascending" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json =
|
||||
Json.firstByFieldsOrdered
|
||||
SqliteDb.TableName Any [ Field.Equal "Sub.Foo" "green" ] [ Field.Named "Sub.Bar" ]
|
||||
Expect.equal json JsonDocument.two "An incorrect document was returned"
|
||||
}
|
||||
testTask "succeeds when sorting descending" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
let! json =
|
||||
Json.firstByFieldsOrdered
|
||||
SqliteDb.TableName Any [ Field.Equal "Sub.Foo" "green" ] [ Field.Named "Sub.Bar DESC" ]
|
||||
Expect.equal json JsonDocument.four "An incorrect document was returned"
|
||||
}
|
||||
]
|
||||
testList "writeAll" [
|
||||
testTask "succeeds when there is data" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
|
||||
do! insert SqliteDb.TableName { Foo = "one"; Bar = "two" }
|
||||
do! insert SqliteDb.TableName { Foo = "three"; Bar = "four" }
|
||||
do! insert SqliteDb.TableName { Foo = "five"; Bar = "six" }
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeAll SqliteDb.TableName writer
|
||||
let json = streamText stream
|
||||
verifyBeginEnd json
|
||||
Expect.stringContains json """{"Foo":"one","Bar":"two"}""" "The first document was not found"
|
||||
Expect.stringContains json """{"Foo":"three","Bar":"four"}""" "The second document was not found"
|
||||
Expect.stringContains json """{"Foo":"five","Bar":"six"}""" "The third document was not found"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when there is no data" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeAll SqliteDb.TableName writer
|
||||
verifyEmpty (streamText stream)
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
]
|
||||
testList "writeAllOrdered" [
|
||||
testTask "succeeds when ordering numerically" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeAllOrdered SqliteDb.TableName writer [ Field.Named "n:NumValue" ]
|
||||
Expect.equal
|
||||
(streamText stream)
|
||||
$"[{JsonDocument.one},{JsonDocument.three},{JsonDocument.two},{JsonDocument.four},{JsonDocument.five}]"
|
||||
"The documents were not ordered correctly"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when ordering numerically descending" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeAllOrdered SqliteDb.TableName writer [ Field.Named "n:NumValue DESC" ]
|
||||
Expect.equal
|
||||
(streamText stream)
|
||||
$"[{JsonDocument.five},{JsonDocument.four},{JsonDocument.two},{JsonDocument.three},{JsonDocument.one}]"
|
||||
"The documents were not ordered correctly"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when ordering alphabetically" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeAllOrdered SqliteDb.TableName writer [ Field.Named "Id DESC" ]
|
||||
Expect.equal
|
||||
(streamText stream)
|
||||
$"[{JsonDocument.two},{JsonDocument.three},{JsonDocument.one},{JsonDocument.four},{JsonDocument.five}]"
|
||||
"The documents were not ordered correctly"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
]
|
||||
testList "writeById" [
|
||||
testTask "succeeds when a document is found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeById SqliteDb.TableName writer "two"
|
||||
Expect.equal (streamText stream) JsonDocument.two "The incorrect document was returned"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when a document is not found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeById SqliteDb.TableName writer "three hundred eighty-seven"
|
||||
verifyNoDoc (streamText stream)
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
]
|
||||
testList "writeByFields" [
|
||||
testTask "succeeds when documents are found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeByFields SqliteDb.TableName writer Any [ Field.Greater "NumValue" 15 ]
|
||||
let json = streamText stream
|
||||
verifyBeginEnd json
|
||||
Expect.stringContains json JsonDocument.four "Document `four` should have been returned"
|
||||
Expect.stringContains json JsonDocument.five "Document `five` should have been returned"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when documents are found using IN with numeric field" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeByFields SqliteDb.TableName writer All [ Field.In "NumValue" [ 2; 4; 6; 8 ] ]
|
||||
Expect.equal
|
||||
(streamText stream) $"[{JsonDocument.three}]" "There should have been one document returned"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when documents are not found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeByFields SqliteDb.TableName writer Any [ Field.Greater "NumValue" 100 ]
|
||||
verifyEmpty (streamText stream)
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds for InArray when matching documents exist" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! Definition.ensureTable SqliteDb.TableName
|
||||
for doc in ArrayDocument.TestDocuments do do! insert SqliteDb.TableName doc
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeByFields
|
||||
SqliteDb.TableName writer All [ Field.InArray "Values" SqliteDb.TableName [ "c" ] ]
|
||||
let json = streamText stream
|
||||
verifyBeginEnd json
|
||||
Expect.stringContains
|
||||
json """{"Id":"first","Values":["a","b","c"]}""" "Document `first` should have been returned"
|
||||
Expect.stringContains
|
||||
json """{"Id":"second","Values":["c","d","e"]}""" "Document `second` should have been returned"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds for InArray when no matching documents exist" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! Definition.ensureTable SqliteDb.TableName
|
||||
for doc in ArrayDocument.TestDocuments do do! insert SqliteDb.TableName doc
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeByFields
|
||||
SqliteDb.TableName writer All [ Field.InArray "Values" SqliteDb.TableName [ "j" ] ]
|
||||
verifyEmpty (streamText stream)
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
]
|
||||
testList "writeByFieldsOrdered" [
|
||||
testTask "succeeds when sorting ascending" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeByFieldsOrdered
|
||||
SqliteDb.TableName writer Any [ Field.Greater "NumValue" 15 ] [ Field.Named "Id" ]
|
||||
Expect.equal
|
||||
(streamText stream) $"[{JsonDocument.five},{JsonDocument.four}]" "Incorrect documents were returned"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when sorting descending" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeByFieldsOrdered
|
||||
SqliteDb.TableName writer Any [ Field.Greater "NumValue" 15 ] [ Field.Named "Id DESC" ]
|
||||
Expect.equal
|
||||
(streamText stream) $"[{JsonDocument.four},{JsonDocument.five}]" "Incorrect documents were returned"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when sorting case-sensitively" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeByFieldsOrdered
|
||||
SqliteDb.TableName writer All [ Field.LessOrEqual "NumValue" 10 ] [ Field.Named "Value" ]
|
||||
Expect.equal
|
||||
(streamText stream)
|
||||
$"[{JsonDocument.three},{JsonDocument.one},{JsonDocument.two}]"
|
||||
"Documents not ordered correctly"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when sorting case-insensitively" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeByFieldsOrdered
|
||||
SqliteDb.TableName writer All [ Field.LessOrEqual "NumValue" 10 ] [ Field.Named "i:Value" ]
|
||||
Expect.equal
|
||||
(streamText stream)
|
||||
$"[{JsonDocument.three},{JsonDocument.two},{JsonDocument.one}]"
|
||||
"Documents not ordered correctly"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
]
|
||||
testList "writeFirstByFields" [
|
||||
testTask "succeeds when a document is found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeFirstByFields SqliteDb.TableName writer Any [ Field.Equal "Value" "another" ]
|
||||
Expect.equal (streamText stream) JsonDocument.two "The incorrect document was returned"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when multiple documents are found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeFirstByFields SqliteDb.TableName writer Any [ Field.Equal "Sub.Foo" "green" ]
|
||||
let json = streamText stream
|
||||
Expect.notEqual json "{}" "There should have been a document returned"
|
||||
verifyAny json [ JsonDocument.two; JsonDocument.four ]
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when a document is not found" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeFirstByFields SqliteDb.TableName writer Any [ Field.Equal "Value" "absent" ]
|
||||
verifyNoDoc (streamText stream)
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
]
|
||||
testList "writeFirstByFieldsOrdered" [
|
||||
testTask "succeeds when sorting ascending" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeFirstByFieldsOrdered
|
||||
SqliteDb.TableName writer Any [ Field.Equal "Sub.Foo" "green" ] [ Field.Named "Sub.Bar" ]
|
||||
Expect.equal (streamText stream) JsonDocument.two "An incorrect document was returned"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
testTask "succeeds when sorting descending" {
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
use stream = new MemoryStream()
|
||||
let writer = writeStream stream
|
||||
try
|
||||
do! Json.writeFirstByFieldsOrdered
|
||||
SqliteDb.TableName writer Any [ Field.Equal "Sub.Foo" "green" ] [ Field.Named "Sub.Bar DESC" ]
|
||||
Expect.equal (streamText stream) JsonDocument.four "An incorrect document was returned"
|
||||
finally
|
||||
writer.Complete()
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
/// Integration tests for the Update module of the SQLite library
|
||||
let updateTests = testList "Update" [
|
||||
testList "byId" [
|
||||
@@ -682,7 +1309,7 @@ let updateTests = testList "Update" [
|
||||
use! db = SqliteDb.BuildDb()
|
||||
do! loadDocs ()
|
||||
|
||||
do! Update.byFunc SqliteDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
|
||||
do! Update.byFunc SqliteDb.TableName _.Id { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
|
||||
let! after = Find.byId<string, JsonDocument> SqliteDb.TableName "one"
|
||||
Expect.isSome after "There should have been a document returned post-update"
|
||||
Expect.equal
|
||||
@@ -697,7 +1324,7 @@ let updateTests = testList "Update" [
|
||||
Expect.isEmpty before "There should have been no documents returned"
|
||||
|
||||
// This not raising an exception is the test
|
||||
do! Update.byFunc SqliteDb.TableName (_.Id) { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
|
||||
do! Update.byFunc SqliteDb.TableName _.Id { Id = "one"; Value = "le un"; NumValue = 1; Sub = None }
|
||||
}
|
||||
]
|
||||
]
|
||||
@@ -854,6 +1481,7 @@ let all = testList "Sqlite" [
|
||||
countTests
|
||||
existsTests
|
||||
findTests
|
||||
jsonTests
|
||||
updateTests
|
||||
patchTests
|
||||
removeFieldsTests
|
||||
|
||||
@@ -26,6 +26,22 @@ type JsonDocument =
|
||||
NumValue: int
|
||||
Sub: SubDocument option }
|
||||
|
||||
module JsonDocument =
|
||||
/// The JSON for document ID `one`
|
||||
let one = """{"Id":"one","Value":"FIRST!","NumValue":0,"Sub":null}"""
|
||||
|
||||
/// The JSON for document ID `two`
|
||||
let two = """{"Id":"two","Value":"another","NumValue":10,"Sub":{"Foo":"green","Bar":"blue"}}"""
|
||||
|
||||
/// The JSON for document ID `three`
|
||||
let three = """{"Id":"three","Value":"","NumValue":4,"Sub":null}"""
|
||||
|
||||
/// The JSON for document ID `four`
|
||||
let four = """{"Id":"four","Value":"purple","NumValue":17,"Sub":{"Foo":"green","Bar":"red"}}"""
|
||||
|
||||
/// The JSON for document ID `five`
|
||||
let five = """{"Id":"five","Value":"purple","NumValue":18,"Sub":null}"""
|
||||
|
||||
|
||||
/// An empty JsonDocument
|
||||
let emptyDoc = { Id = ""; Value = ""; NumValue = 0; Sub = None }
|
||||
|
||||
Reference in New Issue
Block a user