{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TemplateHaskell #-}
module Hasura.Backends.MSSQL.DDL.EventTrigger
( createTableEventTrigger,
fetchUndeliveredEvents,
setRetry,
recordSuccess,
recordError,
recordError',
dropTriggerQ,
dropTriggerAndArchiveEvents,
dropDanglingSQLTrigger,
redeliverEvent,
insertManualEvent,
unlockEventsInSource,
getMaintenanceModeVersion,
qualifyTableName,
createMissingSQLTriggers,
checkIfTriggerExists,
)
where
import Control.Monad.Trans.Control (MonadBaseControl)
import Data.Aeson qualified as J
import Data.ByteString qualified as B
import Data.ByteString.Lazy qualified as BL
import Data.FileEmbed (makeRelativeToProject)
import Data.HashSet qualified as HashSet
import Data.Set.NonEmpty qualified as NE
import Data.Text qualified as T
import Data.Text.Extended (commaSeparated, toTxt)
import Data.Text.Lazy qualified as LT
import Data.Text.NonEmpty (mkNonEmptyTextUnsafe)
import Data.Time
import Database.MSSQL.Transaction (TxE, multiRowQueryE, singleRowQueryE, unitQueryE)
import Database.ODBC.SQLServer (Datetime2 (..), rawUnescapedText, toSql)
import Database.ODBC.TH qualified as ODBC
import Hasura.Backends.MSSQL.Connection
import Hasura.Backends.MSSQL.DDL.Source.Version
import Hasura.Backends.MSSQL.SQL.Error qualified as HGE
import Hasura.Backends.MSSQL.ToQuery (fromTableName, toQueryFlat)
import Hasura.Backends.MSSQL.Types (SchemaName (..), TableName (..))
import Hasura.Backends.MSSQL.Types.Internal (columnNameText, geoTypes)
import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.EventTrigger
import Hasura.RQL.Types.Eventing (EventId (..), OpVar (..))
import Hasura.RQL.Types.Source
import Hasura.RQL.Types.Table (PrimaryKey (..))
import Hasura.SQL.Backend
import Hasura.Server.Types
import Hasura.Session
import Hasura.Tracing qualified as Tracing
import Text.Shakespeare.Text qualified as ST
fetchUndeliveredEvents ::
(MonadIO m, MonadError QErr m) =>
MSSQLSourceConfig ->
SourceName ->
[TriggerName] ->
MaintenanceMode () ->
FetchBatchSize ->
m [Event 'MSSQL]
fetchUndeliveredEvents :: MSSQLSourceConfig
-> SourceName
-> [TriggerName]
-> MaintenanceMode ()
-> FetchBatchSize
-> m [Event 'MSSQL]
fetchUndeliveredEvents MSSQLSourceConfig
sourceConfig SourceName
sourceName [TriggerName]
triggerNames MaintenanceMode ()
_ FetchBatchSize
fetchBatchSize = do
m (Either QErr [Event 'MSSQL]) -> m [Event 'MSSQL]
forall e (m :: * -> *) a. MonadError e m => m (Either e a) -> m a
liftEitherM (m (Either QErr [Event 'MSSQL]) -> m [Event 'MSSQL])
-> m (Either QErr [Event 'MSSQL]) -> m [Event 'MSSQL]
forall a b. (a -> b) -> a -> b
$
IO (Either QErr [Event 'MSSQL]) -> m (Either QErr [Event 'MSSQL])
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr [Event 'MSSQL]) -> m (Either QErr [Event 'MSSQL]))
-> IO (Either QErr [Event 'MSSQL])
-> m (Either QErr [Event 'MSSQL])
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig
-> TxET QErr IO [Event 'MSSQL] -> IO (Either QErr [Event 'MSSQL])
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxET QErr IO [Event 'MSSQL] -> IO (Either QErr [Event 'MSSQL]))
-> TxET QErr IO [Event 'MSSQL] -> IO (Either QErr [Event 'MSSQL])
forall a b. (a -> b) -> a -> b
$
SourceName
-> [TriggerName] -> FetchBatchSize -> TxET QErr IO [Event 'MSSQL]
fetchEvents SourceName
sourceName [TriggerName]
triggerNames FetchBatchSize
fetchBatchSize
setRetry ::
(MonadIO m, MonadError QErr m) =>
MSSQLSourceConfig ->
Event 'MSSQL ->
UTCTime ->
MaintenanceMode MaintenanceModeVersion ->
m ()
setRetry :: MSSQLSourceConfig
-> Event 'MSSQL
-> UTCTime
-> MaintenanceMode MaintenanceModeVersion
-> m ()
setRetry MSSQLSourceConfig
sourceConfig Event 'MSSQL
event UTCTime
retryTime MaintenanceMode MaintenanceModeVersion
maintenanceModeVersion = do
m (Either QErr ()) -> m ()
forall e (m :: * -> *) a. MonadError e m => m (Either e a) -> m a
liftEitherM (m (Either QErr ()) -> m ()) -> m (Either QErr ()) -> m ()
forall a b. (a -> b) -> a -> b
$
IO (Either QErr ()) -> m (Either QErr ())
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr ()) -> m (Either QErr ()))
-> IO (Either QErr ()) -> m (Either QErr ())
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig -> TxET QErr IO () -> IO (Either QErr ())
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxET QErr IO () -> IO (Either QErr ()))
-> TxET QErr IO () -> IO (Either QErr ())
forall a b. (a -> b) -> a -> b
$
Event 'MSSQL
-> UTCTime
-> MaintenanceMode MaintenanceModeVersion
-> TxET QErr IO ()
setRetryTx Event 'MSSQL
event UTCTime
retryTime MaintenanceMode MaintenanceModeVersion
maintenanceModeVersion
insertManualEvent ::
(MonadIO m, MonadError QErr m) =>
MSSQLSourceConfig ->
TableName ->
TriggerName ->
J.Value ->
UserInfo ->
Tracing.TraceContext ->
m EventId
insertManualEvent :: MSSQLSourceConfig
-> TableName
-> TriggerName
-> Value
-> UserInfo
-> TraceContext
-> m EventId
insertManualEvent MSSQLSourceConfig
sourceConfig TableName
tableName TriggerName
triggerName Value
payload UserInfo
_userInfo TraceContext
_traceCtx =
m (Either QErr EventId) -> m EventId
forall e (m :: * -> *) a. MonadError e m => m (Either e a) -> m a
liftEitherM (m (Either QErr EventId) -> m EventId)
-> m (Either QErr EventId) -> m EventId
forall a b. (a -> b) -> a -> b
$
IO (Either QErr EventId) -> m (Either QErr EventId)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr EventId) -> m (Either QErr EventId))
-> IO (Either QErr EventId) -> m (Either QErr EventId)
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig
-> TxET QErr IO EventId -> IO (Either QErr EventId)
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxET QErr IO EventId -> IO (Either QErr EventId))
-> TxET QErr IO EventId -> IO (Either QErr EventId)
forall a b. (a -> b) -> a -> b
$
TableName -> TriggerName -> Value -> TxET QErr IO EventId
insertMSSQLManualEventTx TableName
tableName TriggerName
triggerName Value
payload
getMaintenanceModeVersion ::
( MonadIO m,
MonadError QErr m
) =>
MSSQLSourceConfig ->
m MaintenanceModeVersion
getMaintenanceModeVersion :: MSSQLSourceConfig -> m MaintenanceModeVersion
getMaintenanceModeVersion MSSQLSourceConfig
sourceConfig =
m (Either QErr MaintenanceModeVersion) -> m MaintenanceModeVersion
forall e (m :: * -> *) a. MonadError e m => m (Either e a) -> m a
liftEitherM (m (Either QErr MaintenanceModeVersion)
-> m MaintenanceModeVersion)
-> m (Either QErr MaintenanceModeVersion)
-> m MaintenanceModeVersion
forall a b. (a -> b) -> a -> b
$
IO (Either QErr MaintenanceModeVersion)
-> m (Either QErr MaintenanceModeVersion)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr MaintenanceModeVersion)
-> m (Either QErr MaintenanceModeVersion))
-> IO (Either QErr MaintenanceModeVersion)
-> m (Either QErr MaintenanceModeVersion)
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig
-> TxET QErr IO MaintenanceModeVersion
-> IO (Either QErr MaintenanceModeVersion)
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceReadTx MSSQLSourceConfig
sourceConfig (TxET QErr IO MaintenanceModeVersion
-> IO (Either QErr MaintenanceModeVersion))
-> TxET QErr IO MaintenanceModeVersion
-> IO (Either QErr MaintenanceModeVersion)
forall a b. (a -> b) -> a -> b
$ TxET QErr IO MaintenanceModeVersion
getMaintenanceModeVersionTx
recordSuccess ::
(MonadIO m) =>
MSSQLSourceConfig ->
Event 'MSSQL ->
Invocation 'EventType ->
MaintenanceMode MaintenanceModeVersion ->
m (Either QErr ())
recordSuccess :: MSSQLSourceConfig
-> Event 'MSSQL
-> Invocation 'EventType
-> MaintenanceMode MaintenanceModeVersion
-> m (Either QErr ())
recordSuccess MSSQLSourceConfig
sourceConfig Event 'MSSQL
event Invocation 'EventType
invocation MaintenanceMode MaintenanceModeVersion
maintenanceModeVersion =
IO (Either QErr ()) -> m (Either QErr ())
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr ()) -> m (Either QErr ()))
-> IO (Either QErr ()) -> m (Either QErr ())
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig -> TxET QErr IO () -> IO (Either QErr ())
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxET QErr IO () -> IO (Either QErr ()))
-> TxET QErr IO () -> IO (Either QErr ())
forall a b. (a -> b) -> a -> b
$ do
Invocation 'EventType -> TxET QErr IO ()
insertInvocation Invocation 'EventType
invocation
Event 'MSSQL
-> MaintenanceMode MaintenanceModeVersion -> TxET QErr IO ()
setSuccessTx Event 'MSSQL
event MaintenanceMode MaintenanceModeVersion
maintenanceModeVersion
recordError ::
(MonadIO m) =>
MSSQLSourceConfig ->
Event 'MSSQL ->
Invocation 'EventType ->
ProcessEventError ->
MaintenanceMode MaintenanceModeVersion ->
m (Either QErr ())
recordError :: MSSQLSourceConfig
-> Event 'MSSQL
-> Invocation 'EventType
-> ProcessEventError
-> MaintenanceMode MaintenanceModeVersion
-> m (Either QErr ())
recordError MSSQLSourceConfig
sourceConfig Event 'MSSQL
event Invocation 'EventType
invocation ProcessEventError
processEventError MaintenanceMode MaintenanceModeVersion
maintenanceModeVersion =
MSSQLSourceConfig
-> Event 'MSSQL
-> Maybe (Invocation 'EventType)
-> ProcessEventError
-> MaintenanceMode MaintenanceModeVersion
-> m (Either QErr ())
forall (m :: * -> *).
MonadIO m =>
MSSQLSourceConfig
-> Event 'MSSQL
-> Maybe (Invocation 'EventType)
-> ProcessEventError
-> MaintenanceMode MaintenanceModeVersion
-> m (Either QErr ())
recordError' MSSQLSourceConfig
sourceConfig Event 'MSSQL
event (Invocation 'EventType -> Maybe (Invocation 'EventType)
forall a. a -> Maybe a
Just Invocation 'EventType
invocation) ProcessEventError
processEventError MaintenanceMode MaintenanceModeVersion
maintenanceModeVersion
recordError' ::
(MonadIO m) =>
MSSQLSourceConfig ->
Event 'MSSQL ->
Maybe (Invocation 'EventType) ->
ProcessEventError ->
MaintenanceMode MaintenanceModeVersion ->
m (Either QErr ())
recordError' :: MSSQLSourceConfig
-> Event 'MSSQL
-> Maybe (Invocation 'EventType)
-> ProcessEventError
-> MaintenanceMode MaintenanceModeVersion
-> m (Either QErr ())
recordError' MSSQLSourceConfig
sourceConfig Event 'MSSQL
event Maybe (Invocation 'EventType)
invocation ProcessEventError
processEventError MaintenanceMode MaintenanceModeVersion
maintenanceModeVersion =
IO (Either QErr ()) -> m (Either QErr ())
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr ()) -> m (Either QErr ()))
-> IO (Either QErr ()) -> m (Either QErr ())
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig -> TxET QErr IO () -> IO (Either QErr ())
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxET QErr IO () -> IO (Either QErr ()))
-> TxET QErr IO () -> IO (Either QErr ())
forall a b. (a -> b) -> a -> b
$ do
Maybe (Invocation 'EventType)
-> (Invocation 'EventType -> TxET QErr IO ()) -> TxET QErr IO ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
onJust Maybe (Invocation 'EventType)
invocation Invocation 'EventType -> TxET QErr IO ()
insertInvocation
case ProcessEventError
processEventError of
PESetRetry UTCTime
retryTime -> do
Event 'MSSQL
-> UTCTime
-> MaintenanceMode MaintenanceModeVersion
-> TxET QErr IO ()
setRetryTx Event 'MSSQL
event UTCTime
retryTime MaintenanceMode MaintenanceModeVersion
maintenanceModeVersion
ProcessEventError
PESetError -> Event 'MSSQL
-> MaintenanceMode MaintenanceModeVersion -> TxET QErr IO ()
setErrorTx Event 'MSSQL
event MaintenanceMode MaintenanceModeVersion
maintenanceModeVersion
redeliverEvent ::
(MonadIO m, MonadError QErr m) =>
MSSQLSourceConfig ->
EventId ->
m ()
redeliverEvent :: MSSQLSourceConfig -> EventId -> m ()
redeliverEvent MSSQLSourceConfig
sourceConfig EventId
eventId =
m (Either QErr ()) -> m ()
forall e (m :: * -> *) a. MonadError e m => m (Either e a) -> m a
liftEitherM (m (Either QErr ()) -> m ()) -> m (Either QErr ()) -> m ()
forall a b. (a -> b) -> a -> b
$
IO (Either QErr ()) -> m (Either QErr ())
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr ()) -> m (Either QErr ()))
-> IO (Either QErr ()) -> m (Either QErr ())
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig -> TxET QErr IO () -> IO (Either QErr ())
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxET QErr IO () -> IO (Either QErr ()))
-> TxET QErr IO () -> IO (Either QErr ())
forall a b. (a -> b) -> a -> b
$ do
EventId -> TxET QErr IO ()
checkEventTx EventId
eventId
EventId -> TxET QErr IO ()
markForDeliveryTx EventId
eventId
dropTriggerAndArchiveEvents ::
(MonadIO m, MonadError QErr m) =>
MSSQLSourceConfig ->
TriggerName ->
TableName ->
m ()
dropTriggerAndArchiveEvents :: MSSQLSourceConfig -> TriggerName -> TableName -> m ()
dropTriggerAndArchiveEvents MSSQLSourceConfig
sourceConfig TriggerName
triggerName TableName
table =
m (Either QErr ()) -> m ()
forall e (m :: * -> *) a. MonadError e m => m (Either e a) -> m a
liftEitherM (m (Either QErr ()) -> m ()) -> m (Either QErr ()) -> m ()
forall a b. (a -> b) -> a -> b
$
IO (Either QErr ()) -> m (Either QErr ())
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr ()) -> m (Either QErr ()))
-> IO (Either QErr ()) -> m (Either QErr ())
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig -> TxET QErr IO () -> IO (Either QErr ())
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxET QErr IO () -> IO (Either QErr ()))
-> TxET QErr IO () -> IO (Either QErr ())
forall a b. (a -> b) -> a -> b
$ do
TriggerName -> SchemaName -> TxET QErr IO ()
dropTriggerQ TriggerName
triggerName (TableName -> SchemaName
tableSchema TableName
table)
TriggerName -> TxET QErr IO ()
archiveEvents TriggerName
triggerName
dropDanglingSQLTrigger ::
(MonadIO m, MonadError QErr m) =>
MSSQLSourceConfig ->
TriggerName ->
TableName ->
HashSet Ops ->
m ()
dropDanglingSQLTrigger :: MSSQLSourceConfig
-> TriggerName -> TableName -> HashSet Ops -> m ()
dropDanglingSQLTrigger MSSQLSourceConfig
sourceConfig TriggerName
triggerName TableName
table HashSet Ops
ops =
m (Either QErr ()) -> m ()
forall e (m :: * -> *) a. MonadError e m => m (Either e a) -> m a
liftEitherM (m (Either QErr ()) -> m ()) -> m (Either QErr ()) -> m ()
forall a b. (a -> b) -> a -> b
$
IO (Either QErr ()) -> m (Either QErr ())
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr ()) -> m (Either QErr ()))
-> IO (Either QErr ()) -> m (Either QErr ())
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig -> TxET QErr IO () -> IO (Either QErr ())
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxET QErr IO () -> IO (Either QErr ()))
-> TxET QErr IO () -> IO (Either QErr ())
forall a b. (a -> b) -> a -> b
$ do
(Ops -> TxET QErr IO ()) -> HashSet Ops -> TxET QErr IO ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
(a -> f b) -> t a -> f ()
traverse_ (TriggerName -> SchemaName -> Ops -> TxET QErr IO ()
dropTriggerOp TriggerName
triggerName (TableName -> SchemaName
tableSchema TableName
table)) HashSet Ops
ops
createTableEventTrigger ::
MonadIO m =>
ServerConfigCtx ->
MSSQLSourceConfig ->
TableName ->
[ColumnInfo 'MSSQL] ->
TriggerName ->
TriggerOpsDef 'MSSQL ->
Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)) ->
m (Either QErr ())
createTableEventTrigger :: ServerConfigCtx
-> MSSQLSourceConfig
-> TableName
-> [ColumnInfo 'MSSQL]
-> TriggerName
-> TriggerOpsDef 'MSSQL
-> Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
-> m (Either QErr ())
createTableEventTrigger ServerConfigCtx
_serverConfigCtx MSSQLSourceConfig
sourceConfig TableName
table [ColumnInfo 'MSSQL]
columns TriggerName
triggerName TriggerOpsDef 'MSSQL
opsDefinition Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
primaryKeyMaybe = do
IO (Either QErr ()) -> m (Either QErr ())
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr ()) -> m (Either QErr ()))
-> IO (Either QErr ()) -> m (Either QErr ())
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig -> TxET QErr IO () -> IO (Either QErr ())
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxET QErr IO () -> IO (Either QErr ()))
-> TxET QErr IO () -> IO (Either QErr ())
forall a b. (a -> b) -> a -> b
$ do
TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> TriggerOpsDef 'MSSQL
-> Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
-> TxET QErr IO ()
forall (m :: * -> *).
MonadMSSQLTx m =>
TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> TriggerOpsDef 'MSSQL
-> Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
-> m ()
mkAllTriggersQ TriggerName
triggerName TableName
table [ColumnInfo 'MSSQL]
columns TriggerOpsDef 'MSSQL
opsDefinition Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
primaryKeyMaybe
createMissingSQLTriggers ::
( MonadIO m,
MonadError QErr m,
MonadBaseControl IO m
) =>
MSSQLSourceConfig ->
TableName ->
([ColumnInfo 'MSSQL], Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))) ->
TriggerName ->
TriggerOpsDef 'MSSQL ->
m ()
createMissingSQLTriggers :: MSSQLSourceConfig
-> TableName
-> ([ColumnInfo 'MSSQL],
Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)))
-> TriggerName
-> TriggerOpsDef 'MSSQL
-> m ()
createMissingSQLTriggers MSSQLSourceConfig
sourceConfig table :: TableName
table@(TableName Text
tableNameText (SchemaName Text
schemaText)) ([ColumnInfo 'MSSQL]
allCols, Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
primaryKeyMaybe) TriggerName
triggerName TriggerOpsDef 'MSSQL
opsDefinition = do
m (Either QErr ()) -> m ()
forall e (m :: * -> *) a. MonadError e m => m (Either e a) -> m a
liftEitherM (m (Either QErr ()) -> m ()) -> m (Either QErr ()) -> m ()
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig -> TxET QErr m () -> m (Either QErr ())
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxET QErr m () -> m (Either QErr ()))
-> TxET QErr m () -> m (Either QErr ())
forall a b. (a -> b) -> a -> b
$ do
Maybe (SubscribeOpSpec 'MSSQL)
-> (SubscribeOpSpec 'MSSQL -> TxET QErr m ()) -> TxET QErr m ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
onJust (TriggerOpsDef 'MSSQL -> Maybe (SubscribeOpSpec 'MSSQL)
forall (b :: BackendType).
TriggerOpsDef b -> Maybe (SubscribeOpSpec b)
tdInsert TriggerOpsDef 'MSSQL
opsDefinition) (Ops -> SubscribeOpSpec 'MSSQL -> TxET QErr m ()
doesSQLTriggerExist Ops
INSERT)
Maybe (SubscribeOpSpec 'MSSQL)
-> (SubscribeOpSpec 'MSSQL -> TxET QErr m ()) -> TxET QErr m ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
onJust (TriggerOpsDef 'MSSQL -> Maybe (SubscribeOpSpec 'MSSQL)
forall (b :: BackendType).
TriggerOpsDef b -> Maybe (SubscribeOpSpec b)
tdUpdate TriggerOpsDef 'MSSQL
opsDefinition) (Ops -> SubscribeOpSpec 'MSSQL -> TxET QErr m ()
doesSQLTriggerExist Ops
UPDATE)
Maybe (SubscribeOpSpec 'MSSQL)
-> (SubscribeOpSpec 'MSSQL -> TxET QErr m ()) -> TxET QErr m ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
onJust (TriggerOpsDef 'MSSQL -> Maybe (SubscribeOpSpec 'MSSQL)
forall (b :: BackendType).
TriggerOpsDef b -> Maybe (SubscribeOpSpec b)
tdDelete TriggerOpsDef 'MSSQL
opsDefinition) (Ops -> SubscribeOpSpec 'MSSQL -> TxET QErr m ()
doesSQLTriggerExist Ops
DELETE)
where
doesSQLTriggerExist :: Ops -> SubscribeOpSpec 'MSSQL -> TxET QErr m ()
doesSQLTriggerExist Ops
op SubscribeOpSpec 'MSSQL
opSpec = do
let triggerNameWithOp :: Text
triggerNameWithOp = Text
"notify_hasura_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TriggerName -> Text
triggerNameToTxt TriggerName
triggerName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Ops -> Text
forall a. Show a => a -> Text
tshow Ops
op
Bool
doesOpTriggerExist <-
TxE QErr Bool -> TxET QErr m Bool
forall (m :: * -> *) a. MonadMSSQLTx m => TxE QErr a -> m a
liftMSSQLTx (TxE QErr Bool -> TxET QErr m Bool)
-> TxE QErr Bool -> TxET QErr m Bool
forall a b. (a -> b) -> a -> b
$
(MSSQLTxError -> QErr) -> Query -> TxE QErr Bool
forall (m :: * -> *) a e.
(MonadIO m, FromRow a) =>
(MSSQLTxError -> e) -> Query -> TxET e m a
singleRowQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
[ODBC.sql|
SELECT CASE WHEN EXISTS
( SELECT 1
FROM sys.triggers tr
INNER join sys.tables tb on tr.parent_id = tb.object_id
INNER join sys.schemas s on tb.schema_id = s.schema_id
WHERE tb.name = $tableNameText AND tr.name = $triggerNameWithOp AND s.name = $schemaText
)
THEN CAST(1 AS BIT)
ELSE CAST(0 AS BIT)
END;
|]
Bool -> TxET QErr m () -> TxET QErr m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
doesOpTriggerExist (TxET QErr m () -> TxET QErr m ())
-> TxET QErr m () -> TxET QErr m ()
forall a b. (a -> b) -> a -> b
$ do
case Ops
op of
Ops
INSERT -> TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> SubscribeOpSpec 'MSSQL
-> TxET QErr m ()
forall (m :: * -> *).
MonadMSSQLTx m =>
TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> SubscribeOpSpec 'MSSQL
-> m ()
mkInsertTriggerQ TriggerName
triggerName TableName
table [ColumnInfo 'MSSQL]
allCols SubscribeOpSpec 'MSSQL
opSpec
Ops
UPDATE -> TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
-> SubscribeOpSpec 'MSSQL
-> TxET QErr m ()
forall (m :: * -> *).
MonadMSSQLTx m =>
TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
-> SubscribeOpSpec 'MSSQL
-> m ()
mkUpdateTriggerQ TriggerName
triggerName TableName
table [ColumnInfo 'MSSQL]
allCols Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
primaryKeyMaybe SubscribeOpSpec 'MSSQL
opSpec
Ops
DELETE -> TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> SubscribeOpSpec 'MSSQL
-> TxET QErr m ()
forall (m :: * -> *).
MonadMSSQLTx m =>
TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> SubscribeOpSpec 'MSSQL
-> m ()
mkDeleteTriggerQ TriggerName
triggerName TableName
table [ColumnInfo 'MSSQL]
allCols SubscribeOpSpec 'MSSQL
opSpec
Ops
MANUAL -> () -> TxET QErr m ()
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
unlockEventsInSource ::
MonadIO m =>
MSSQLSourceConfig ->
NE.NESet EventId ->
m (Either QErr Int)
unlockEventsInSource :: MSSQLSourceConfig -> NESet EventId -> m (Either QErr Int)
unlockEventsInSource MSSQLSourceConfig
sourceConfig NESet EventId
eventIds =
IO (Either QErr Int) -> m (Either QErr Int)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr Int) -> m (Either QErr Int))
-> IO (Either QErr Int) -> m (Either QErr Int)
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig -> TxET QErr IO Int -> IO (Either QErr Int)
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxET QErr IO Int -> IO (Either QErr Int))
-> TxET QErr IO Int -> IO (Either QErr Int)
forall a b. (a -> b) -> a -> b
$ do
[EventId] -> TxET QErr IO Int
unlockEventsTx ([EventId] -> TxET QErr IO Int) -> [EventId] -> TxET QErr IO Int
forall a b. (a -> b) -> a -> b
$ NESet EventId -> [EventId]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList NESet EventId
eventIds
checkIfTriggerExists ::
(MonadIO m, MonadError QErr m) =>
MSSQLSourceConfig ->
TriggerName ->
HashSet Ops ->
m Bool
checkIfTriggerExists :: MSSQLSourceConfig -> TriggerName -> HashSet Ops -> m Bool
checkIfTriggerExists MSSQLSourceConfig
sourceConfig TriggerName
triggerName HashSet Ops
ops = do
m (Either QErr Bool) -> m Bool
forall e (m :: * -> *) a. MonadError e m => m (Either e a) -> m a
liftEitherM (m (Either QErr Bool) -> m Bool) -> m (Either QErr Bool) -> m Bool
forall a b. (a -> b) -> a -> b
$
IO (Either QErr Bool) -> m (Either QErr Bool)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr Bool) -> m (Either QErr Bool))
-> IO (Either QErr Bool) -> m (Either QErr Bool)
forall a b. (a -> b) -> a -> b
$
MSSQLSourceConfig -> TxE QErr Bool -> IO (Either QErr Bool)
forall (m :: * -> *) a.
(MonadIO m, MonadBaseControl IO m) =>
MSSQLSourceConfig -> TxET QErr m a -> m (Either QErr a)
runMSSQLSourceWriteTx MSSQLSourceConfig
sourceConfig (TxE QErr Bool -> IO (Either QErr Bool))
-> TxE QErr Bool -> IO (Either QErr Bool)
forall a b. (a -> b) -> a -> b
$
([Bool] -> Bool) -> TxET QErr IO [Bool] -> TxE QErr Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [Bool] -> Bool
forall (t :: * -> *). Foldable t => t Bool -> Bool
or ((Ops -> TxE QErr Bool) -> [Ops] -> TxET QErr IO [Bool]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (TriggerName -> Ops -> TxE QErr Bool
checkIfTriggerExistsQ TriggerName
triggerName) (HashSet Ops -> [Ops]
forall a. HashSet a -> [a]
HashSet.toList HashSet Ops
ops))
insertInvocation :: Invocation 'EventType -> TxE QErr ()
insertInvocation :: Invocation 'EventType -> TxET QErr IO ()
insertInvocation Invocation 'EventType
invo = do
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
[ODBC.sql|
INSERT INTO hdb_catalog.event_invocation_logs (event_id, status, request, response)
VALUES ($invoEventId, $invoStatus, $invoRequest, $invoResponse)
|]
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
[ODBC.sql|
UPDATE hdb_catalog.event_log
SET tries = tries + 1
WHERE id = $invoEventId
|]
where
invoEventId :: Text
invoEventId = EventId -> Text
unEventId (EventId -> Text) -> EventId -> Text
forall a b. (a -> b) -> a -> b
$ Invocation 'EventType -> EventId
forall (a :: TriggerTypes). Invocation a -> EventId
iEventId Invocation 'EventType
invo
invoStatus :: Maybe Int
invoStatus = Int -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Int) -> Maybe Int -> Maybe Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Invocation 'EventType -> Maybe Int
forall (a :: TriggerTypes). Invocation a -> Maybe Int
iStatus Invocation 'EventType
invo :: Maybe Int
invoRequest :: ByteString
invoRequest = Value -> ByteString
forall a. ToJSON a => a -> ByteString
J.encode (Value -> ByteString) -> Value -> ByteString
forall a b. (a -> b) -> a -> b
$ WebhookRequest -> Value
forall a. ToJSON a => a -> Value
J.toJSON (WebhookRequest -> Value) -> WebhookRequest -> Value
forall a b. (a -> b) -> a -> b
$ Invocation 'EventType -> WebhookRequest
forall (a :: TriggerTypes). Invocation a -> WebhookRequest
iRequest Invocation 'EventType
invo
invoResponse :: ByteString
invoResponse = Value -> ByteString
forall a. ToJSON a => a -> ByteString
J.encode (Value -> ByteString) -> Value -> ByteString
forall a b. (a -> b) -> a -> b
$ Response 'EventType -> Value
forall a. ToJSON a => a -> Value
J.toJSON (Response 'EventType -> Value) -> Response 'EventType -> Value
forall a b. (a -> b) -> a -> b
$ Invocation 'EventType -> Response 'EventType
forall (a :: TriggerTypes). Invocation a -> Response a
iResponse Invocation 'EventType
invo
insertMSSQLManualEventTx ::
TableName ->
TriggerName ->
J.Value ->
TxE QErr EventId
insertMSSQLManualEventTx :: TableName -> TriggerName -> Value -> TxET QErr IO EventId
insertMSSQLManualEventTx (TableName Text
tableName (SchemaName Text
schemaName)) TriggerName
triggerName Value
rowData = do
ByteString
eventId <-
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ByteString
forall (m :: * -> *) a e.
(MonadIO m, FromRow a) =>
(MSSQLTxError -> e) -> Query -> TxET e m a
singleRowQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
[ODBC.sql|
INSERT INTO hdb_catalog.event_log (schema_name, table_name, trigger_name, payload)
OUTPUT CONVERT(varchar(MAX), inserted.id)
VALUES
($schemaName, $tableName, $triggerNameTxt, $payload)
|]
EventId -> TxET QErr IO EventId
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> EventId
EventId (ByteString -> Text
bsToTxt ByteString
eventId))
where
triggerNameTxt :: Text
triggerNameTxt = TriggerName -> Text
triggerNameToTxt TriggerName
triggerName
payload :: ByteString
payload = Value -> ByteString
forall a. ToJSON a => a -> ByteString
J.encode Value
rowData
setSuccessTx :: Event 'MSSQL -> MaintenanceMode MaintenanceModeVersion -> TxE QErr ()
setSuccessTx :: Event 'MSSQL
-> MaintenanceMode MaintenanceModeVersion -> TxET QErr IO ()
setSuccessTx Event 'MSSQL
event = \case
(MaintenanceModeEnabled MaintenanceModeVersion
PreviousMMVersion) -> Text -> TxET QErr IO ()
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 Text
"unexpected: no previous maintenance mode version found for MSSQL source"
(MaintenanceModeEnabled MaintenanceModeVersion
CurrentMMVersion) -> TxET QErr IO ()
latestVersionSetSuccess
MaintenanceMode MaintenanceModeVersion
MaintenanceModeDisabled -> TxET QErr IO ()
latestVersionSetSuccess
where
eventId :: Text
eventId = EventId -> Text
unEventId (EventId -> Text) -> EventId -> Text
forall a b. (a -> b) -> a -> b
$ Event 'MSSQL -> EventId
forall (b :: BackendType). Event b -> EventId
eId Event 'MSSQL
event
latestVersionSetSuccess :: TxET QErr IO ()
latestVersionSetSuccess =
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
[ODBC.sql|
UPDATE hdb_catalog.event_log
SET delivered = 1 , next_retry_at = NULL, locked = NULL
WHERE id = $eventId
|]
setErrorTx :: Event 'MSSQL -> MaintenanceMode MaintenanceModeVersion -> TxE QErr ()
setErrorTx :: Event 'MSSQL
-> MaintenanceMode MaintenanceModeVersion -> TxET QErr IO ()
setErrorTx Event 'MSSQL
event = \case
(MaintenanceModeEnabled MaintenanceModeVersion
PreviousMMVersion) -> Text -> TxET QErr IO ()
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 Text
"unexpected: there is no previous maintenance mode version supported for MSSQL event triggers"
(MaintenanceModeEnabled MaintenanceModeVersion
CurrentMMVersion) -> TxET QErr IO ()
latestVersionSetSuccess
MaintenanceMode MaintenanceModeVersion
MaintenanceModeDisabled -> TxET QErr IO ()
latestVersionSetSuccess
where
eventId :: Text
eventId = EventId -> Text
unEventId (EventId -> Text) -> EventId -> Text
forall a b. (a -> b) -> a -> b
$ Event 'MSSQL -> EventId
forall (b :: BackendType). Event b -> EventId
eId Event 'MSSQL
event
latestVersionSetSuccess :: TxET QErr IO ()
latestVersionSetSuccess =
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
[ODBC.sql|
UPDATE hdb_catalog.event_log
SET error = 1 , next_retry_at = NULL, locked = NULL
WHERE id = $eventId
|]
setRetryTx :: Event 'MSSQL -> UTCTime -> MaintenanceMode MaintenanceModeVersion -> TxE QErr ()
setRetryTx :: Event 'MSSQL
-> UTCTime
-> MaintenanceMode MaintenanceModeVersion
-> TxET QErr IO ()
setRetryTx Event 'MSSQL
event UTCTime
utcTime MaintenanceMode MaintenanceModeVersion
maintenanceMode = do
Datetime2
time <- UTCTime -> TxET QErr IO Datetime2
forall (m :: * -> *). MonadIO m => UTCTime -> m Datetime2
convertUTCToDatetime2 UTCTime
utcTime
case MaintenanceMode MaintenanceModeVersion
maintenanceMode of
(MaintenanceModeEnabled MaintenanceModeVersion
PreviousMMVersion) -> Text -> TxET QErr IO ()
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 Text
"unexpected: there is no previous maintenance mode version supported for MSSQL event triggers"
(MaintenanceModeEnabled MaintenanceModeVersion
CurrentMMVersion) -> Datetime2 -> TxET QErr IO ()
latestVersionSetRetry Datetime2
time
MaintenanceMode MaintenanceModeVersion
MaintenanceModeDisabled -> Datetime2 -> TxET QErr IO ()
latestVersionSetRetry Datetime2
time
where
eventId :: Text
eventId = EventId -> Text
unEventId (EventId -> Text) -> EventId -> Text
forall a b. (a -> b) -> a -> b
$ Event 'MSSQL -> EventId
forall (b :: BackendType). Event b -> EventId
eId Event 'MSSQL
event
latestVersionSetRetry :: Datetime2 -> TxET QErr IO ()
latestVersionSetRetry Datetime2
time =
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
[ODBC.sql|
UPDATE hdb_catalog.event_log
SET next_retry_at = TODATETIMEOFFSET ($time, DATEPART(TZOFFSET, SYSDATETIMEOFFSET())), locked = NULL
WHERE id = $eventId
|]
fetchEvents :: SourceName -> [TriggerName] -> FetchBatchSize -> TxE QErr [Event 'MSSQL]
fetchEvents :: SourceName
-> [TriggerName] -> FetchBatchSize -> TxET QErr IO [Event 'MSSQL]
fetchEvents SourceName
source [TriggerName]
triggerNames (FetchBatchSize Int
fetchBatchSize) = do
[(ByteString, Text, Text, Text, ByteString, Int, ByteString)]
events <-
(MSSQLTxError -> QErr)
-> Query
-> TxET
QErr
IO
[(ByteString, Text, Text, Text, ByteString, Int, ByteString)]
forall (m :: * -> *) a e.
(MonadIO m, FromRow a) =>
(MSSQLTxError -> e) -> Query -> TxET e m [a]
multiRowQueryE MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler (Query
-> TxET
QErr
IO
[(ByteString, Text, Text, Text, ByteString, Int, ByteString)])
-> Query
-> TxET
QErr
IO
[(ByteString, Text, Text, Text, ByteString, Int, ByteString)]
forall a b. (a -> b) -> a -> b
$
Text -> Query
rawUnescapedText (Text -> Query) -> (Text -> Text) -> Text -> Query
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
LT.toStrict (Text -> Query) -> Text -> Query
forall a b. (a -> b) -> a -> b
$
$(makeRelativeToProject "src-rsr/mssql/mssql_fetch_events.sql.shakespeare" >>= ST.stextFile)
((ByteString, Text, Text, Text, ByteString, Int, ByteString)
-> TxET QErr IO (Event 'MSSQL))
-> [(ByteString, Text, Text, Text, ByteString, Int, ByteString)]
-> TxET QErr IO [Event 'MSSQL]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (ByteString, Text, Text, Text, ByteString, Int, ByteString)
-> TxET QErr IO (Event 'MSSQL)
uncurryEvent [(ByteString, Text, Text, Text, ByteString, Int, ByteString)]
events
where
triggerNamesTxt :: Text
triggerNamesTxt = Text
"(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [Text] -> Text
forall t (f :: * -> *). (ToTxt t, Foldable f) => f t -> Text
commaSeparated ((TriggerName -> Text) -> [TriggerName] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (\TriggerName
t -> Text
"'" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TriggerName -> Text
forall a. ToTxt a => a -> Text
toTxt TriggerName
t Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"'") [TriggerName]
triggerNames) Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")"
uncurryEvent :: (ByteString, Text, Text, Text, ByteString, Int, ByteString)
-> TxET QErr IO (Event 'MSSQL)
uncurryEvent (ByteString
id', Text
sn, Text
tn, Text
trn, ByteString
payload' :: BL.ByteString, Int
tries, ByteString
created_at :: B.ByteString) = do
Value
payload <- ByteString -> TxET QErr IO Value
forall a (m :: * -> *). (FromJSON a, QErrM m) => ByteString -> m a
encodePayload ByteString
payload'
UTCTime
createdAt <- ByteString -> TxET QErr IO UTCTime
forall (m :: * -> *). QErrM m => ByteString -> m UTCTime
convertTime ByteString
created_at
Event 'MSSQL -> TxET QErr IO (Event 'MSSQL)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Event 'MSSQL -> TxET QErr IO (Event 'MSSQL))
-> Event 'MSSQL -> TxET QErr IO (Event 'MSSQL)
forall a b. (a -> b) -> a -> b
$
Event :: forall (b :: BackendType).
EventId
-> SourceName
-> TableName b
-> TriggerMetadata
-> Value
-> Int
-> UTCTime
-> Event b
Event
{ eId :: EventId
eId = Text -> EventId
EventId (ByteString -> Text
bsToTxt ByteString
id'),
eSource :: SourceName
eSource = SourceName
source,
eTable :: TableName 'MSSQL
eTable = (Text -> SchemaName -> TableName
TableName Text
tn (Text -> SchemaName
SchemaName Text
sn)),
eTrigger :: TriggerMetadata
eTrigger = TriggerName -> TriggerMetadata
TriggerMetadata (NonEmptyText -> TriggerName
TriggerName (NonEmptyText -> TriggerName) -> NonEmptyText -> TriggerName
forall a b. (a -> b) -> a -> b
$ Text -> NonEmptyText
mkNonEmptyTextUnsafe Text
trn),
eEvent :: Value
eEvent = Value
payload,
eTries :: Int
eTries = Int
tries,
eCreatedAt :: UTCTime
eCreatedAt = UTCTime
createdAt
}
encodePayload :: (J.FromJSON a, QErrM m) => BL.ByteString -> m a
encodePayload :: ByteString -> m a
encodePayload ByteString
payload =
Either String a -> (String -> m a) -> m a
forall (m :: * -> *) e a.
Applicative m =>
Either e a -> (e -> m a) -> m a
onLeft
(ByteString -> Either String a
forall a. FromJSON a => ByteString -> Either String a
J.eitherDecode ByteString
payload)
(\String
_ -> Text -> m a
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 (Text -> m a) -> Text -> m a
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack String
"payload decode failed while fetching MSSQL events")
convertTime :: (QErrM m) => B.ByteString -> m UTCTime
convertTime :: ByteString -> m UTCTime
convertTime ByteString
createdAt =
Either String UTCTime -> (String -> m UTCTime) -> m UTCTime
forall (m :: * -> *) e a.
Applicative m =>
Either e a -> (e -> m a) -> m a
onLeft
(String -> Either String UTCTime
forall a. Read a => String -> Either String a
readEither (Text -> String
T.unpack (Text -> String) -> Text -> String
forall a b. (a -> b) -> a -> b
$ ByteString -> Text
bsToTxt ByteString
createdAt) :: Either String UTCTime)
(\String
_ -> Text -> m UTCTime
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 (Text -> m UTCTime) -> Text -> m UTCTime
forall a b. (a -> b) -> a -> b
$ String -> Text
T.pack String
"conversion to UTCTime failed while fetching MSSQL events")
dropTriggerQ :: TriggerName -> SchemaName -> TxE QErr ()
dropTriggerQ :: TriggerName -> SchemaName -> TxET QErr IO ()
dropTriggerQ TriggerName
triggerName SchemaName
schemaName =
(Ops -> TxET QErr IO ()) -> [Ops] -> TxET QErr IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (TriggerName -> SchemaName -> Ops -> TxET QErr IO ()
dropTriggerOp TriggerName
triggerName SchemaName
schemaName) [Ops
INSERT, Ops
UPDATE, Ops
DELETE]
dropTriggerOp :: TriggerName -> SchemaName -> Ops -> TxE QErr ()
dropTriggerOp :: TriggerName -> SchemaName -> Ops -> TxET QErr IO ()
dropTriggerOp TriggerName
triggerName SchemaName
schemaName Ops
triggerOp =
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
(Text -> Query
rawUnescapedText (Text -> Query) -> Text -> Query
forall a b. (a -> b) -> a -> b
$ Ops -> Text
getDropTriggerSQL Ops
triggerOp)
where
getDropTriggerSQL :: Ops -> Text
getDropTriggerSQL :: Ops -> Text
getDropTriggerSQL Ops
op =
Text
"DROP TRIGGER IF EXISTS " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> QualifiedTriggerName -> Text
unQualifiedTriggerName (Ops -> SchemaName -> TriggerName -> QualifiedTriggerName
msssqlIdenTrigger Ops
op SchemaName
schemaName TriggerName
triggerName)
archiveEvents :: TriggerName -> TxE QErr ()
archiveEvents :: TriggerName -> TxET QErr IO ()
archiveEvents TriggerName
triggerName =
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
[ODBC.sql|
UPDATE hdb_catalog.event_log
SET archived = 1
WHERE trigger_name = $triggerNameTxt
|]
where
triggerNameTxt :: Text
triggerNameTxt = TriggerName -> Text
triggerNameToTxt TriggerName
triggerName
checkEventTx :: EventId -> TxE QErr ()
checkEventTx :: EventId -> TxET QErr IO ()
checkEventTx EventId
eventId = do
([Bool]
events :: [Bool]) <-
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO [Bool]
forall (m :: * -> *) a e.
(MonadIO m, FromRow a) =>
(MSSQLTxError -> e) -> Query -> TxET e m [a]
multiRowQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
[ODBC.sql|
SELECT
CAST(CASE
WHEN (l.locked IS NOT NULL AND l.locked >= DATEADD(MINUTE, -30, SYSDATETIMEOFFSET())) THEN 1 ELSE 0
END
AS bit)
FROM hdb_catalog.event_log l
WHERE l.id = $eId
|]
Bool
event <- [Bool] -> TxE QErr Bool
forall (m :: * -> *) a. MonadError QErr m => [a] -> m a
getEvent [Bool]
events
Bool -> TxET QErr IO ()
forall (f :: * -> *). MonadError QErr f => Bool -> f ()
assertEventUnlocked Bool
event
where
eId :: Text
eId = EventId -> Text
unEventId (EventId -> Text) -> EventId -> Text
forall a b. (a -> b) -> a -> b
$ EventId
eventId
getEvent :: [a] -> m a
getEvent [] = Code -> Text -> m a
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotExists Text
"event not found"
getEvent (a
x : [a]
_) = a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
assertEventUnlocked :: Bool -> f ()
assertEventUnlocked Bool
locked =
Bool -> f () -> f ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
locked (f () -> f ()) -> f () -> f ()
forall a b. (a -> b) -> a -> b
$
Code -> Text -> f ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
Busy Text
"event is already being processed"
markForDeliveryTx :: EventId -> TxE QErr ()
markForDeliveryTx :: EventId -> TxET QErr IO ()
markForDeliveryTx EventId
eventId = do
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
[ODBC.sql|
UPDATE hdb_catalog.event_log
SET delivered = 0, error = 0, tries = 0
WHERE id = $eId
|]
where
eId :: Text
eId = EventId -> Text
unEventId (EventId -> Text) -> EventId -> Text
forall a b. (a -> b) -> a -> b
$ EventId
eventId
unlockEventsTx :: [EventId] -> TxE QErr Int
unlockEventsTx :: [EventId] -> TxET QErr IO Int
unlockEventsTx [EventId]
eventIds = do
Int
numEvents <-
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO Int
forall (m :: * -> *) a e.
(MonadIO m, FromRow a) =>
(MSSQLTxError -> e) -> Query -> TxET e m a
singleRowQueryE MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler (Query -> TxET QErr IO Int) -> Query -> TxET QErr IO Int
forall a b. (a -> b) -> a -> b
$
Text -> Query
rawUnescapedText (Text -> Query) -> (Text -> Text) -> Text -> Query
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
LT.toStrict (Text -> Query) -> Text -> Query
forall a b. (a -> b) -> a -> b
$
let eventIdsValues :: Text
eventIdsValues = [EventId] -> Text
generateValuesFromEvents [EventId]
eventIds
in $(makeRelativeToProject "src-rsr/mssql/mssql_unlock_events.sql.shakespeare" >>= ST.stextFile)
Int -> TxET QErr IO Int
forall (m :: * -> *) a. Monad m => a -> m a
return Int
numEvents
where
generateValuesFromEvents :: [EventId] -> Text
generateValuesFromEvents :: [EventId] -> Text
generateValuesFromEvents [EventId]
events = [Text] -> Text
forall t (f :: * -> *). (ToTxt t, Foldable f) => f t -> Text
commaSeparated [Text]
values
where
values :: [Text]
values = (EventId -> Text) -> [EventId] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (\EventId
e -> Text
"(" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> EventId -> Text
forall a. ToTxt a => a -> Text
toTxt EventId
e Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
")") [EventId]
events
getMaintenanceModeVersionTx :: TxE QErr MaintenanceModeVersion
getMaintenanceModeVersionTx :: TxET QErr IO MaintenanceModeVersion
getMaintenanceModeVersionTx = do
SourceCatalogVersion
catalogVersion <- TxET QErr IO SourceCatalogVersion
forall (m :: * -> *). MonadMSSQLTx m => m SourceCatalogVersion
getSourceCatalogVersion
if
| SourceCatalogVersion
catalogVersion SourceCatalogVersion -> SourceCatalogVersion -> Bool
forall a. Eq a => a -> a -> Bool
== SourceCatalogVersion
latestSourceCatalogVersion -> MaintenanceModeVersion -> TxET QErr IO MaintenanceModeVersion
forall (f :: * -> *) a. Applicative f => a -> f a
pure MaintenanceModeVersion
CurrentMMVersion
| Bool
otherwise ->
Text -> TxET QErr IO MaintenanceModeVersion
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 (Text -> TxET QErr IO MaintenanceModeVersion)
-> Text -> TxET QErr IO MaintenanceModeVersion
forall a b. (a -> b) -> a -> b
$
Text
"Maintenance mode is only supported with catalog versions: "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SourceCatalogVersion -> Text
forall a. Show a => a -> Text
tshow SourceCatalogVersion
latestSourceCatalogVersion
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" but received "
Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> SourceCatalogVersion -> Text
forall a. Show a => a -> Text
tshow SourceCatalogVersion
catalogVersion
convertUTCToDatetime2 :: MonadIO m => UTCTime -> m Datetime2
convertUTCToDatetime2 :: UTCTime -> m Datetime2
convertUTCToDatetime2 UTCTime
utcTime = do
TimeZone
timezone <- IO TimeZone -> m TimeZone
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO TimeZone -> m TimeZone) -> IO TimeZone -> m TimeZone
forall a b. (a -> b) -> a -> b
$ UTCTime -> IO TimeZone
getTimeZone UTCTime
utcTime
let localTime :: LocalTime
localTime = TimeZone -> UTCTime -> LocalTime
utcToLocalTime TimeZone
timezone UTCTime
utcTime
Datetime2 -> m Datetime2
forall (m :: * -> *) a. Monad m => a -> m a
return (Datetime2 -> m Datetime2) -> Datetime2 -> m Datetime2
forall a b. (a -> b) -> a -> b
$ LocalTime -> Datetime2
Datetime2 LocalTime
localTime
checkIfTriggerExistsQ ::
TriggerName ->
Ops ->
TxE QErr Bool
checkIfTriggerExistsQ :: TriggerName -> Ops -> TxE QErr Bool
checkIfTriggerExistsQ TriggerName
triggerName Ops
op = do
let triggerNameWithOp :: Text
triggerNameWithOp = Text
"notify_hasura_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TriggerName -> Text
triggerNameToTxt TriggerName
triggerName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Ops -> Text
forall a. Show a => a -> Text
tshow Ops
op
TxE QErr Bool -> TxE QErr Bool
forall (m :: * -> *) a. MonadMSSQLTx m => TxE QErr a -> m a
liftMSSQLTx (TxE QErr Bool -> TxE QErr Bool) -> TxE QErr Bool -> TxE QErr Bool
forall a b. (a -> b) -> a -> b
$
(MSSQLTxError -> QErr) -> Query -> TxE QErr Bool
forall (m :: * -> *) a e.
(MonadIO m, FromRow a) =>
(MSSQLTxError -> e) -> Query -> TxET e m a
singleRowQueryE
MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler
[ODBC.sql|
SELECT CASE WHEN EXISTS
( SELECT 1
FROM sys.triggers WHERE name = $triggerNameWithOp
)
THEN CAST(1 AS BIT)
ELSE CAST(0 AS BIT)
END;
|]
newtype QualifiedTriggerName = QualifiedTriggerName {QualifiedTriggerName -> Text
unQualifiedTriggerName :: Text}
newtype SQLFragment = SQLFragment {SQLFragment -> Text
unSQLFragment :: Text}
msssqlIdenTrigger :: Ops -> SchemaName -> TriggerName -> QualifiedTriggerName
msssqlIdenTrigger :: Ops -> SchemaName -> TriggerName -> QualifiedTriggerName
msssqlIdenTrigger Ops
op (SchemaName Text
schemaName) TriggerName
triggerName =
Text -> QualifiedTriggerName
QualifiedTriggerName (Text -> QualifiedTriggerName) -> Text -> QualifiedTriggerName
forall a b. (a -> b) -> a -> b
$ Ops -> Text -> Text
qualifyHasuraTriggerName Ops
op (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ TriggerName -> Text
triggerNameToTxt TriggerName
triggerName
where
qualifyHasuraTriggerName :: Ops -> Text -> Text
qualifyHasuraTriggerName Ops
op' Text
triggerName' = Text
schemaName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"notify_hasura_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
triggerName' Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"_" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Ops -> Text
forall a. Show a => a -> Text
tshow Ops
op'
mkAllTriggersQ ::
MonadMSSQLTx m =>
TriggerName ->
TableName ->
[ColumnInfo 'MSSQL] ->
TriggerOpsDef 'MSSQL ->
Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)) ->
m ()
mkAllTriggersQ :: TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> TriggerOpsDef 'MSSQL
-> Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
-> m ()
mkAllTriggersQ TriggerName
triggerName TableName
tableName [ColumnInfo 'MSSQL]
allCols TriggerOpsDef 'MSSQL
fullSpec Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
primaryKey = do
Maybe (SubscribeOpSpec 'MSSQL)
-> (SubscribeOpSpec 'MSSQL -> m ()) -> m ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
onJust (TriggerOpsDef 'MSSQL -> Maybe (SubscribeOpSpec 'MSSQL)
forall (b :: BackendType).
TriggerOpsDef b -> Maybe (SubscribeOpSpec b)
tdInsert TriggerOpsDef 'MSSQL
fullSpec) (TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> SubscribeOpSpec 'MSSQL
-> m ()
forall (m :: * -> *).
MonadMSSQLTx m =>
TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> SubscribeOpSpec 'MSSQL
-> m ()
mkInsertTriggerQ TriggerName
triggerName TableName
tableName [ColumnInfo 'MSSQL]
allCols)
Maybe (SubscribeOpSpec 'MSSQL)
-> (SubscribeOpSpec 'MSSQL -> m ()) -> m ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
onJust (TriggerOpsDef 'MSSQL -> Maybe (SubscribeOpSpec 'MSSQL)
forall (b :: BackendType).
TriggerOpsDef b -> Maybe (SubscribeOpSpec b)
tdDelete TriggerOpsDef 'MSSQL
fullSpec) (TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> SubscribeOpSpec 'MSSQL
-> m ()
forall (m :: * -> *).
MonadMSSQLTx m =>
TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> SubscribeOpSpec 'MSSQL
-> m ()
mkDeleteTriggerQ TriggerName
triggerName TableName
tableName [ColumnInfo 'MSSQL]
allCols)
Maybe (SubscribeOpSpec 'MSSQL)
-> (SubscribeOpSpec 'MSSQL -> m ()) -> m ()
forall (m :: * -> *) a.
Applicative m =>
Maybe a -> (a -> m ()) -> m ()
onJust (TriggerOpsDef 'MSSQL -> Maybe (SubscribeOpSpec 'MSSQL)
forall (b :: BackendType).
TriggerOpsDef b -> Maybe (SubscribeOpSpec b)
tdUpdate TriggerOpsDef 'MSSQL
fullSpec) (TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
-> SubscribeOpSpec 'MSSQL
-> m ()
forall (m :: * -> *).
MonadMSSQLTx m =>
TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
-> SubscribeOpSpec 'MSSQL
-> m ()
mkUpdateTriggerQ TriggerName
triggerName TableName
tableName [ColumnInfo 'MSSQL]
allCols Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
primaryKey)
getApplicableColumns :: [ColumnInfo 'MSSQL] -> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
getApplicableColumns :: [ColumnInfo 'MSSQL]
-> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
getApplicableColumns [ColumnInfo 'MSSQL]
allColumnInfos = \case
SubscribeColumns 'MSSQL
SubCStar -> [ColumnInfo 'MSSQL]
allColumnInfos
SubCArray [Column 'MSSQL]
cols -> [Column 'MSSQL] -> [ColumnInfo 'MSSQL] -> [ColumnInfo 'MSSQL]
forall (b :: BackendType).
Backend b =>
[Column b] -> [ColumnInfo b] -> [ColumnInfo b]
getColInfos [Column 'MSSQL]
cols [ColumnInfo 'MSSQL]
allColumnInfos
checkSpatialDataTypeColumns ::
MonadMSSQLTx m =>
[ColumnInfo 'MSSQL] ->
SubscribeOpSpec 'MSSQL ->
m ()
checkSpatialDataTypeColumns :: [ColumnInfo 'MSSQL] -> SubscribeOpSpec 'MSSQL -> m ()
checkSpatialDataTypeColumns [ColumnInfo 'MSSQL]
allCols (SubscribeOpSpec SubscribeColumns 'MSSQL
listenCols Maybe (SubscribeColumns 'MSSQL)
deliveryCols) = do
let listenColumns :: [ColumnInfo 'MSSQL]
listenColumns = [ColumnInfo 'MSSQL]
-> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
getApplicableColumns [ColumnInfo 'MSSQL]
allCols SubscribeColumns 'MSSQL
listenCols
deliveryColumns :: [ColumnInfo 'MSSQL]
deliveryColumns = [ColumnInfo 'MSSQL]
-> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
getApplicableColumns [ColumnInfo 'MSSQL]
allCols (SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL])
-> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
forall a b. (a -> b) -> a -> b
$ SubscribeColumns 'MSSQL
-> Maybe (SubscribeColumns 'MSSQL) -> SubscribeColumns 'MSSQL
forall a. a -> Maybe a -> a
fromMaybe SubscribeColumns 'MSSQL
forall (b :: BackendType). SubscribeColumns b
SubCStar Maybe (SubscribeColumns 'MSSQL)
deliveryCols
isGeoTypesInListenCols :: Bool
isGeoTypesInListenCols = (ColumnInfo 'MSSQL -> Bool) -> [ColumnInfo 'MSSQL] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((ScalarType 'MSSQL -> Bool) -> ColumnType 'MSSQL -> Bool
forall (b :: BackendType).
(ScalarType b -> Bool) -> ColumnType b -> Bool
isScalarColumnWhere ScalarType 'MSSQL -> Bool
ScalarType -> Bool
isGeoType (ColumnType 'MSSQL -> Bool)
-> (ColumnInfo 'MSSQL -> ColumnType 'MSSQL)
-> ColumnInfo 'MSSQL
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ColumnInfo 'MSSQL -> ColumnType 'MSSQL
forall (b :: BackendType). ColumnInfo b -> ColumnType b
ciType) [ColumnInfo 'MSSQL]
listenColumns
isGeoTypesInDeliversCols :: Bool
isGeoTypesInDeliversCols = (ColumnInfo 'MSSQL -> Bool) -> [ColumnInfo 'MSSQL] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((ScalarType 'MSSQL -> Bool) -> ColumnType 'MSSQL -> Bool
forall (b :: BackendType).
(ScalarType b -> Bool) -> ColumnType b -> Bool
isScalarColumnWhere ScalarType 'MSSQL -> Bool
ScalarType -> Bool
isGeoType (ColumnType 'MSSQL -> Bool)
-> (ColumnInfo 'MSSQL -> ColumnType 'MSSQL)
-> ColumnInfo 'MSSQL
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ColumnInfo 'MSSQL -> ColumnType 'MSSQL
forall (b :: BackendType). ColumnInfo b -> ColumnType b
ciType) [ColumnInfo 'MSSQL]
deliveryColumns
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool
isGeoTypesInListenCols Bool -> Bool -> Bool
|| Bool
isGeoTypesInDeliversCols) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"Event triggers for MS-SQL sources are not supported on tables having Geometry or Geography column types"
where
isGeoType :: ScalarType -> Bool
isGeoType = (ScalarType -> [ScalarType] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ScalarType]
geoTypes)
mkInsertTriggerQ ::
MonadMSSQLTx m =>
TriggerName ->
TableName ->
[ColumnInfo 'MSSQL] ->
SubscribeOpSpec 'MSSQL ->
m ()
mkInsertTriggerQ :: TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> SubscribeOpSpec 'MSSQL
-> m ()
mkInsertTriggerQ TriggerName
triggerName TableName
table [ColumnInfo 'MSSQL]
allCols subOpSpec :: SubscribeOpSpec 'MSSQL
subOpSpec@(SubscribeOpSpec SubscribeColumns 'MSSQL
_listenCols Maybe (SubscribeColumns 'MSSQL)
deliveryCols) = do
[ColumnInfo 'MSSQL] -> SubscribeOpSpec 'MSSQL -> m ()
forall (m :: * -> *).
MonadMSSQLTx m =>
[ColumnInfo 'MSSQL] -> SubscribeOpSpec 'MSSQL -> m ()
checkSpatialDataTypeColumns [ColumnInfo 'MSSQL]
allCols SubscribeOpSpec 'MSSQL
subOpSpec
TxET QErr IO () -> m ()
forall (m :: * -> *) a. MonadMSSQLTx m => TxE QErr a -> m a
liftMSSQLTx (TxET QErr IO () -> m ()) -> TxET QErr IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler (Query -> TxET QErr IO ()) -> Query -> TxET QErr IO ()
forall a b. (a -> b) -> a -> b
$
Text -> Query
rawUnescapedText (Text -> Query) -> (Text -> Text) -> Text -> Query
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
LT.toStrict (Text -> Query) -> Text -> Query
forall a b. (a -> b) -> a -> b
$ do
let deliveryColumns :: [ColumnInfo 'MSSQL]
deliveryColumns = [ColumnInfo 'MSSQL]
-> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
getApplicableColumns [ColumnInfo 'MSSQL]
allCols (SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL])
-> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
forall a b. (a -> b) -> a -> b
$ SubscribeColumns 'MSSQL
-> Maybe (SubscribeColumns 'MSSQL) -> SubscribeColumns 'MSSQL
forall a. a -> Maybe a -> a
fromMaybe SubscribeColumns 'MSSQL
forall (b :: BackendType). SubscribeColumns b
SubCStar Maybe (SubscribeColumns 'MSSQL)
deliveryCols
TableName -> TriggerName -> [ColumnInfo 'MSSQL] -> Text
mkInsertTriggerQuery TableName
table TriggerName
triggerName [ColumnInfo 'MSSQL]
deliveryColumns
mkDeleteTriggerQ ::
MonadMSSQLTx m =>
TriggerName ->
TableName ->
[ColumnInfo 'MSSQL] ->
SubscribeOpSpec 'MSSQL ->
m ()
mkDeleteTriggerQ :: TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> SubscribeOpSpec 'MSSQL
-> m ()
mkDeleteTriggerQ TriggerName
triggerName TableName
table [ColumnInfo 'MSSQL]
allCols subOpSpec :: SubscribeOpSpec 'MSSQL
subOpSpec@(SubscribeOpSpec SubscribeColumns 'MSSQL
_listenCols Maybe (SubscribeColumns 'MSSQL)
deliveryCols) = do
[ColumnInfo 'MSSQL] -> SubscribeOpSpec 'MSSQL -> m ()
forall (m :: * -> *).
MonadMSSQLTx m =>
[ColumnInfo 'MSSQL] -> SubscribeOpSpec 'MSSQL -> m ()
checkSpatialDataTypeColumns [ColumnInfo 'MSSQL]
allCols SubscribeOpSpec 'MSSQL
subOpSpec
TxET QErr IO () -> m ()
forall (m :: * -> *) a. MonadMSSQLTx m => TxE QErr a -> m a
liftMSSQLTx (TxET QErr IO () -> m ()) -> TxET QErr IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler (Query -> TxET QErr IO ()) -> Query -> TxET QErr IO ()
forall a b. (a -> b) -> a -> b
$
Text -> Query
rawUnescapedText (Text -> Query) -> (Text -> Text) -> Text -> Query
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
LT.toStrict (Text -> Query) -> Text -> Query
forall a b. (a -> b) -> a -> b
$ do
let deliveryColumns :: [ColumnInfo 'MSSQL]
deliveryColumns = [ColumnInfo 'MSSQL]
-> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
getApplicableColumns [ColumnInfo 'MSSQL]
allCols (SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL])
-> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
forall a b. (a -> b) -> a -> b
$ SubscribeColumns 'MSSQL
-> Maybe (SubscribeColumns 'MSSQL) -> SubscribeColumns 'MSSQL
forall a. a -> Maybe a -> a
fromMaybe SubscribeColumns 'MSSQL
forall (b :: BackendType). SubscribeColumns b
SubCStar Maybe (SubscribeColumns 'MSSQL)
deliveryCols
TableName -> TriggerName -> [ColumnInfo 'MSSQL] -> Text
mkDeleteTriggerQuery TableName
table TriggerName
triggerName [ColumnInfo 'MSSQL]
deliveryColumns
mkUpdateTriggerQ ::
MonadMSSQLTx m =>
TriggerName ->
TableName ->
[ColumnInfo 'MSSQL] ->
Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)) ->
SubscribeOpSpec 'MSSQL ->
m ()
mkUpdateTriggerQ :: TriggerName
-> TableName
-> [ColumnInfo 'MSSQL]
-> Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
-> SubscribeOpSpec 'MSSQL
-> m ()
mkUpdateTriggerQ TriggerName
triggerName TableName
table [ColumnInfo 'MSSQL]
allCols Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
primaryKeyMaybe subOpSpec :: SubscribeOpSpec 'MSSQL
subOpSpec@(SubscribeOpSpec SubscribeColumns 'MSSQL
listenCols Maybe (SubscribeColumns 'MSSQL)
deliveryCols) = do
[ColumnInfo 'MSSQL] -> SubscribeOpSpec 'MSSQL -> m ()
forall (m :: * -> *).
MonadMSSQLTx m =>
[ColumnInfo 'MSSQL] -> SubscribeOpSpec 'MSSQL -> m ()
checkSpatialDataTypeColumns [ColumnInfo 'MSSQL]
allCols SubscribeOpSpec 'MSSQL
subOpSpec
TxET QErr IO () -> m ()
forall (m :: * -> *) a. MonadMSSQLTx m => TxE QErr a -> m a
liftMSSQLTx (TxET QErr IO () -> m ()) -> TxET QErr IO () -> m ()
forall a b. (a -> b) -> a -> b
$ do
PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)
primaryKey <- Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
-> TxET QErr IO (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
-> TxET QErr IO (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
forall (m :: * -> *) a. Applicative m => Maybe a -> m a -> m a
onNothing Maybe (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
primaryKeyMaybe (Code
-> Text -> TxET QErr IO (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL))
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"Update event triggers for MS-SQL sources are only supported on tables with primary keys")
let deliveryColumns :: [ColumnInfo 'MSSQL]
deliveryColumns = [ColumnInfo 'MSSQL]
-> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
getApplicableColumns [ColumnInfo 'MSSQL]
allCols (SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL])
-> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
forall a b. (a -> b) -> a -> b
$ SubscribeColumns 'MSSQL
-> Maybe (SubscribeColumns 'MSSQL) -> SubscribeColumns 'MSSQL
forall a. a -> Maybe a -> a
fromMaybe SubscribeColumns 'MSSQL
forall (b :: BackendType). SubscribeColumns b
SubCStar Maybe (SubscribeColumns 'MSSQL)
deliveryCols
listenColumns :: [ColumnInfo 'MSSQL]
listenColumns = [ColumnInfo 'MSSQL]
-> SubscribeColumns 'MSSQL -> [ColumnInfo 'MSSQL]
getApplicableColumns [ColumnInfo 'MSSQL]
allCols SubscribeColumns 'MSSQL
listenCols
(MSSQLTxError -> QErr) -> Query -> TxET QErr IO ()
forall (m :: * -> *) e.
MonadIO m =>
(MSSQLTxError -> e) -> Query -> TxET e m ()
unitQueryE MSSQLTxError -> QErr
HGE.defaultMSSQLTxErrorHandler (Query -> TxET QErr IO ()) -> Query -> TxET QErr IO ()
forall a b. (a -> b) -> a -> b
$
Text -> Query
rawUnescapedText (Text -> Query) -> (Text -> Text) -> Text -> Query
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Text
LT.toStrict (Text -> Query) -> Text -> Query
forall a b. (a -> b) -> a -> b
$
TableName
-> TriggerName
-> [ColumnInfo 'MSSQL]
-> [ColumnInfo 'MSSQL]
-> PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)
-> Text
mkUpdateTriggerQuery TableName
table TriggerName
triggerName [ColumnInfo 'MSSQL]
listenColumns [ColumnInfo 'MSSQL]
deliveryColumns PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)
primaryKey
generateColumnTriggerAlias :: OpVar -> Maybe Text -> ColumnInfo 'MSSQL -> SQLFragment
generateColumnTriggerAlias :: OpVar -> Maybe Text -> ColumnInfo 'MSSQL -> SQLFragment
generateColumnTriggerAlias OpVar
op Maybe Text
colPrefixMaybe ColumnInfo 'MSSQL
colInfo =
let opText :: Text
opText =
case OpVar
op of
OpVar
OLD -> Text
"old"
OpVar
NEW -> Text
"new"
dbColNameText :: Text
dbColNameText = ColumnName -> Text
columnNameText (ColumnName -> Text) -> ColumnName -> Text
forall a b. (a -> b) -> a -> b
$ ColumnInfo 'MSSQL -> Column 'MSSQL
forall (b :: BackendType). ColumnInfo b -> Column b
ciColumn ColumnInfo 'MSSQL
colInfo
joinPrefixedDbColNameText :: Text
joinPrefixedDbColNameText =
case Maybe Text
colPrefixMaybe of
Just Text
colPrefix -> Text
colPrefix Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
dbColNameText
Maybe Text
Nothing -> Text
dbColNameText
dbColAlias :: Text
dbColAlias = Text
"payload.data" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
opText Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
dbColNameText
in
Text -> SQLFragment
SQLFragment (Text -> SQLFragment) -> Text -> SQLFragment
forall a b. (a -> b) -> a -> b
$ Text -> Text
LT.toStrict (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ [ST.stext| #{joinPrefixedDbColNameText} as [#{dbColAlias}]|]
qualifyTableName :: TableName -> Text
qualifyTableName :: TableName -> Text
qualifyTableName = Query -> Text
forall a. ToTxt a => a -> Text
toTxt (Query -> Text) -> (TableName -> Query) -> TableName -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Printer -> Query
toQueryFlat (Printer -> Query) -> (TableName -> Printer) -> TableName -> Query
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TableName -> Printer
fromTableName
mkInsertTriggerQuery :: TableName -> TriggerName -> [ColumnInfo 'MSSQL] -> LT.Text
mkInsertTriggerQuery :: TableName -> TriggerName -> [ColumnInfo 'MSSQL] -> Text
mkInsertTriggerQuery table :: TableName
table@(TableName Text
tableName schema :: SchemaName
schema@(SchemaName Text
schemaName)) TriggerName
triggerName [ColumnInfo 'MSSQL]
columns =
let QualifiedTriggerName Text
qualifiedTriggerName = Ops -> SchemaName -> TriggerName -> QualifiedTriggerName
msssqlIdenTrigger Ops
INSERT SchemaName
schema TriggerName
triggerName
triggerNameText :: Text
triggerNameText = TriggerName -> Text
triggerNameToTxt TriggerName
triggerName
qualifiedTableName :: Text
qualifiedTableName = TableName -> Text
qualifyTableName TableName
table
operation :: Text
operation = Ops -> Text
forall a. Show a => a -> Text
tshow Ops
INSERT
Text
deliveryColsSQLExpression :: Text =
[Text] -> Text
forall t (f :: * -> *). (ToTxt t, Foldable f) => f t -> Text
commaSeparated ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (ColumnInfo 'MSSQL -> Text) -> [ColumnInfo 'MSSQL] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (SQLFragment -> Text
unSQLFragment (SQLFragment -> Text)
-> (ColumnInfo 'MSSQL -> SQLFragment) -> ColumnInfo 'MSSQL -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OpVar -> Maybe Text -> ColumnInfo 'MSSQL -> SQLFragment
generateColumnTriggerAlias OpVar
NEW Maybe Text
forall a. Maybe a
Nothing) [ColumnInfo 'MSSQL]
columns
in $(makeRelativeToProject "src-rsr/mssql/mssql_insert_trigger.sql.shakespeare" >>= ST.stextFile)
mkDeleteTriggerQuery :: TableName -> TriggerName -> [ColumnInfo 'MSSQL] -> LT.Text
mkDeleteTriggerQuery :: TableName -> TriggerName -> [ColumnInfo 'MSSQL] -> Text
mkDeleteTriggerQuery table :: TableName
table@(TableName Text
tableName schema :: SchemaName
schema@(SchemaName Text
schemaName)) TriggerName
triggerName [ColumnInfo 'MSSQL]
columns =
let QualifiedTriggerName Text
qualifiedTriggerName = Ops -> SchemaName -> TriggerName -> QualifiedTriggerName
msssqlIdenTrigger Ops
DELETE SchemaName
schema TriggerName
triggerName
triggerNameText :: Text
triggerNameText = TriggerName -> Text
triggerNameToTxt TriggerName
triggerName
qualifiedTableName :: Text
qualifiedTableName = TableName -> Text
qualifyTableName TableName
table
operation :: Text
operation = Ops -> Text
forall a. Show a => a -> Text
tshow Ops
DELETE
Text
deliveryColsSQLExpression :: Text = [Text] -> Text
forall t (f :: * -> *). (ToTxt t, Foldable f) => f t -> Text
commaSeparated ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (ColumnInfo 'MSSQL -> Text) -> [ColumnInfo 'MSSQL] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (SQLFragment -> Text
unSQLFragment (SQLFragment -> Text)
-> (ColumnInfo 'MSSQL -> SQLFragment) -> ColumnInfo 'MSSQL -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OpVar -> Maybe Text -> ColumnInfo 'MSSQL -> SQLFragment
generateColumnTriggerAlias OpVar
OLD Maybe Text
forall a. Maybe a
Nothing) [ColumnInfo 'MSSQL]
columns
in $(makeRelativeToProject "src-rsr/mssql/mssql_delete_trigger.sql.shakespeare" >>= ST.stextFile)
mkPrimaryKeyJoinExp :: Text -> Text -> [ColumnInfo 'MSSQL] -> SQLFragment
mkPrimaryKeyJoinExp :: Text -> Text -> [ColumnInfo 'MSSQL] -> SQLFragment
mkPrimaryKeyJoinExp Text
lhsPrefix Text
rhsPrefix [ColumnInfo 'MSSQL]
columns =
Text -> SQLFragment
SQLFragment (Text -> SQLFragment) -> Text -> SQLFragment
forall a b. (a -> b) -> a -> b
$ Text -> [Text] -> Text
T.intercalate Text
" AND " ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ ColumnInfo 'MSSQL -> Text
singleColExp (ColumnInfo 'MSSQL -> Text) -> [ColumnInfo 'MSSQL] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ColumnInfo 'MSSQL]
columns
where
singleColExp :: ColumnInfo 'MSSQL -> Text
singleColExp ColumnInfo 'MSSQL
colInfo =
let dbColNameText :: Text
dbColNameText = ColumnName -> Text
columnNameText (ColumnName -> Text) -> ColumnName -> Text
forall a b. (a -> b) -> a -> b
$ ColumnInfo 'MSSQL -> Column 'MSSQL
forall (b :: BackendType). ColumnInfo b -> Column b
ciColumn ColumnInfo 'MSSQL
colInfo
in Text -> Text
LT.toStrict (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ [ST.stext| #{lhsPrefix}.#{dbColNameText} = #{rhsPrefix}.#{dbColNameText} |]
mkListenColumnsExp :: Text -> Text -> [ColumnInfo 'MSSQL] -> SQLFragment
mkListenColumnsExp :: Text -> Text -> [ColumnInfo 'MSSQL] -> SQLFragment
mkListenColumnsExp Text
_ Text
_ [] = Text -> SQLFragment
SQLFragment Text
""
mkListenColumnsExp Text
lhsPrefix Text
rhsPrefix [ColumnInfo 'MSSQL]
columns =
Text -> SQLFragment
SQLFragment (Text -> SQLFragment) -> Text -> SQLFragment
forall a b. (a -> b) -> a -> b
$ Text
"where " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text -> [Text] -> Text
T.intercalate Text
" OR " (ColumnInfo 'MSSQL -> Text
singleColExp (ColumnInfo 'MSSQL -> Text) -> [ColumnInfo 'MSSQL] -> [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [ColumnInfo 'MSSQL]
columns)
where
singleColExp :: ColumnInfo 'MSSQL -> Text
singleColExp ColumnInfo 'MSSQL
colInfo =
let dbColNameText :: Text
dbColNameText = ColumnName -> Text
columnNameText (ColumnName -> Text) -> ColumnName -> Text
forall a b. (a -> b) -> a -> b
$ ColumnInfo 'MSSQL -> Column 'MSSQL
forall (b :: BackendType). ColumnInfo b -> Column b
ciColumn ColumnInfo 'MSSQL
colInfo
in Text -> Text
LT.toStrict (Text -> Text) -> Text -> Text
forall a b. (a -> b) -> a -> b
$ [ST.stext| #{lhsPrefix}.#{dbColNameText} != #{rhsPrefix}.#{dbColNameText} |]
isPrimaryKeyInListenColumns :: [ColumnInfo 'MSSQL] -> PrimaryKey 'MSSQL (ColumnInfo 'MSSQL) -> SQLFragment
isPrimaryKeyInListenColumns :: [ColumnInfo 'MSSQL]
-> PrimaryKey 'MSSQL (ColumnInfo 'MSSQL) -> SQLFragment
isPrimaryKeyInListenColumns [ColumnInfo 'MSSQL]
listenCols PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)
primaryKey =
case (NESeq (ColumnInfo 'MSSQL) -> [ColumnInfo 'MSSQL]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL) -> NESeq (ColumnInfo 'MSSQL)
forall (b :: BackendType) a. PrimaryKey b a -> NESeq a
_pkColumns PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)
primaryKey) [ColumnInfo 'MSSQL] -> [ColumnInfo 'MSSQL] -> [ColumnInfo 'MSSQL]
forall a. Eq a => [a] -> [a] -> [a]
`intersect` [ColumnInfo 'MSSQL]
listenCols) of
[] -> Text -> SQLFragment
SQLFragment (Text -> SQLFragment) -> Text -> SQLFragment
forall a b. (a -> b) -> a -> b
$ Text
"1 != 1"
[ColumnInfo 'MSSQL]
_ -> Text -> SQLFragment
SQLFragment (Text -> SQLFragment) -> Text -> SQLFragment
forall a b. (a -> b) -> a -> b
$ Text
"1 = 1"
mkUpdateTriggerQuery :: TableName -> TriggerName -> [ColumnInfo 'MSSQL] -> [ColumnInfo 'MSSQL] -> PrimaryKey 'MSSQL (ColumnInfo 'MSSQL) -> LT.Text
mkUpdateTriggerQuery :: TableName
-> TriggerName
-> [ColumnInfo 'MSSQL]
-> [ColumnInfo 'MSSQL]
-> PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)
-> Text
mkUpdateTriggerQuery
table :: TableName
table@(TableName Text
tableName schema :: SchemaName
schema@(SchemaName Text
schemaName))
TriggerName
triggerName
[ColumnInfo 'MSSQL]
listenColumns
[ColumnInfo 'MSSQL]
deliveryColumns
PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)
primaryKey =
let QualifiedTriggerName Text
qualifiedTriggerName = Ops -> SchemaName -> TriggerName -> QualifiedTriggerName
msssqlIdenTrigger Ops
UPDATE SchemaName
schema TriggerName
triggerName
triggerNameText :: Text
triggerNameText = TriggerName -> Text
triggerNameToTxt TriggerName
triggerName
qualifiedTableName :: Text
qualifiedTableName = TableName -> Text
qualifyTableName TableName
table
operation :: Text
operation = Ops -> Text
forall a. Show a => a -> Text
tshow Ops
UPDATE
Text
oldDeliveryColsSQLExp :: Text = [Text] -> Text
forall t (f :: * -> *). (ToTxt t, Foldable f) => f t -> Text
commaSeparated ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (ColumnInfo 'MSSQL -> Text) -> [ColumnInfo 'MSSQL] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (SQLFragment -> Text
unSQLFragment (SQLFragment -> Text)
-> (ColumnInfo 'MSSQL -> SQLFragment) -> ColumnInfo 'MSSQL -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OpVar -> Maybe Text -> ColumnInfo 'MSSQL -> SQLFragment
generateColumnTriggerAlias OpVar
OLD (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"DELETED")) [ColumnInfo 'MSSQL]
deliveryColumns
Text
newDeliveryColsSQLExp :: Text = [Text] -> Text
forall t (f :: * -> *). (ToTxt t, Foldable f) => f t -> Text
commaSeparated ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (ColumnInfo 'MSSQL -> Text) -> [ColumnInfo 'MSSQL] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (SQLFragment -> Text
unSQLFragment (SQLFragment -> Text)
-> (ColumnInfo 'MSSQL -> SQLFragment) -> ColumnInfo 'MSSQL -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OpVar -> Maybe Text -> ColumnInfo 'MSSQL -> SQLFragment
generateColumnTriggerAlias OpVar
NEW (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"INSERTED")) [ColumnInfo 'MSSQL]
deliveryColumns
Text
oldDeliveryColsSQLExpWhenPrimaryKeyUpdated :: Text =
Text
"NULL as [payload.data.old]"
Text
newDeliveryColsSQLExpWhenPrimaryKeyUpdated :: Text =
[Text] -> Text
forall t (f :: * -> *). (ToTxt t, Foldable f) => f t -> Text
commaSeparated ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ (ColumnInfo 'MSSQL -> Text) -> [ColumnInfo 'MSSQL] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (SQLFragment -> Text
unSQLFragment (SQLFragment -> Text)
-> (ColumnInfo 'MSSQL -> SQLFragment) -> ColumnInfo 'MSSQL -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. OpVar -> Maybe Text -> ColumnInfo 'MSSQL -> SQLFragment
generateColumnTriggerAlias OpVar
NEW (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"INSERTED")) [ColumnInfo 'MSSQL]
deliveryColumns
primaryKeyJoinExp :: Text
primaryKeyJoinExp = SQLFragment -> Text
unSQLFragment (SQLFragment -> Text) -> SQLFragment -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Text -> [ColumnInfo 'MSSQL] -> SQLFragment
mkPrimaryKeyJoinExp Text
"INSERTED" Text
"DELETED" (NESeq (ColumnInfo 'MSSQL) -> [ColumnInfo 'MSSQL]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (PrimaryKey 'MSSQL (ColumnInfo 'MSSQL) -> NESeq (ColumnInfo 'MSSQL)
forall (b :: BackendType) a. PrimaryKey b a -> NESeq a
_pkColumns PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)
primaryKey))
listenColumnExp :: Text
listenColumnExp = SQLFragment -> Text
unSQLFragment (SQLFragment -> Text) -> SQLFragment -> Text
forall a b. (a -> b) -> a -> b
$ Text -> Text -> [ColumnInfo 'MSSQL] -> SQLFragment
mkListenColumnsExp Text
"INSERTED" Text
"DELETED" [ColumnInfo 'MSSQL]
listenColumns
isPrimaryKeyInListenColumnsExp :: Text
isPrimaryKeyInListenColumnsExp = SQLFragment -> Text
unSQLFragment (SQLFragment -> Text) -> SQLFragment -> Text
forall a b. (a -> b) -> a -> b
$ [ColumnInfo 'MSSQL]
-> PrimaryKey 'MSSQL (ColumnInfo 'MSSQL) -> SQLFragment
isPrimaryKeyInListenColumns [ColumnInfo 'MSSQL]
listenColumns PrimaryKey 'MSSQL (ColumnInfo 'MSSQL)
primaryKey
in $(makeRelativeToProject "src-rsr/mssql/mssql_update_trigger.sql.shakespeare" >>= ST.stextFile)