Tweaks prior to release
This commit is contained in:
parent
5bb9eec4a8
commit
3b7176005c
@ -4,26 +4,37 @@ open System.Security.Cryptography
|
||||
|
||||
/// The types of comparisons available for JSON fields
|
||||
type Comparison =
|
||||
|
||||
/// Equals (=)
|
||||
| Equal of Value: obj
|
||||
|
||||
/// Greater Than (>)
|
||||
| Greater of Value: obj
|
||||
|
||||
/// Greater Than or Equal To (>=)
|
||||
| GreaterOrEqual of Value: obj
|
||||
|
||||
/// Less Than (<)
|
||||
| Less of Value: obj
|
||||
|
||||
/// Less Than or Equal To (<=)
|
||||
| LessOrEqual of Value: obj
|
||||
|
||||
/// Not Equal to (<>)
|
||||
| NotEqual of Value: obj
|
||||
|
||||
/// Between (BETWEEN)
|
||||
| Between of Min: obj * Max: obj
|
||||
|
||||
/// In (IN)
|
||||
| In of Values: obj seq
|
||||
|
||||
/// In Array (PostgreSQL: |?, SQLite: EXISTS / json_each / IN)
|
||||
| InArray of Table: string * Values: obj seq
|
||||
|
||||
/// Exists (IS NOT NULL)
|
||||
| Exists
|
||||
|
||||
/// Does Not Exist (IS NULL)
|
||||
| NotExists
|
||||
|
||||
@ -53,26 +64,29 @@ type Dialect =
|
||||
/// The format in which an element of a JSON field should be extracted
|
||||
[<Struct>]
|
||||
type FieldFormat =
|
||||
|
||||
/// Use ->> or #>>; extracts a text (PostgreSQL) or SQL (SQLite) value
|
||||
| AsSql
|
||||
|
||||
/// Use -> or #>; extracts a JSONB (PostgreSQL) or JSON (SQLite) value
|
||||
| AsJson
|
||||
|
||||
|
||||
/// Criteria for a field WHERE clause
|
||||
type Field =
|
||||
{ /// The name of the field
|
||||
Name: string
|
||||
type Field = {
|
||||
|
||||
/// The comparison for the field
|
||||
Comparison: Comparison
|
||||
/// The name of the field
|
||||
Name: string
|
||||
|
||||
/// The name of the parameter for this field
|
||||
ParameterName: string option
|
||||
/// The comparison for the field
|
||||
Comparison: Comparison
|
||||
|
||||
/// The table qualifier for this field
|
||||
Qualifier: string option }
|
||||
with
|
||||
/// The name of the parameter for this field
|
||||
ParameterName: string option
|
||||
|
||||
/// The table qualifier for this field
|
||||
Qualifier: string option
|
||||
} with
|
||||
|
||||
/// Create a comparison against a field
|
||||
static member Where name (comparison: Comparison) =
|
||||
@ -190,8 +204,10 @@ with
|
||||
/// How fields should be matched
|
||||
[<Struct>]
|
||||
type FieldMatch =
|
||||
|
||||
/// Any field matches (OR)
|
||||
| Any
|
||||
|
||||
/// All fields match (AND)
|
||||
| All
|
||||
|
||||
@ -202,6 +218,7 @@ type FieldMatch =
|
||||
|
||||
/// Derive parameter names (each instance wraps a counter to uniquely name anonymous fields)
|
||||
type ParameterName() =
|
||||
|
||||
/// The counter for the next field value
|
||||
let mutable currentIdx = -1
|
||||
|
||||
@ -213,35 +230,30 @@ type ParameterName() =
|
||||
currentIdx <- currentIdx + 1
|
||||
$"@field{currentIdx}"
|
||||
|
||||
#if NET6_0
|
||||
open System.Text
|
||||
#endif
|
||||
|
||||
/// Automatically-generated document ID strategies
|
||||
[<Struct>]
|
||||
type AutoId =
|
||||
|
||||
/// No automatic IDs will be generated
|
||||
| Disabled
|
||||
|
||||
/// Generate a MAX-plus-1 numeric value for documents
|
||||
| Number
|
||||
|
||||
/// Generate a GUID for each document (as a lowercase, no-dashes, 32-character string)
|
||||
| Guid
|
||||
|
||||
/// Generate a random string of hexadecimal characters for each document
|
||||
| RandomString
|
||||
with
|
||||
/// Generate a GUID string
|
||||
static member GenerateGuid () =
|
||||
static member GenerateGuid() =
|
||||
System.Guid.NewGuid().ToString "N"
|
||||
|
||||
/// Generate a string of random hexadecimal characters
|
||||
static member GenerateRandomString (length: int) =
|
||||
#if NET8_0_OR_GREATER
|
||||
static member GenerateRandomString(length: int) =
|
||||
RandomNumberGenerator.GetHexString(length, lowercase = true)
|
||||
#else
|
||||
RandomNumberGenerator.GetBytes((length / 2) + 1)
|
||||
|> Array.fold (fun (str: StringBuilder) byt -> str.Append(byt.ToString "x2")) (StringBuilder length)
|
||||
|> function it -> it.Length <- length; it.ToString()
|
||||
#endif
|
||||
|
||||
/// Does the given document need an automatic ID generated?
|
||||
static member NeedsAutoId<'T> strategy (document: 'T) idProp =
|
||||
|
@ -7,6 +7,7 @@ This package provides common definitions and functionality for `BitBadger.Docume
|
||||
## Features
|
||||
|
||||
- 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
|
||||
|
@ -6,17 +6,14 @@
|
||||
<AssemblyVersion>4.0.0.0</AssemblyVersion>
|
||||
<FileVersion>4.0.0.0</FileVersion>
|
||||
<VersionPrefix>4.0.0</VersionPrefix>
|
||||
<VersionSuffix>rc5</VersionSuffix>
|
||||
<PackageReleaseNotes>From v3.1: (see project site for breaking changes and compatibility)
|
||||
- Change ByField to ByFields
|
||||
- Support dot-access to nested document fields
|
||||
- Add Find*Ordered functions/methods
|
||||
|
||||
Release Candidate Changes:
|
||||
- from v4-rc4: Field construction functions are now generic.
|
||||
- from v4-rc3: Add In/InArray field comparisons, revamp internal comparison handling.
|
||||
- from v4-rc2: preserve additional ORDER BY qualifiers.
|
||||
- from v4-rc1: add case-insensitive ordering.</PackageReleaseNotes>
|
||||
- Add case-insensitive ordering (as of rc2)
|
||||
- Preserve additional ORDER BY qualifiers (as of rc3)
|
||||
- Add In / InArray comparisons (as of rc4)
|
||||
- Field construction functions are generic (as of rc5)</PackageReleaseNotes>
|
||||
<Authors>danieljsummers</Authors>
|
||||
<Company>Bit Badger Solutions</Company>
|
||||
<PackageReadmeFile>README.md</PackageReadmeFile>
|
||||
|
@ -14,8 +14,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Npgsql" Version="9.0.1" />
|
||||
<PackageReference Include="Npgsql.FSharp" Version="5.7.0" />
|
||||
<PackageReference Include="Npgsql" Version="9.0.2" />
|
||||
<PackageReference Include="Npgsql.FSharp" Version="8.0.0" />
|
||||
<PackageReference Update="FSharp.Core" Version="9.0.100" />
|
||||
</ItemGroup>
|
||||
|
||||
|
@ -3,8 +3,10 @@
|
||||
/// The type of index to generate for the document
|
||||
[<Struct>]
|
||||
type DocumentIndex =
|
||||
|
||||
/// A GIN index with standard operations (all operators supported)
|
||||
| Full
|
||||
|
||||
/// A GIN index with JSONPath operations (optimized for @>, @?, @@ operators)
|
||||
| Optimized
|
||||
|
||||
@ -36,6 +38,7 @@ open Npgsql.FSharp
|
||||
/// Helper functions
|
||||
[<AutoOpen>]
|
||||
module private Helpers =
|
||||
|
||||
/// Shorthand to retrieve the data source as SqlProps
|
||||
let internal fromDataSource () =
|
||||
Configuration.dataSource () |> Sql.fromDataSource
|
||||
|
@ -5,6 +5,7 @@ This package provides a lightweight document library backed by [PostgreSQL](http
|
||||
## Features
|
||||
|
||||
- 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)
|
||||
- Address documents via ID, via comparison on any field, via equality on any property (using JSON containment, on a likely indexed field), 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)
|
||||
- Use `Task`-based async for all data access functions
|
||||
|
@ -1,6 +1,5 @@
|
||||
namespace BitBadger.Documents.Sqlite
|
||||
|
||||
open BitBadger.Documents
|
||||
open Microsoft.Data.Sqlite
|
||||
|
||||
/// F# extensions for the SqliteConnection type
|
||||
@ -263,9 +262,3 @@ type SqliteConnectionCSharpExtensions =
|
||||
[<Extension>]
|
||||
static member inline DeleteByFields(conn, tableName, howMatched, fields) =
|
||||
WithConn.Delete.byFields tableName howMatched fields conn
|
||||
|
||||
/// Delete documents by matching a comparison on a JSON field
|
||||
[<Extension>]
|
||||
[<System.Obsolete "Use DeleteByFields instead; will be removed in v4">]
|
||||
static member inline DeleteByField(conn, tableName, field) =
|
||||
conn.DeleteByFields(tableName, Any, [ field ])
|
||||
|
@ -153,7 +153,7 @@ module Results =
|
||||
/// Create a domain item from a document, specifying the field in which the document is found
|
||||
[<CompiledName "FromDocument">]
|
||||
let fromDocument<'TDoc> field (rdr: SqliteDataReader) : 'TDoc =
|
||||
Configuration.serializer().Deserialize<'TDoc>(rdr.GetString(rdr.GetOrdinal(field)))
|
||||
Configuration.serializer().Deserialize<'TDoc>(rdr.GetString(rdr.GetOrdinal field))
|
||||
|
||||
/// Create a domain item from a document
|
||||
[<CompiledName "FromData">]
|
||||
|
@ -5,6 +5,7 @@ This package provides a lightweight document library backed by [SQLite](https://
|
||||
## Features
|
||||
|
||||
- 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)
|
||||
- Address documents via ID or via comparison on any field
|
||||
- Access documents as your domain models (<abbr title="Plain Old CLR Objects">POCO</abbr>s)
|
||||
- Use `Task`-based async for all data access functions
|
||||
@ -72,28 +73,28 @@ Count customers in Atlanta:
|
||||
|
||||
```csharp
|
||||
// C#; parameters are table name, field, operator, and value
|
||||
// Count.ByField type signature is Func<string, Field, Task<long>>
|
||||
var customerCount = await Count.ByField("customer", Field.Equal("City", "Atlanta"));
|
||||
// Count.ByFields type signature is Func<string, FieldMatch, IEnumerable<Field>, Task<long>>
|
||||
var customerCount = await Count.ByFields("customer", FieldMatch.Any, [Field.Equal("City", "Atlanta")]);
|
||||
```
|
||||
|
||||
```fsharp
|
||||
// F#
|
||||
// Count.byField type signature is string -> Field -> Task<int64>
|
||||
let! customerCount = Count.byField "customer" (Field.Equal "City" "Atlanta")
|
||||
// Count.byFields type signature is string -> FieldMatch -> Field seq -> Task<int64>
|
||||
let! customerCount = Count.byFields "customer" Any [ Field.Equal "City" "Atlanta" ]
|
||||
```
|
||||
|
||||
Delete customers in Chicago: _(no offense, Second City; just an example...)_
|
||||
|
||||
```csharp
|
||||
// C#; parameters are same as above, except return is void
|
||||
// Delete.ByField type signature is Func<string, Field, Task>
|
||||
await Delete.ByField("customer", Field.Equal("City", "Chicago"));
|
||||
// Delete.ByFields type signature is Func<string, FieldMatch, IEnumerable<Field>, Task>
|
||||
await Delete.ByFields("customer", FieldMatch.Any, [Field.Equal("City", "Chicago")]);
|
||||
```
|
||||
|
||||
```fsharp
|
||||
// F#
|
||||
// Delete.byField type signature is string -> string -> Op -> obj -> Task<unit>
|
||||
do! Delete.byField "customer" (Field.Equal "City" "Chicago")
|
||||
// Delete.byFields type signature is string -> FieldMatch -> Field seq -> Task<unit>
|
||||
do! Delete.byFields "customer" Any [ Field.Equal "City" "Chicago" ]
|
||||
```
|
||||
|
||||
## More Information
|
||||
|
Loading…
Reference in New Issue
Block a user