2021-02-23 20:37:27 +03:00
|
|
|
{-# OPTIONS_GHC -fno-warn-orphans #-}
|
|
|
|
|
|
|
|
module Hasura.Backends.MSSQL.Instances.Execute (NoMultiplex(..)) where
|
|
|
|
|
|
|
|
import Hasura.Prelude
|
|
|
|
|
|
|
|
import qualified Data.Environment as Env
|
|
|
|
import qualified Data.HashMap.Strict.InsOrd as OMap
|
|
|
|
import qualified Database.ODBC.SQLServer as ODBC
|
|
|
|
import qualified Language.GraphQL.Draft.Syntax as G
|
|
|
|
import qualified Network.HTTP.Client as HTTP
|
|
|
|
import qualified Network.HTTP.Types as HTTP
|
|
|
|
|
|
|
|
import Data.Text.Extended
|
|
|
|
|
2021-03-15 16:02:58 +03:00
|
|
|
import qualified Hasura.SQL.AnyBackend as AB
|
|
|
|
|
2021-02-25 21:15:55 +03:00
|
|
|
import Hasura.Backends.MSSQL.Connection
|
2021-02-23 20:37:27 +03:00
|
|
|
import Hasura.Backends.MSSQL.Plan
|
|
|
|
import Hasura.Backends.MSSQL.ToQuery
|
|
|
|
import Hasura.EncJSON
|
|
|
|
import Hasura.GraphQL.Context
|
|
|
|
import Hasura.GraphQL.Execute.Backend
|
|
|
|
import Hasura.GraphQL.Execute.LiveQuery.Plan
|
|
|
|
import Hasura.GraphQL.Parser
|
|
|
|
import Hasura.RQL.Types
|
|
|
|
import Hasura.Session
|
|
|
|
|
|
|
|
|
|
|
|
instance BackendExecute 'MSSQL where
|
|
|
|
type PreparedQuery 'MSSQL = Text
|
|
|
|
type MultiplexedQuery 'MSSQL = NoMultiplex
|
2021-02-25 21:15:55 +03:00
|
|
|
type ExecutionMonad 'MSSQL = ExceptT QErr IO
|
2021-02-23 20:37:27 +03:00
|
|
|
getRemoteJoins = const []
|
|
|
|
|
|
|
|
mkDBQueryPlan = msDBQueryPlan
|
|
|
|
mkDBMutationPlan = msDBMutationPlan
|
|
|
|
mkDBSubscriptionPlan = msDBSubscriptionPlan
|
2021-04-13 14:10:08 +03:00
|
|
|
mkDBQueryExplain = msDBQueryExplain
|
|
|
|
mkLiveQueryExplain = msDBLiveQueryExplain
|
2021-02-23 20:37:27 +03:00
|
|
|
|
|
|
|
-- multiplexed query
|
|
|
|
|
|
|
|
newtype NoMultiplex = NoMultiplex (G.Name, ODBC.Query)
|
|
|
|
|
|
|
|
instance ToTxt NoMultiplex where
|
|
|
|
toTxt (NoMultiplex (_name, query)) = toTxt query
|
|
|
|
|
|
|
|
|
|
|
|
-- query
|
|
|
|
|
|
|
|
msDBQueryPlan
|
|
|
|
:: forall m.
|
|
|
|
( MonadError QErr m
|
|
|
|
)
|
|
|
|
=> Env.Environment
|
|
|
|
-> HTTP.Manager
|
|
|
|
-> [HTTP.Header]
|
|
|
|
-> UserInfo
|
|
|
|
-> [G.Directive G.Name]
|
2021-04-01 23:40:31 +03:00
|
|
|
-> SourceName
|
2021-02-23 20:37:27 +03:00
|
|
|
-> SourceConfig 'MSSQL
|
|
|
|
-> QueryDB 'MSSQL (UnpreparedValue 'MSSQL)
|
|
|
|
-> m ExecutionStep
|
2021-04-01 23:40:31 +03:00
|
|
|
msDBQueryPlan _env _manager _reqHeaders userInfo _directives sourceName sourceConfig qrf = do
|
2021-02-23 20:37:27 +03:00
|
|
|
select <- fromSelect <$> planNoPlan userInfo qrf
|
|
|
|
let queryString = ODBC.renderQuery $ toQueryPretty select
|
2021-02-25 21:15:55 +03:00
|
|
|
pool = _mscConnectionPool sourceConfig
|
|
|
|
odbcQuery = encJFromText <$> runJSONPathQuery pool (toQueryFlat select)
|
2021-03-15 16:02:58 +03:00
|
|
|
pure
|
|
|
|
$ ExecStepDB []
|
|
|
|
. AB.mkAnyBackend
|
2021-04-01 23:40:31 +03:00
|
|
|
$ DBStepInfo sourceName sourceConfig (Just queryString) odbcQuery
|
2021-02-23 20:37:27 +03:00
|
|
|
|
2021-04-13 14:10:08 +03:00
|
|
|
msDBQueryExplain
|
|
|
|
:: forall m
|
|
|
|
. ( MonadError QErr m
|
|
|
|
)
|
|
|
|
=> G.Name
|
|
|
|
-> UserInfo
|
|
|
|
-> SourceName
|
|
|
|
-> SourceConfig 'MSSQL
|
|
|
|
-> QueryDB 'MSSQL (UnpreparedValue 'MSSQL)
|
|
|
|
-> m (AB.AnyBackend DBStepInfo)
|
|
|
|
msDBQueryExplain fieldName userInfo sourceName sourceConfig qrf = do
|
|
|
|
select <- withExplain . fromSelect <$> planNoPlan userInfo qrf
|
|
|
|
let queryString = ODBC.renderQuery $ toQueryPretty select
|
|
|
|
pool = _mscConnectionPool sourceConfig
|
|
|
|
-- TODO: execute `select` in separate batch
|
|
|
|
-- https://github.com/hasura/graphql-engine-mono/issues/1024
|
|
|
|
odbcQuery = runJSONPathQuery pool (toQueryFlat select) <&> \explainInfo ->
|
|
|
|
encJFromJValue $ ExplainPlan fieldName (Just queryString) (Just [explainInfo])
|
|
|
|
pure
|
|
|
|
$ AB.mkAnyBackend
|
|
|
|
$ DBStepInfo sourceName sourceConfig Nothing odbcQuery
|
|
|
|
|
|
|
|
msDBLiveQueryExplain
|
|
|
|
:: ( MonadError QErr m
|
|
|
|
, MonadIO m
|
|
|
|
)
|
|
|
|
=> LiveQueryPlan 'MSSQL (MultiplexedQuery 'MSSQL) -> m LiveQueryPlanExplanation
|
|
|
|
msDBLiveQueryExplain (LiveQueryPlan plan sourceConfig variables) = do
|
|
|
|
let NoMultiplex (_name, query) = _plqpQuery plan
|
|
|
|
select = withExplain $ QueryPrinter query
|
|
|
|
pool = _mscConnectionPool sourceConfig
|
|
|
|
-- TODO: execute `select` in separate batch
|
|
|
|
-- https://github.com/hasura/graphql-engine-mono/issues/1024
|
|
|
|
_explainInfo <- runJSONPathQuery pool (toQueryFlat select)
|
|
|
|
pure $ LiveQueryPlanExplanation (toTxt query) [] variables
|
|
|
|
|
2021-02-23 20:37:27 +03:00
|
|
|
-- mutation
|
|
|
|
|
|
|
|
msDBMutationPlan
|
|
|
|
:: forall m.
|
|
|
|
( MonadError QErr m
|
|
|
|
)
|
|
|
|
=> Env.Environment
|
|
|
|
-> HTTP.Manager
|
|
|
|
-> [HTTP.Header]
|
|
|
|
-> UserInfo
|
|
|
|
-> Bool
|
2021-04-01 23:40:31 +03:00
|
|
|
-> SourceName
|
2021-02-23 20:37:27 +03:00
|
|
|
-> SourceConfig 'MSSQL
|
|
|
|
-> MutationDB 'MSSQL (UnpreparedValue 'MSSQL)
|
|
|
|
-> m ExecutionStep
|
2021-04-01 23:40:31 +03:00
|
|
|
msDBMutationPlan _env _manager _reqHeaders _userInfo _stringifyNum _sourceName _sourceConfig _mrf =
|
2021-02-23 20:37:27 +03:00
|
|
|
throw500 "mutations are not supported in MSSQL; this should be unreachable"
|
|
|
|
|
|
|
|
|
|
|
|
-- subscription
|
|
|
|
|
|
|
|
msDBSubscriptionPlan
|
|
|
|
:: forall m.
|
|
|
|
( MonadError QErr m
|
|
|
|
)
|
|
|
|
=> UserInfo
|
2021-04-01 23:40:31 +03:00
|
|
|
-> SourceName
|
2021-02-23 20:37:27 +03:00
|
|
|
-> SourceConfig 'MSSQL
|
|
|
|
-> InsOrdHashMap G.Name (QueryDB 'MSSQL (UnpreparedValue 'MSSQL))
|
|
|
|
-> m (LiveQueryPlan 'MSSQL (MultiplexedQuery 'MSSQL))
|
2021-04-01 23:40:31 +03:00
|
|
|
msDBSubscriptionPlan userInfo _sourceName sourceConfig rootFields = do
|
2021-02-23 20:37:27 +03:00
|
|
|
-- WARNING: only keeping the first root field for now!
|
|
|
|
query <- traverse mkQuery $ head $ OMap.toList rootFields
|
|
|
|
let roleName = _uiRole userInfo
|
|
|
|
parameterizedPlan = ParameterizedLiveQueryPlan roleName $ NoMultiplex query
|
|
|
|
pure
|
|
|
|
$ LiveQueryPlan parameterizedPlan sourceConfig
|
|
|
|
$ mkCohortVariables mempty mempty mempty mempty
|
|
|
|
where
|
|
|
|
mkQuery = fmap (toQueryFlat . fromSelect) . planNoPlan userInfo
|