{-# LANGUAGE QuasiQuotes #-}

module Hasura.Backends.MSSQL.DDL.Source.Version
  ( SourceCatalogVersion,
    initialSourceCatalogVersion,
    latestSourceCatalogVersion,
    previousSourceCatalogVersions,
    setSourceCatalogVersion,
    getSourceCatalogVersion,
  )
where

import Database.MSSQL.Transaction
import Database.ODBC.SQLServer
import Database.ODBC.TH qualified as ODBC
import Hasura.Backends.MSSQL.Connection (MonadMSSQLTx (..))
import Hasura.Backends.MSSQL.SQL.Error qualified as HGE
import Hasura.Prelude
import Hasura.RQL.Types.BackendType (BackendType (MSSQL))
import Hasura.Server.Migrate.Version qualified as Version

type SourceCatalogVersion = Version.SourceCatalogVersion 'MSSQL

initialSourceCatalogVersion :: SourceCatalogVersion
initialSourceCatalogVersion :: SourceCatalogVersion
initialSourceCatalogVersion = Int -> SourceCatalogVersion
forall (backend :: BackendType).
Int -> SourceCatalogVersion backend
Version.SourceCatalogVersion Int
1

latestSourceCatalogVersion :: SourceCatalogVersion
latestSourceCatalogVersion :: SourceCatalogVersion
latestSourceCatalogVersion = Int -> SourceCatalogVersion
forall (backend :: BackendType).
Int -> SourceCatalogVersion backend
Version.SourceCatalogVersion Int
4

previousSourceCatalogVersions :: [SourceCatalogVersion]
previousSourceCatalogVersions :: [SourceCatalogVersion]
previousSourceCatalogVersions = [SourceCatalogVersion
initialSourceCatalogVersion .. SourceCatalogVersion -> SourceCatalogVersion
forall a. Enum a => a -> a
pred SourceCatalogVersion
latestSourceCatalogVersion]

setSourceCatalogVersion :: (MonadMSSQLTx m) => SourceCatalogVersion -> m ()
setSourceCatalogVersion :: forall (m :: * -> *).
MonadMSSQLTx m =>
SourceCatalogVersion -> m ()
setSourceCatalogVersion (Version.SourceCatalogVersion Int
version) =
  TxE QErr () -> m ()
forall a. TxE QErr a -> m a
forall (m :: * -> *) a. MonadMSSQLTx m => TxE QErr a -> m a
liftMSSQLTx (TxE QErr () -> m ()) -> TxE QErr () -> m ()
forall a b. (a -> b) -> a -> b
$ (MSSQLTxError -> QErr) -> Query -> TxE QErr ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler Query
setSourceCatalogVersionQuery
  where
    setSourceCatalogVersionQuery :: Query
setSourceCatalogVersionQuery =
      [ODBC.sql|
        BEGIN TRANSACTION
          IF EXISTS (select 1 from hdb_catalog.hdb_source_catalog_version WITH (UPDLOCK,SERIALIZABLE))
              BEGIN
                  UPDATE hdb_catalog.hdb_source_catalog_version
                  SET version = $version,  upgraded_on = SYSDATETIMEOFFSET()
              END
          ELSE
              BEGIN
                  INSERT INTO hdb_catalog.hdb_source_catalog_version (version, upgraded_on)
                  values ($version, SYSDATETIMEOFFSET())
              END
        COMMIT TRANSACTION
      |]

getSourceCatalogVersion :: (MonadMSSQLTx m) => m SourceCatalogVersion
getSourceCatalogVersion :: forall (m :: * -> *). MonadMSSQLTx m => m SourceCatalogVersion
getSourceCatalogVersion =
  Int -> SourceCatalogVersion
forall (backend :: BackendType).
Int -> SourceCatalogVersion backend
Version.SourceCatalogVersion
    (Int -> SourceCatalogVersion) -> m Int -> m SourceCatalogVersion
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TxE QErr Int -> m Int
forall a. TxE QErr a -> m a
forall (m :: * -> *) a. MonadMSSQLTx m => TxE QErr a -> m a
liftMSSQLTx ((MSSQLTxError -> QErr) -> Query -> TxE QErr Int
forall (m :: * -> *) a e.
(MonadIO m, FromRow a) =>
(MSSQLTxError -> e) -> Query -> TxET e m a
singleRowQueryE MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler Query
[ODBC.sql| SELECT version FROM hdb_catalog.hdb_source_catalog_version |])