graphql-engine/server/src-lib/Hasura/Backends/DataWrapper/Adapter/Execute.hs
Solomon 893fb8cd92 Feature/gdw execute and metadata [GDW-74]
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4195
Co-authored-by: Daniel Chambers <1214352+daniel-chambers@users.noreply.github.com>
GitOrigin-RevId: 2508b604e7453c2efaa2f7096b2b4b2ce6885d2d
2022-04-14 02:07:04 +00:00

78 lines
3.5 KiB
Haskell

{-# OPTIONS_GHC -fno-warn-orphans #-}
module Hasura.Backends.DataWrapper.Adapter.Execute
(
)
where
--------------------------------------------------------------------------------
import Data.Aeson qualified as J
import Data.ByteString.Lazy qualified as BL
import Data.Text.Encoding qualified as TE
import Hasura.Backends.DataWrapper.API (Capabilities (dcRelationships), Routes (..), SchemaResponse (srCapabilities))
import Hasura.Backends.DataWrapper.Agent.Client
import Hasura.Backends.DataWrapper.IR.Query qualified as IR
import Hasura.Backends.DataWrapper.Plan qualified as GDW
import Hasura.Base.Error (Code (NotSupported), QErr, throw400, throw500)
import Hasura.EncJSON (EncJSON, encJFromJValue)
import Hasura.GraphQL.Execute.Backend (BackendExecute (..), DBStepInfo (..), ExplainPlan (..))
import Hasura.GraphQL.Namespace qualified as GQL
import Hasura.Prelude
import Hasura.SQL.AnyBackend (mkAnyBackend)
import Hasura.SQL.Backend (BackendType (DataWrapper))
import Hasura.Session
import Hasura.Tracing qualified as Tracing
import Witch qualified (from)
--------------------------------------------------------------------------------
instance BackendExecute 'DataWrapper where
type PreparedQuery 'DataWrapper = GDW.Plan
type MultiplexedQuery 'DataWrapper = Void
type ExecutionMonad 'DataWrapper = Tracing.TraceT (ExceptT QErr IO)
mkDBQueryPlan UserInfo {..} sourceName sourceConfig ir = do
plan' <- GDW.mkPlan _uiSession sourceConfig ir
pure
DBStepInfo
{ dbsiSourceName = sourceName,
dbsiSourceConfig = sourceConfig,
dbsiPreparedQuery = Just plan',
dbsiAction = buildAction sourceConfig (GDW.query plan')
}
mkDBQueryExplain fieldName UserInfo {..} sourceName sourceConfig ir = do
plan' <- GDW.mkPlan _uiSession sourceConfig ir
pure $
mkAnyBackend @'DataWrapper
DBStepInfo
{ dbsiSourceName = sourceName,
dbsiSourceConfig = sourceConfig,
dbsiPreparedQuery = Just plan',
dbsiAction = pure . encJFromJValue . toExplainPlan fieldName $ plan'
}
mkDBMutationPlan _ _ _ _ _ =
throw400 NotSupported "mkDBMutationPlan: not implemented for GraphQL Data Wrappers."
mkLiveQuerySubscriptionPlan _ _ _ _ _ =
throw400 NotSupported "mkLiveQuerySubscriptionPlan: not implemented for GraphQL Data Wrappers."
mkDBStreamingSubscriptionPlan _ _ _ _ =
throw400 NotSupported "mkLiveQuerySubscriptionPlan: not implemented for GraphQL Data Wrappers."
mkDBRemoteRelationshipPlan _ _ _ _ _ _ _ =
throw500 "mkDBRemoteRelationshipPlan: not implemented for GraphQL Data Wrappers."
mkSubscriptionExplain _ =
throw400 NotSupported "mkSubscriptionExplain: not implemented for GraphQL Data Wrappers."
toExplainPlan :: GQL.RootFieldAlias -> GDW.Plan -> ExplainPlan
toExplainPlan fieldName plan_ =
ExplainPlan fieldName (Just "") (Just [TE.decodeUtf8 $ BL.toStrict $ J.encode $ GDW.query $ plan_])
buildAction :: GDW.SourceConfig -> IR.Query -> Tracing.TraceT (ExceptT QErr IO) EncJSON
buildAction GDW.SourceConfig {..} query = do
-- TODO(SOLOMON): Should this check occur during query construction in 'mkPlan'?
when (GDW.queryHasRelations query && not (dcRelationships (srCapabilities dscSchema))) $
throw400 NotSupported "Agents must provide their own dataloader."
Routes {..} <- liftIO $ client @(Tracing.TraceT (ExceptT QErr IO)) dscManager (ConnSourceConfig dscEndpoint)
queryResponse <- _query $ Witch.from query
pure $ encJFromJValue queryResponse