mssql isolation level option

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/9626
GitOrigin-RevId: 43861a982afadd9fdefb7d8996999e051e751222
This commit is contained in:
Gil Mizrahi 2023-06-23 18:19:26 +03:00 committed by hasura-bot
parent e7983e268a
commit 653106087c
5 changed files with 80 additions and 12 deletions

View File

@ -127,10 +127,11 @@ keywords:
## MsSQLSourceConnectionInfo {#mssqlsourceconnectioninfo}
| Key | Required | Schema | Description |
| ----------------- | -------- | --------------------------------------- | ------------------------------------------------------------- |
| connection_string | true | `String` \| [FromEnv](#fromenv) | The database connection string, or as an environment variable |
| pool_settings | false | [MsSQLPoolSettings](#mssqlpoolsettings) | Connection pool settings |
| Key | Required | Schema | Description |
| ----------------- | -------- | ------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------- |
| connection_string | true | `String` \| [FromEnv](#fromenv) | The database connection string, or as an environment variable |
| pool_settings | false | [MsSQLPoolSettings](#mssqlpoolsettings) | Connection pool settings |
| isolation_level | false | `read-uncommited` \| `read-committed` \| `repeatable-read` \| `snapshot` \| `serializable` | The transaction isolation level in which the queries made to the source will be run with (default: `read-committed`). |
## FromEnv {#fromenv}

View File

@ -4935,6 +4935,11 @@
}
]
},
"isolation_level": {
"default": "read-committed",
"description": "The transaction isolation level in which the queries made to the source will be run with (default: read-committed).\nIsolation level",
"type": "string"
},
"pool_settings": {
"$ref": "#/components/schemas/MSSQLPoolSettings"
}

View File

@ -18,9 +18,13 @@ module Database.MSSQL.Transaction
)
where
import Autodocodec (HasCodec (codec), bimapCodec, textCodec, (<?>))
import Autodocodec.Aeson qualified as AC
import Control.Exception (try)
import Control.Monad.Morph (MFunctor (hoist))
import Control.Monad.Trans.Control (MonadBaseControl)
import Data.Aeson qualified as J
import Data.Text qualified as T
import Database.MSSQL.Pool
import Database.ODBC.SQLServer (FromRow)
import Database.ODBC.SQLServer qualified as ODBC
@ -243,17 +247,62 @@ data TransactionState
-- rollback of the transaction.
TSUncommittable
-- | <https://learn.microsoft.com/en-us/sql/t-sql/statements/set-transaction-isolation-level-transact-sql>
data TxIsolation
= ReadCommitted
= ReadUncommitted
| ReadCommitted
| RepeatableRead
| Snapshot
| Serializable
deriving (Eq, Generic)
instance Show TxIsolation where
show = \case
ReadUncommitted -> "READ UNCOMMITTED"
ReadCommitted -> "READ COMMITTED"
RepeatableRead -> "REPEATABLE READ"
Snapshot -> "SNAPSHOT"
Serializable -> "SERIALIZABLE"
instance Hashable TxIsolation
instance NFData TxIsolation
instance HasCodec TxIsolation where
codec =
bimapCodec
decode
encode
textCodec
<?> "Isolation level"
where
decode :: Text -> Either String TxIsolation
decode = \case
"read-uncommitted" -> Right ReadUncommitted
"read-committed" -> Right ReadCommitted
"repeatable-read" -> Right RepeatableRead
"snapshot" -> Right Snapshot
"serializable" -> Right Serializable
_ ->
Left
$ T.unpack
$ "Unexpected options for isolation_level. Expected "
<> "'read-uncommited' | 'read-committed' | 'repeatable-read' | 'snapshot' | 'serializable'"
encode :: TxIsolation -> Text
encode = \case
ReadUncommitted -> "read-uncommitted"
ReadCommitted -> "read-committed"
RepeatableRead -> "repeatable-read"
Snapshot -> "snapshot"
Serializable -> "serializable"
instance J.ToJSON TxIsolation where
toJSON = AC.toJSONViaCodec
toEncoding = AC.toEncodingViaCodec
instance J.FromJSON TxIsolation where
parseJSON = AC.parseJSONViaCodec
-- | Wraps an action in a transaction. Rolls back on errors.
asTransaction ::
forall e a m.

View File

