mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-18 04:51:35 +03:00
5238bb8011
Co-authored-by: Aravind K P <8335904+scriptonist@users.noreply.github.com> GitOrigin-RevId: f11b3b2e964af4860c3bb0fd9efec6be54c2e88b
150 lines
5.4 KiB
Haskell
150 lines
5.4 KiB
Haskell
{-# 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)
|