Add builder CE

Also update to .NET 6
This commit is contained in:
Daniel J. Summers 2022-04-11 23:20:50 -04:00
parent 9ab98082b0
commit 812e20522a
5 changed files with 323 additions and 107 deletions

View File

@ -1,9 +1,8 @@
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15 # Visual Studio Version 17
VisualStudioVersion = 15.0.26124.0 VisualStudioVersion = 17.1.32228.430
MinimumVisualStudioVersion = 15.0.26124.0 MinimumVisualStudioVersion = 15.0.26124.0
Project("{E3D587AC-BEA4-4336-919D-1B6F1397C8FD}") = "RethinkDb.Driver.FSharp", "RethinkDb.Driver.FSharp\RethinkDb.Driver.FSharp.fsproj", "{9026E009-55DC-454E-87B7-39B9CBAD8BF8}" Project("{6EC3EE1D-3C4E-46DD-8F32-0CC8E7565705}") = "RethinkDb.Driver.FSharp", "RethinkDb.Driver.FSharp\RethinkDb.Driver.FSharp.fsproj", "{9026E009-55DC-454E-87B7-39B9CBAD8BF8}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -14,19 +13,24 @@ Global
Release|x64 = Release|x64 Release|x64 = Release|x64
Release|x86 = Release|x86 Release|x86 = Release|x86
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution GlobalSection(ProjectConfigurationPlatforms) = postSolution
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|x64.ActiveCfg = Debug|x64 {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|x64.ActiveCfg = Debug|Any CPU
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|x64.Build.0 = Debug|x64 {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|x64.Build.0 = Debug|Any CPU
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|x86.ActiveCfg = Debug|x86 {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|x86.ActiveCfg = Debug|Any CPU
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|x86.Build.0 = Debug|x86 {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Debug|x86.Build.0 = Debug|Any CPU
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|Any CPU.Build.0 = Release|Any CPU {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|Any CPU.Build.0 = Release|Any CPU
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|x64.ActiveCfg = Release|x64 {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|x64.ActiveCfg = Release|Any CPU
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|x64.Build.0 = Release|x64 {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|x64.Build.0 = Release|Any CPU
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|x86.ActiveCfg = Release|x86 {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|x86.ActiveCfg = Release|Any CPU
{9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|x86.Build.0 = Release|x86 {9026E009-55DC-454E-87B7-39B9CBAD8BF8}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {F557ECA4-998C-4FBE-9B59-ABFA3F8A84DF}
EndGlobalSection
EndGlobal

View File

@ -0,0 +1,189 @@
[<AutoOpen>]
module RethinkDb.Driver.FSharp.RethinkBuilder
open RethinkDb.Driver
open RethinkDb.Driver.Ast
open RethinkDb.Driver.Net
open System.Threading.Tasks
/// Computation Expression builder for RethinkDB queries
type RethinkBuilder<'T> () =
/// Create a RethinkDB hash map of the given field/value pairs
let fieldsToMap (fields : (string * obj) list) =
fields
|> List.fold (fun (m : Model.MapObject) item -> m.With (fst item, snd item)) (RethinkDB.R.HashMap ())
member _.Bind (expr : ReqlExpr, f : ReqlExpr -> ReqlExpr) = f expr
member this.For (expr, f) = this.Bind (expr, f)
member _.Yield _ = RethinkDB.R
// meta queries (tables, indexes, etc.)
/// List all databases
[<CustomOperation "dbList">]
member _.DbList (r : RethinkDB) = r.DbList ()
/// Create a database
[<CustomOperation "dbCreate">]
member _.DbCreate (r : RethinkDB, db : string) = r.DbCreate db
/// List all tables for the default database
[<CustomOperation "tableList">]
member _.TableList (r : RethinkDB) = r.TableList ()
/// List all tables for the specified database
[<CustomOperation "tableListWithDb">]
member _.TableListWithDb (r : RethinkDB, db : string) = r.Db(db).TableList ()
/// Create a table in the default database
[<CustomOperation "tableCreate">]
member _.TableCreate (r : RethinkDB, table : string) = r.TableCreate table
/// Create a table in the default database
[<CustomOperation "tableCreateWithDb">]
member _.TableCreateWithDb (r : RethinkDB, table : string, db : string) = r.Db(db).TableCreate table
/// List all indexes for a table
[<CustomOperation "indexList">]
member _.IndexList (tbl : Table) = tbl.IndexList ()
/// Create an index for a table
[<CustomOperation "indexCreate">]
member _.IndexCreate (tbl : Table, index : string) = tbl.IndexCreate index
/// Create an index for a table, using a function to calculate the index
[<CustomOperation "indexCreate">]
member _.IndexCreate (tbl : Table, index : string, f : ReqlExpr -> obj) = tbl.IndexCreate (index, ReqlFunction1 f)
// database/table identification
/// Specify a database for further commands
[<CustomOperation "withDb">]
member _.Db (expr : RethinkDB, db : string) = expr.Db db
/// Specify a table in the default database
[<CustomOperation "withTable">]
member _.TableInDefaultDb (expr : RethinkDB, table : string) = expr.Table table
/// Specify a table in a specific database
[<CustomOperation "withTableInDb">]
member _.Table (expr : RethinkDB, table : string, db : string) = expr.Db(db).Table table
/// Create an equality join with another table
[<CustomOperation "eqJoin">]
member _.EqJoin (expr : ReqlExpr, field : string, otherTable : string) =
expr.EqJoin (field, RethinkDB.R.Table otherTable)
// data retrieval / manipulation
/// Get a document from a table by its ID
[<CustomOperation "get">]
member _.Get (tbl : Table, key : obj) = tbl.Get key
/// Get all documents matching the given index value
[<CustomOperation "getAll">]
member _.GetAll (tbl : Table, keys : obj list, index : string) =
tbl.GetAll(Array.ofList keys).OptArg ("index", index)
/// Limit the results of this query
[<CustomOperation "limit">]
member _.Limit (expr : ReqlExpr, limit : int) = expr.Limit limit
/// Count documents for the current query
[<CustomOperation "count">]
member _.Count (expr : ReqlExpr) = expr.Count ()
/// Filter a query by a single field value
[<CustomOperation "filter">]
member _.Filter (expr : ReqlExpr, field : string, value : obj) = expr.Filter (fieldsToMap [ field, value ])
/// Filter a query by multiple field values
[<CustomOperation "filter">]
member _.Filter (expr : ReqlExpr, filter : (string * obj) list) = expr.Filter (fieldsToMap filter)
/// Filter a query by a function
[<CustomOperation "filter">]
member _.Filter (expr : ReqlExpr, f : ReqlExpr -> obj) = expr.Filter (ReqlFunction1 f)
/// Filter a query by multiple functions (has the effect of ANDing them)
[<CustomOperation "filter">]
member _.Filter (expr : ReqlExpr, fs : (ReqlExpr -> obj) list) =
fs |> List.fold (fun (e : ReqlExpr) f -> e.Filter (ReqlFunction1 f)) expr
/// Map fields for the current query
[<CustomOperation "map">]
member _.Map (expr : ReqlExpr, f : ReqlExpr -> obj) = expr.Map (ReqlFunction1 f)
/// Exclude the given fields from the output
[<CustomOperation "without">]
member _.Without (expr : ReqlExpr, fields : obj list) = expr.Without (Array.ofList fields)
/// Combine a left and right selection into a single record
[<CustomOperation "zip">]
member _.Zip (expr : ReqlExpr) = expr.Zip ()
/// Merge a document into the current query
[<CustomOperation "merge">]
member _.Merge (expr : ReqlExpr, f : ReqlExpr -> obj) = expr.Merge (ReqlFunction1 f)
/// Pluck (select only) specific fields from the query
[<CustomOperation "pluck">]
member _.Pluck (expr : ReqlExpr, fields : string list) = expr.Pluck (Array.ofList fields)
/// Order the results by the given field value (ascending)
[<CustomOperation "orderBy">]
member _.OrderBy (expr : ReqlExpr, field : string) = expr.OrderBy field
/// Order the results by the given function value
[<CustomOperation "orderBy">]
member _.OrderBy (expr : ReqlExpr, f : ReqlExpr -> obj) = expr.OrderBy (ReqlFunction1 f)
/// Order the results by the given field value (descending)
[<CustomOperation "orderByDescending">]
member _.OrderByDescending (expr : ReqlExpr, field : string) = expr.OrderBy (RethinkDB.R.Desc field)
/// Insert a document into the given table
[<CustomOperation "insert">]
member _.Insert (tbl : Table, doc : obj) = tbl.Insert doc
/// Update specific fields in a document
[<CustomOperation "update">]
member _.Update (expr : ReqlExpr, fields : (string * obj) list) = expr.Update (fieldsToMap fields)
/// Replace the current query with the specified document
[<CustomOperation "replace">]
member _.Replace (expr : ReqlExpr, doc : obj) = expr.Replace doc
/// Delete the document(s) identified by the current query
[<CustomOperation "delete">]
member _.Delete (expr : ReqlExpr) = expr.Delete ()
// executing queries
/// Execute the query, returning the result of the type specified
[<CustomOperation "result">]
member _.Result (expr : ReqlExpr) : IConnection -> Task<'T> =
fun conn -> task {
return! expr.RunResultAsync<'T> conn
}
/// Execute the query, returning the result of the type specified, or None if no result is found
[<CustomOperation "resultOption">]
member _.ResultOption (expr : ReqlExpr) : IConnection -> Task<'T option> =
fun conn -> task {
let! result = expr.RunResultAsync<'T> conn
return match (box >> isNull) result with true -> None | false -> Some result
}
/// Perform a write operation
[<CustomOperation "write">]
member _.Write (expr : ReqlExpr) : IConnection -> Task<Model.Result> =
fun conn -> task {
return! expr.RunWriteAsync conn
}
/// RethinkDB computation expression
let rethink<'T> = RethinkBuilder<'T> ()

View File

@ -1,8 +1,10 @@
namespace RethinkDb.Driver.FSharp namespace RethinkDb.Driver.FSharp
open Microsoft.Extensions.Configuration
open Newtonsoft.Json.Linq open Newtonsoft.Json.Linq
open RethinkDb.Driver open RethinkDb.Driver
open RethinkDb.Driver.Net open RethinkDb.Driver.Net
open System.Threading.Tasks
/// Parameters for the RethinkDB configuration /// Parameters for the RethinkDB configuration
type DataConfigParameter = type DataConfigParameter =
@ -13,15 +15,10 @@ type DataConfigParameter =
| Timeout of int | Timeout of int
| Database of string | Database of string
/// RethinDB configuration
type DataConfig = /// Connection builder function
{ Parameters : DataConfigParameter list } module private ConnectionBuilder =
with let build (builder : Connection.Builder) block =
static member empty =
{ Parameters = [] }
/// Create a RethinkDB connection
member this.CreateConnection () : IConnection =
let folder (builder : Connection.Builder) block =
match block with match block with
| Hostname x -> builder.Hostname x | Hostname x -> builder.Hostname x
| Port x -> builder.Port x | Port x -> builder.Port x
@ -29,34 +26,52 @@ with
| AuthKey x -> builder.AuthKey x | AuthKey x -> builder.AuthKey x
| Timeout x -> builder.Timeout x | Timeout x -> builder.Timeout x
| Database x -> builder.Db x | Database x -> builder.Db x
let bldr =
/// RethinDB configuration
type DataConfig =
{ Parameters : DataConfigParameter list }
/// An empty configuration
static member empty =
{ Parameters = [] }
/// Create a RethinkDB connection
member this.CreateConnection () : IConnection =
this.Parameters this.Parameters
|> Seq.fold folder (RethinkDB.R.Connection ()) |> Seq.fold ConnectionBuilder.build (RethinkDB.R.Connection ())
upcast bldr.Connect () |> function builder -> builder.Connect ()
/// Create a RethinkDB connection
member this.CreateConnectionAsync () : Task<Connection> =
this.Parameters
|> Seq.fold ConnectionBuilder.build (RethinkDB.R.Connection ())
|> function builder -> builder.ConnectAsync ()
/// The effective hostname /// The effective hostname
member this.Hostname = member this.Hostname =
match this.Parameters match this.Parameters |> List.tryPick (fun x -> match x with Hostname _ -> Some x | _ -> None) with
|> List.tryPick (fun x -> match x with Hostname _ -> Some x | _ -> None) with
| Some (Hostname x) -> x | Some (Hostname x) -> x
| _ -> RethinkDBConstants.DefaultHostname | _ -> RethinkDBConstants.DefaultHostname
/// The effective port /// The effective port
member this.Port = member this.Port =
match this.Parameters match this.Parameters |> List.tryPick (fun x -> match x with Port _ -> Some x | _ -> None) with
|> List.tryPick (fun x -> match x with Port _ -> Some x | _ -> None) with
| Some (Port x) -> x | Some (Port x) -> x
| _ -> RethinkDBConstants.DefaultPort | _ -> RethinkDBConstants.DefaultPort
/// The effective connection timeout /// The effective connection timeout
member this.Timeout = member this.Timeout =
match this.Parameters match this.Parameters |> List.tryPick (fun x -> match x with Timeout _ -> Some x | _ -> None) with
|> List.tryPick (fun x -> match x with Timeout _ -> Some x | _ -> None) with
| Some (Timeout x) -> x | Some (Timeout x) -> x
| _ -> RethinkDBConstants.DefaultTimeout | _ -> RethinkDBConstants.DefaultTimeout
/// The effective database /// The effective database
member this.Database = member this.Database =
match this.Parameters match this.Parameters |> List.tryPick (fun x -> match x with Database _ -> Some x | _ -> None) with
|> List.tryPick (fun x -> match x with Database _ -> Some x | _ -> None) with
| Some (Database x) -> x | Some (Database x) -> x
| _ -> RethinkDBConstants.DefaultDbName | _ -> RethinkDBConstants.DefaultDbName
/// Parse settings from JSON /// Parse settings from JSON
/// ///
/// A sample JSON object with all the possible properties filled in: /// A sample JSON object with all the possible properties filled in:
@ -72,24 +87,32 @@ with
/// ///
/// None of these properties are required, and properties not matching any of the above listed ones will be ignored. /// None of these properties are required, and properties not matching any of the above listed ones will be ignored.
static member FromJson json = static member FromJson json =
let isNotNull = not << isNull
let parsed = JObject.Parse json let parsed = JObject.Parse json
let config = { Parameters =
seq { [ match parsed["hostname"] with null -> () | x -> Hostname <| x.Value<string> ()
match parsed.["hostname"] with x when isNotNull x -> yield Hostname <| x.Value<string> () | _ -> () match parsed["port"] with null -> () | x -> Port <| x.Value<int> ()
match parsed.["port"] with x when isNotNull x -> yield Port <| x.Value<int> () | _ -> () match parsed["auth-key"] with null -> () | x -> AuthKey <| x.Value<string> ()
match parsed.["auth-key"] with x when isNotNull x -> yield AuthKey <| x.Value<string> () | _ -> () match parsed["timeout"] with null -> () | x -> Timeout <| x.Value<int> ()
match parsed.["timeout"] with x when isNotNull x -> yield Timeout <| x.Value<int> () | _ -> () match parsed["database"] with null -> () | x -> Database <| x.Value<string> ()
match parsed.["database"] with x when isNotNull x -> yield Database <| x.Value<string> () | _ -> () match parsed["username"], parsed["password"] with
let userName = parsed.["username"] | null, _ | _, null -> ()
let password = parsed.["password"] | userName, password -> User (userName.Value<string> (), password.Value<string> ())
match isNotNull userName && isNotNull password with ]
| true -> yield User (userName.Value<string> (), password.Value<string> ())
| _ -> ()
} }
|> List.ofSeq
{ Parameters = config }
/// Parse settings from a JSON text file /// Parse settings from a JSON text file
/// ///
/// See doc for FromJson for the expected JSON format. /// See doc for FromJson for the expected JSON format.
static member FromJsonFile = System.IO.File.ReadAllText >> DataConfig.FromJson static member FromJsonFile = System.IO.File.ReadAllText >> DataConfig.FromJson
/// Parse settings from application configuration
static member FromConfiguration (cfg : IConfigurationSection) =
{ Parameters =
[ match cfg["hostname"] with null -> () | host -> Hostname host
match cfg["port"] with null -> () | port -> Port (int port)
match cfg["auth-key"] with null -> () | key -> AuthKey key
match cfg["timeout"] with null -> () | time -> Timeout (int time)
match cfg["database"] with null -> () | db -> Database db
match cfg["username"], cfg["password"] with null, _ | _, null -> () | user -> User user
]
}

View File

@ -14,7 +14,7 @@ let asyncCursor<'T> conn (expr : ReqlExpr) =
/// Get the result of a non-select ReQL expression /// Get the result of a non-select ReQL expression
let asyncReqlResult conn (expr : ReqlExpr) = let asyncReqlResult conn (expr : ReqlExpr) =
expr.RunResultAsync conn expr.RunWriteAsync conn
|> Async.AwaitTask |> Async.AwaitTask
/// Get the results of an expression /// Get the results of an expression

View File

@ -1,7 +1,7 @@
<Project Sdk="FSharp.NET.Sdk;Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFrameworks>net45;netstandard1.6</TargetFrameworks> <TargetFrameworks>net6.0</TargetFrameworks>
<Description>Idiomatic F# extentions to the official RethinkDB C# driver</Description> <Description>Idiomatic F# extentions to the official RethinkDB C# driver</Description>
<Authors>Daniel J. Summers</Authors> <Authors>Daniel J. Summers</Authors>
<PackageLicenseUrl>https://github.com/danieljsummers/RethinkDb.Driver.FSharp/blob/master/LICENSE</PackageLicenseUrl> <PackageLicenseUrl>https://github.com/danieljsummers/RethinkDb.Driver.FSharp/blob/master/LICENSE</PackageLicenseUrl>
@ -11,19 +11,19 @@
<PackageReleaseNotes>Alpha; use at your own risk</PackageReleaseNotes> <PackageReleaseNotes>Alpha; use at your own risk</PackageReleaseNotes>
<Copyright>See LICENSE</Copyright> <Copyright>See LICENSE</Copyright>
<PackageTags>RethinkDB document F#</PackageTags> <PackageTags>RethinkDB document F#</PackageTags>
<VersionPrefix>0.7.0</VersionPrefix> <VersionPrefix>0.7.1</VersionPrefix>
<VersionSuffix>alpha-0004</VersionSuffix> <VersionSuffix>alpha-0001</VersionSuffix>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Builder.fs" />
<Compile Include="Functions.fs" /> <Compile Include="Functions.fs" />
<Compile Include="Config.fs" /> <Compile Include="Config.fs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="FSharp.Core" Version="4.*" /> <PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.1" />
<PackageReference Include="FSharp.NET.Sdk" Version="1.0.*" PrivateAssets="All" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
<PackageReference Include="Newtonsoft.Json" Version="10.*" />
<PackageReference Include="RethinkDb.Driver" Version="2.*" /> <PackageReference Include="RethinkDb.Driver" Version="2.*" />
</ItemGroup> </ItemGroup>