graphql-engine/server/src-lib/Hasura/Backends/BigQuery/Instances/Execute.hs

150 lines
5.4 KiB
Haskell
Raw Normal View History

{-# OPTIONS_GHC -fno-warn-orphans #-}
module Hasura.Backends.BigQuery.Instances.Execute () where
import Hasura.Prelude
import qualified Data.Aeson as Aeson
import qualified Data.Environment as Env
import qualified Data.HashMap.Strict.InsOrd as OMap
import qualified Data.Text as T
import qualified Language.GraphQL.Draft.Syntax as G
import qualified Network.HTTP.Client as HTTP
import qualified Network.HTTP.Types as HTTP
import qualified Hasura.Backends.BigQuery.DataLoader.Execute as DataLoader
import qualified Hasura.Backends.BigQuery.DataLoader.Plan as DataLoader
import qualified Hasura.Base.Error as E
import qualified Hasura.SQL.AnyBackend as AB
import qualified Hasura.Tracing as Tracing
import Hasura.Backends.BigQuery.Plan
import Hasura.Base.Error
import Hasura.EncJSON
import Hasura.GraphQL.Context
import Hasura.GraphQL.Execute.Backend
import Hasura.GraphQL.Parser
import Hasura.RQL.Types
import Hasura.Session
instance BackendExecute 'BigQuery where
type PreparedQuery 'BigQuery = Text
type MultiplexedQuery 'BigQuery = Void
type ExecutionMonad 'BigQuery = Tracing.TraceT (ExceptT QErr IO)
getRemoteJoins = const []
mkDBQueryPlan = bqDBQueryPlan
mkDBMutationPlan = bqDBMutationPlan
mkDBSubscriptionPlan _ _ _ _ =
throwError $ E.internalError "Cannot currently perform subscriptions on BigQuery sources."
mkDBQueryExplain = bqDBQueryExplain
mkLiveQueryExplain _ =
throwError $ E.internalError "Cannot currently retrieve query execution plans on BigQuery sources."
-- query
bqDBQueryPlan
:: forall m.
( MonadError E.QErr m
)
=> Env.Environment
-> HTTP.Manager
-> [HTTP.Header]
-> UserInfo
-> SourceName
-> SourceConfig 'BigQuery
-> QueryDB 'BigQuery (UnpreparedValue 'BigQuery)
-> m ExecutionStep
bqDBQueryPlan _env _manager _reqHeaders userInfo sourceName sourceConfig qrf = do
select <- planNoPlan userInfo qrf
let (!headAndTail, !plannedActionsList) =
DataLoader.runPlan
(DataLoader.planSelectHeadAndTail Nothing Nothing select)
!actionsForest = DataLoader.actionsForest id plannedActionsList
let action = do
result <-
DataLoader.runExecute
sourceConfig
headAndTail
(DataLoader.execute actionsForest)
case result of
Left err -> throw500WithDetail "dataLoader error" $ Aeson.toJSON $ show err
Right recordSet -> pure $! recordSetToEncJSON recordSet
pure
$ ExecStepDB []
. AB.mkAnyBackend
$ DBStepInfo @'BigQuery sourceName sourceConfig (Just (DataLoader.drawActionsForest actionsForest)) action
-- | Convert the dataloader's 'RecordSet' type to JSON.
recordSetToEncJSON :: DataLoader.RecordSet -> EncJSON
recordSetToEncJSON DataLoader.RecordSet {rows} =
encJFromList (toList (fmap encJFromRecord rows))
where
encJFromRecord =
encJFromInsOrdHashMap . fmap encJFromOutputValue . OMap.mapKeys coerce
encJFromOutputValue outputValue =
case outputValue of
DataLoader.NullOutputValue -> encJFromJValue Aeson.Null
DataLoader.DecimalOutputValue !i -> encJFromJValue i
DataLoader.BigDecimalOutputValue !i -> encJFromJValue i
DataLoader.FloatOutputValue !i -> encJFromJValue i
DataLoader.TextOutputValue !i -> encJFromJValue i
DataLoader.BytesOutputValue !i -> encJFromJValue i
DataLoader.DateOutputValue !i -> encJFromJValue i
DataLoader.TimestampOutputValue !i -> encJFromJValue i
DataLoader.TimeOutputValue !i -> encJFromJValue i
DataLoader.DatetimeOutputValue !i -> encJFromJValue i
DataLoader.GeographyOutputValue !i -> encJFromJValue i
DataLoader.BoolOutputValue !i -> encJFromJValue i
DataLoader.IntegerOutputValue !i -> encJFromJValue i
DataLoader.ArrayOutputValue !vector ->
encJFromList (toList (fmap encJFromOutputValue vector))
-- Really, the case below shouldn't be happening. But if it
-- does, it's not a problem either. The output will just have
-- a record in it.
DataLoader.RecordOutputValue !record -> encJFromRecord record
-- mutation
bqDBMutationPlan
:: forall m.
( MonadError E.QErr m
)
=> Env.Environment
-> HTTP.Manager
-> [HTTP.Header]
-> UserInfo
-> Bool
-> SourceName
-> SourceConfig 'BigQuery
-> MutationDB 'BigQuery (UnpreparedValue 'BigQuery)
-> m ExecutionStep
bqDBMutationPlan _env _manager _reqHeaders _userInfo _stringifyNum _sourceName _sourceConfig _mrf =
throw500 "mutations are not supported in BigQuery; this should be unreachable"
-- explain
bqDBQueryExplain
:: MonadError E.QErr m
=> G.Name
-> UserInfo
-> SourceName
-> SourceConfig 'BigQuery
-> QueryDB 'BigQuery (UnpreparedValue 'BigQuery)
-> m (AB.AnyBackend DBStepInfo)
bqDBQueryExplain fieldName userInfo sourceName sourceConfig qrf = do
actionsForest <- planToForest userInfo qrf
pure
$ AB.mkAnyBackend
$ DBStepInfo @'BigQuery sourceName sourceConfig Nothing
$ pure
$ encJFromJValue
$ ExplainPlan
fieldName
(Just $ DataLoader.drawActionsForestSQL actionsForest)
(Just $ T.lines $ DataLoader.drawActionsForest actionsForest)