@ -1466,7 +1466,7 @@ mkPgSourceResolver pgLogger env _ config = runExceptT do
mkMSSQLSourceResolver :: SourceResolver ('MSSQL)
mkMSSQLSourceResolver env _name (MSSQLConnConfiguration connInfo _) = runExceptT do
let MSSQLConnectionInfo iConnString MSSQLPoolSettings {..} = connInfo
let MSSQLConnectionInfo iConnString MSSQLPoolSettings {..} isolationLevel = connInfo
connOptions =
MSPool.ConnectionOptions
{ _coConnections = fromMaybe defaultMSSQLMaxConnections _mpsMaxConnections,
@ -1474,6 +1474,6 @@ mkMSSQLSourceResolver env _name (MSSQLConnConfiguration connInfo _) = runExceptT
_coIdleTime = _mpsIdleTimeout
}
(connString, mssqlPool) <- createMSSQLPool iConnString connOptions env
let mssqlExecCtx = mkMSSQLExecCtx mssqlPool NeverResizePool
let mssqlExecCtx = mkMSSQLExecCtx isolationLevel mssqlPool NeverResizePool
numReadReplicas = 0
pure $ MSSQLSourceConfig connString mssqlExecCtx numReadReplicas

View File

@ -35,6 +35,7 @@ import Data.Aeson qualified as J
import Data.Environment qualified as Env
import Data.Has
import Data.Text (pack, unpack)
import Data.Text qualified as T
import Data.Time (localTimeToUTC)
import Database.MSSQL.Pool qualified as MSPool
import Database.MSSQL.Transaction qualified as MSTx
@ -148,7 +149,8 @@ defaultMSSQLPoolSettings =
data MSSQLConnectionInfo = MSSQLConnectionInfo
{ _mciConnectionString :: InputConnectionString,
_mciPoolSettings :: MSSQLPoolSettings
_mciPoolSettings :: MSSQLPoolSettings,
_mciIsolationLevel :: MSTx.TxIsolation
}
deriving (Show, Eq, Generic)
@ -164,6 +166,14 @@ instance HasCodec MSSQLConnectionInfo where
AC..= _mciConnectionString
<*> requiredField' "pool_settings"
AC..= _mciPoolSettings
<*> AC.optionalFieldWithDefault "isolation_level" MSTx.ReadCommitted isolationLevelDoc
AC..= _mciIsolationLevel
where
isolationLevelDoc =
T.unwords
[ "The transaction isolation level in which the queries made to the",
"source will be run with (default: read-committed)."
]
instance ToJSON MSSQLConnectionInfo where
toJSON = genericToJSON hasuraJSON
@ -176,6 +186,9 @@ instance FromJSON MSSQLConnectionInfo where
<*> o
.:? "pool_settings"
.!= defaultMSSQLPoolSettings
<*> o
.:? "isolation_level"
.!= MSTx.ReadCommitted
data MSSQLConnConfiguration = MSSQLConnConfiguration
{ _mccConnectionInfo :: MSSQLConnectionInfo,
@ -251,11 +264,11 @@ data MSSQLExecCtx = MSSQLExecCtx
}
-- | Creates a MSSQL execution context for a single primary pool
mkMSSQLExecCtx :: MSPool.MSSQLPool -> ResizePoolStrategy -> MSSQLExecCtx
mkMSSQLExecCtx pool resizeStrategy =
mkMSSQLExecCtx :: MSTx.TxIsolation -> MSPool.MSSQLPool -> ResizePoolStrategy -> MSSQLExecCtx
mkMSSQLExecCtx isolationLevel pool resizeStrategy =
MSSQLExecCtx
{ mssqlRunReadOnly = \tx -> MSTx.runTxE defaultMSSQLTxErrorHandler MSTx.ReadCommitted tx pool,
mssqlRunReadWrite = \tx -> MSTx.runTxE defaultMSSQLTxErrorHandler MSTx.ReadCommitted tx pool,
{ mssqlRunReadOnly = \tx -> MSTx.runTxE defaultMSSQLTxErrorHandler isolationLevel tx pool,
mssqlRunReadWrite = \tx -> MSTx.runTxE defaultMSSQLTxErrorHandler isolationLevel tx pool,
mssqlRunSerializableTx = \tx -> MSTx.runTxE defaultMSSQLTxErrorHandler MSTx.Serializable tx pool,
mssqlDestroyConn = MSPool.drainMSSQLPool pool,
mssqlResizePools =