From 587b70469f2d0bad4cedc832c5ce4919615772bb Mon Sep 17 00:00:00 2001 From: Kerry Perret Date: Sat, 23 Jan 2021 17:08:09 +0100 Subject: [PATCH] feat(refactor): add specific support --- Vp.FSharp.Sql.PostgreSql/PostgreSqlCommand.fs | 92 +++++++++++++++ .../PostgreSqlNullDbValue.fs | 8 ++ .../PostgreSqlTransaction.fs | 22 ++++ .../{Library.fs => Types.fs} | 107 +++--------------- .../Vp.FSharp.Sql.PostgreSql.fsproj | 7 +- 5 files changed, 140 insertions(+), 96 deletions(-) create mode 100644 Vp.FSharp.Sql.PostgreSql/PostgreSqlCommand.fs create mode 100644 Vp.FSharp.Sql.PostgreSql/PostgreSqlNullDbValue.fs create mode 100644 Vp.FSharp.Sql.PostgreSql/PostgreSqlTransaction.fs rename Vp.FSharp.Sql.PostgreSql/{Library.fs => Types.fs} (57%) diff --git a/Vp.FSharp.Sql.PostgreSql/PostgreSqlCommand.fs b/Vp.FSharp.Sql.PostgreSql/PostgreSqlCommand.fs new file mode 100644 index 0000000..b9a36e5 --- /dev/null +++ b/Vp.FSharp.Sql.PostgreSql/PostgreSqlCommand.fs @@ -0,0 +1,92 @@ +namespace Vp.FSharp.Sql.PostgreSql + +open Vp.FSharp.Sql + + +[] +module PostgreSqlCommand = + + /// Initialize a command definition with the given text contained in the given string. + let text value : PostgreSqlCommandDefinition = + SqlCommand.text value + + /// Initialize a command definition with the given text spanning over several strings (ie. list). + let textFromList value : PostgreSqlCommandDefinition = + SqlCommand.textFromList value + + /// Update the command definition so that when executing the command, it doesn't use any logger. + /// Be it the default one (Global, if any.) or a previously overriden one. + let noLogger commandDefinition = { commandDefinition with Logger = LoggerKind.Nothing } + + /// Update the command definition so that when executing the command, it use the given overriding logger. + /// instead of the default one, aka the Global logger, if any. + let overrideLogger value commandDefinition = { commandDefinition with Logger = LoggerKind.Override value } + + /// Update the command definition with the given parameters. + let parameters value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = + SqlCommand.parameters value commandDefinition + + /// Update the command definition with the given cancellation token. + let cancellationToken value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = + SqlCommand.cancellationToken value commandDefinition + + /// Update the command definition with the given timeout. + let timeout value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = + SqlCommand.timeout value commandDefinition + + /// Update the command definition and sets the command type (ie. how it should be interpreted). + let commandType value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = + SqlCommand.commandType value commandDefinition + + /// Update the command definition and sets whether the command should be prepared or not. + let prepare value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = + SqlCommand.prepare value commandDefinition + + /// Update the command definition and sets whether the command should be wrapped in the given transaction. + let transaction value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = + SqlCommand.transaction value commandDefinition + + /// Return the sets of rows as an AsyncSeq accordingly to the command definition. + let queryAsyncSeq connection read (commandDefinition: PostgreSqlCommandDefinition) = + SqlCommand.queryAsyncSeq + connection (Constants.Deps) (PostgreSqlConfiguration.Snapshot) read commandDefinition + + /// Return the sets of rows as a list accordingly to the command definition. + let queryList connection read (commandDefinition: PostgreSqlCommandDefinition) = + SqlCommand.queryList + connection (Constants.Deps) (PostgreSqlConfiguration.Snapshot) read commandDefinition + + /// Return the first set of rows as a list accordingly to the command definition. + let querySetList connection read (commandDefinition: PostgreSqlCommandDefinition) = + SqlCommand.querySetList + connection (Constants.Deps) (PostgreSqlConfiguration.Snapshot) read commandDefinition + + /// Return the 2 first sets of rows as a tuple of 2 lists accordingly to the command definition. + let querySetList2 connection read1 read2 (commandDefinition: PostgreSqlCommandDefinition) = + SqlCommand.querySetList2 + connection (Constants.Deps) (PostgreSqlConfiguration.Snapshot) read1 read2 commandDefinition + + /// Return the 3 first sets of rows as a tuple of 3 lists accordingly to the command definition. + let querySetList3 connection read1 read2 read3 (commandDefinition: PostgreSqlCommandDefinition) = + SqlCommand.querySetList3 + connection (Constants.Deps) (PostgreSqlConfiguration.Snapshot) read1 read2 read3 commandDefinition + + /// Execute the command accordingly to its definition and, + /// - return the first cell value, if it is available and of the given type. + /// - throw an exception, otherwise. + let executeScalar<'Scalar> connection (commandDefinition: PostgreSqlCommandDefinition) = + SqlCommand.executeScalar<'Scalar, _, _, _, _, _, _, _, _> + connection (Constants.Deps) (PostgreSqlConfiguration.Snapshot) commandDefinition + + /// Execute the command accordingly to its definition and, + /// - return Some, if the first cell is available and of the given type. + /// - return None, if first cell is DbNull. + /// - throw an exception, otherwise. + let executeScalarOrNone<'Scalar> connection (commandDefinition: PostgreSqlCommandDefinition) = + SqlCommand.executeScalarOrNone<'Scalar, _, _, _, _, _, _, _, _> + connection (Constants.Deps) (PostgreSqlConfiguration.Snapshot) commandDefinition + + /// Execute the command accordingly to its definition and, return the number of rows affected. + let executeNonQuery connection (commandDefinition: PostgreSqlCommandDefinition) = + SqlCommand.executeNonQuery + connection (Constants.Deps) (PostgreSqlConfiguration.Snapshot) commandDefinition diff --git a/Vp.FSharp.Sql.PostgreSql/PostgreSqlNullDbValue.fs b/Vp.FSharp.Sql.PostgreSql/PostgreSqlNullDbValue.fs new file mode 100644 index 0000000..b141251 --- /dev/null +++ b/Vp.FSharp.Sql.PostgreSql/PostgreSqlNullDbValue.fs @@ -0,0 +1,8 @@ +[] +module Vp.FSharp.Sql.PostgreSql.PostgreSqlNullDbValue + +open Vp.FSharp.Sql + + +let ifNone toDbValue = NullDbValue.ifNone toDbValue PostgreSqlDbValue.Null +let ifError toDbValue = NullDbValue.ifError toDbValue (fun _ -> PostgreSqlDbValue.Null) diff --git a/Vp.FSharp.Sql.PostgreSql/PostgreSqlTransaction.fs b/Vp.FSharp.Sql.PostgreSql/PostgreSqlTransaction.fs new file mode 100644 index 0000000..ea1d243 --- /dev/null +++ b/Vp.FSharp.Sql.PostgreSql/PostgreSqlTransaction.fs @@ -0,0 +1,22 @@ +[] +module Vp.FSharp.Sql.SqlServer.PostgreSqlTransaction + +open Vp.FSharp.Sql +open Vp.FSharp.Sql.PostgreSql + + +let beginTransactionAsync = Constants.Deps.BeginTransactionAsync + +let commit cancellationToken isolationLevel connection body = + Transaction.commit cancellationToken isolationLevel connection beginTransactionAsync body +let notCommit cancellationToken isolationLevel connection body = + Transaction.notCommit cancellationToken isolationLevel connection beginTransactionAsync body +let commitOnOk cancellationToken isolationLevel connection body = + Transaction.commitOnOk cancellationToken isolationLevel connection beginTransactionAsync body +let commitOnSome cancellationToken isolationLevel connection body = + Transaction.commitOnSome cancellationToken isolationLevel connection beginTransactionAsync body + +let defaultCommit connection body = Transaction.defaultCommit connection beginTransactionAsync body +let defaultNotCommit connection body = Transaction.defaultNotCommit connection beginTransactionAsync body +let defaultCommitOnOk connection body = Transaction.defaultCommitOnOk connection beginTransactionAsync body +let defaultCommitOnSome connection body = Transaction.defaultCommitOnSome connection beginTransactionAsync body diff --git a/Vp.FSharp.Sql.PostgreSql/Library.fs b/Vp.FSharp.Sql.PostgreSql/Types.fs similarity index 57% rename from Vp.FSharp.Sql.PostgreSql/Library.fs rename to Vp.FSharp.Sql.PostgreSql/Types.fs index 037c2cd..a17730c 100644 --- a/Vp.FSharp.Sql.PostgreSql/Library.fs +++ b/Vp.FSharp.Sql.PostgreSql/Types.fs @@ -1,7 +1,9 @@ namespace Vp.FSharp.Sql.PostgreSql open System +open System.Data open System.Net +open System.Threading open System.Collections.Generic open System.Net.NetworkInformation @@ -98,15 +100,11 @@ type PostgreSqlDependencies = NpgsqlTransaction, PostgreSqlDbValue> -[] -module PostgreSqlNullDbValue = - let ifNone toDbValue = NullDbValue.ifNone toDbValue PostgreSqlDbValue.Null - let ifError toDbValue = NullDbValue.ifError toDbValue (fun _ -> PostgreSqlDbValue.Null) -[] -module PostgreSqlCommand = +[] +type internal Constants private () = - let private dbValueToParameter name value = + static member DbValueToParameter name value = let parameter = NpgsqlParameter() parameter.ParameterName <- name match value with @@ -254,92 +252,13 @@ module PostgreSqlCommand = parameter.Value <- value parameter - let private deps: PostgreSqlDependencies = + static member Deps : PostgreSqlDependencies = + let beginTransactionAsync + (connection: NpgsqlConnection) (isolationLevel: IsolationLevel) (cancellationToken: CancellationToken) = + connection.BeginTransactionAsync(isolationLevel, cancellationToken) + { CreateCommand = fun connection -> connection.CreateCommand() + SetCommandTransaction = fun command transaction -> command.Transaction <- transaction + BeginTransactionAsync = beginTransactionAsync ExecuteReaderAsync = fun command -> command.ExecuteReaderAsync - DbValueToParameter = dbValueToParameter } - - /// Initialize a command definition with the given text contained in the given string. - let text value : PostgreSqlCommandDefinition = - SqlCommand.text value - - /// Initialize a command definition with the given text spanning over several strings (ie. list). - let textFromList value : PostgreSqlCommandDefinition = - SqlCommand.textFromList value - - /// Update the command definition so that when executing the command, it doesn't use any logger. - /// Be it the default one (Global, if any.) or a previously overriden one. - let noLogger commandDefinition = { commandDefinition with Logger = LoggerKind.Nothing } - - /// Update the command definition so that when executing the command, it use the given overriding logger. - /// instead of the default one, aka the Global logger, if any. - let overrideLogger value commandDefinition = { commandDefinition with Logger = LoggerKind.Override value } - - /// Update the command definition with the given parameters. - let parameters value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = - SqlCommand.parameters value commandDefinition - - /// Update the command definition with the given cancellation token. - let cancellationToken value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = - SqlCommand.cancellationToken value commandDefinition - - /// Update the command definition with the given timeout. - let timeout value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = - SqlCommand.timeout value commandDefinition - - /// Update the command definition and sets the command type (ie. how it should be interpreted). - let commandType value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = - SqlCommand.commandType value commandDefinition - - /// Update the command definition and sets whether the command should be prepared or not. - let prepare value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = - SqlCommand.prepare value commandDefinition - - /// Update the command definition and sets whether the command should be wrapped in the given transaction. - let transaction value (commandDefinition: PostgreSqlCommandDefinition) : PostgreSqlCommandDefinition = - SqlCommand.transaction value commandDefinition - - /// Return the sets of rows as an AsyncSeq accordingly to the command definition. - let queryAsyncSeq connection read (commandDefinition: PostgreSqlCommandDefinition) = - SqlCommand.queryAsyncSeq - connection deps (PostgreSqlConfiguration.Snapshot) read commandDefinition - - /// Return the sets of rows as a list accordingly to the command definition. - let queryList connection read (commandDefinition: PostgreSqlCommandDefinition) = - SqlCommand.queryList - connection deps (PostgreSqlConfiguration.Snapshot) read commandDefinition - - /// Return the first set of rows as a list accordingly to the command definition. - let querySetList connection read (commandDefinition: PostgreSqlCommandDefinition) = - SqlCommand.querySetList - connection deps (PostgreSqlConfiguration.Snapshot) read commandDefinition - - /// Return the 2 first sets of rows as a tuple of 2 lists accordingly to the command definition. - let querySetList2 connection read1 read2 (commandDefinition: PostgreSqlCommandDefinition) = - SqlCommand.querySetList2 - connection deps (PostgreSqlConfiguration.Snapshot) read1 read2 commandDefinition - - /// Return the 3 first sets of rows as a tuple of 3 lists accordingly to the command definition. - let querySetList3 connection read1 read2 read3 (commandDefinition: PostgreSqlCommandDefinition) = - SqlCommand.querySetList3 - connection deps (PostgreSqlConfiguration.Snapshot) read1 read2 read3 commandDefinition - - /// Execute the command accordingly to its definition and, - /// - return the first cell value, if it is available and of the given type. - /// - throw an exception, otherwise. - let executeScalar<'Scalar> connection (commandDefinition: PostgreSqlCommandDefinition) = - SqlCommand.executeScalar<'Scalar, _, _, _, _, _, _, _, _, _> - connection deps (PostgreSqlConfiguration.Snapshot) commandDefinition - - /// Execute the command accordingly to its definition and, - /// - return Some, if the first cell is available and of the given type. - /// - return None, if first cell is DbNull. - /// - throw an exception, otherwise. - let executeScalarOrNone<'Scalar> connection (commandDefinition: PostgreSqlCommandDefinition) = - SqlCommand.executeScalarOrNone<'Scalar, _, _, _, _, _, _, _, _, _> - connection deps (PostgreSqlConfiguration.Snapshot) commandDefinition - - /// Execute the command accordingly to its definition and, return the number of rows affected. - let executeNonQuery connection (commandDefinition: PostgreSqlCommandDefinition) = - SqlCommand.executeNonQuery - connection deps (PostgreSqlConfiguration.Snapshot) commandDefinition + DbValueToParameter = Constants.DbValueToParameter } diff --git a/Vp.FSharp.Sql.PostgreSql/Vp.FSharp.Sql.PostgreSql.fsproj b/Vp.FSharp.Sql.PostgreSql/Vp.FSharp.Sql.PostgreSql.fsproj index 4e9521a..caf586f 100644 --- a/Vp.FSharp.Sql.PostgreSql/Vp.FSharp.Sql.PostgreSql.fsproj +++ b/Vp.FSharp.Sql.PostgreSql/Vp.FSharp.Sql.PostgreSql.fsproj @@ -18,12 +18,15 @@ - + + + + - +