{-# OPTIONS_GHC -fno-warn-orphans #-}

module Hasura.Backends.BigQuery.Instances.Transport () where

import Data.Aeson qualified as J
import Hasura.Backends.BigQuery.Instances.Execute ()
import Hasura.Base.Error
import Hasura.EncJSON
import Hasura.GraphQL.Execute.Backend
import Hasura.GraphQL.Logging
  ( GeneratedQuery (..),
    MonadQueryLog (..),
    QueryLog (..),
    QueryLogKind (QueryLogKindDatabase),
  )
import Hasura.GraphQL.Namespace (RootFieldAlias)
import Hasura.GraphQL.Transport.Backend
import Hasura.GraphQL.Transport.HTTP.Protocol
import Hasura.Logging qualified as L
import Hasura.Prelude
import Hasura.RQL.Types.Backend
import Hasura.SQL.Backend
import Hasura.Server.Types (RequestId)
import Hasura.Session
import Hasura.Tracing
import Hasura.Tracing qualified as Tracing

instance BackendTransport 'BigQuery where
  runDBQuery :: RequestId
-> GQLReqUnparsed
-> RootFieldAlias
-> UserInfo
-> Logger Hasura
-> SourceConfig 'BigQuery
-> ExecutionMonad 'BigQuery EncJSON
-> Maybe (PreparedQuery 'BigQuery)
-> m (DiffTime, EncJSON)
runDBQuery = RequestId
-> GQLReqUnparsed
-> RootFieldAlias
-> UserInfo
-> Logger Hasura
-> SourceConfig 'BigQuery
-> ExecutionMonad 'BigQuery EncJSON
-> Maybe (PreparedQuery 'BigQuery)
-> m (DiffTime, EncJSON)
forall (m :: * -> *).
(MonadIO m, MonadQueryLog m, MonadTrace m, MonadError QErr m) =>
RequestId
-> GQLReqUnparsed
-> RootFieldAlias
-> UserInfo
-> Logger Hasura
-> SourceConfig 'BigQuery
-> TraceT (ExceptT QErr IO) EncJSON
-> Maybe Text
-> m (DiffTime, EncJSON)
runQuery
  runDBQueryExplain :: DBStepInfo 'BigQuery -> m EncJSON
runDBQueryExplain = DBStepInfo 'BigQuery -> m EncJSON
forall (m :: * -> *).
(MonadIO m, MonadError QErr m) =>
DBStepInfo 'BigQuery -> m EncJSON
runQueryExplain
  runDBMutation :: RequestId
-> GQLReqUnparsed
-> RootFieldAlias
-> UserInfo
-> Logger Hasura
-> SourceConfig 'BigQuery
-> ExecutionMonad 'BigQuery EncJSON
-> Maybe (PreparedQuery 'BigQuery)
-> m (DiffTime, EncJSON)
runDBMutation = RequestId
-> GQLReqUnparsed
-> RootFieldAlias
-> UserInfo
-> Logger Hasura
-> SourceConfig 'BigQuery
-> ExecutionMonad 'BigQuery EncJSON
-> Maybe (PreparedQuery 'BigQuery)
-> m (DiffTime, EncJSON)
forall (m :: * -> *).
MonadError QErr m =>
RequestId
-> GQLReqUnparsed
-> RootFieldAlias
-> UserInfo
-> Logger Hasura
-> SourceConfig 'BigQuery
-> TraceT (ExceptT QErr IO) EncJSON
-> Maybe Text
-> m (DiffTime, EncJSON)
runMutation
  runDBSubscription :: SourceConfig 'BigQuery
-> MultiplexedQuery 'BigQuery
-> [(CohortId, CohortVariables)]
-> m (DiffTime, Either QErr [(CohortId, ByteString)])
runDBSubscription = [Char]
-> BigQuerySourceConfig
-> Void
-> [(CohortId, CohortVariables)]
-> m (DiffTime, Either QErr [(CohortId, ByteString)])
forall a. HasCallStack => [Char] -> a
error [Char]
"Not supported."
  runDBStreamingSubscription :: SourceConfig 'BigQuery
-> MultiplexedQuery 'BigQuery
-> [(CohortId, CohortVariables)]
-> m (DiffTime,
      Either QErr [(CohortId, ByteString, CursorVariableValues)])
runDBStreamingSubscription = [Char]
-> BigQuerySourceConfig
-> Void
-> [(CohortId, CohortVariables)]
-> m (DiffTime,
      Either QErr [(CohortId, ByteString, CursorVariableValues)])
forall a. HasCallStack => [Char] -> a
error [Char]
"Not supported"

runQuery ::
  ( MonadIO m,
    MonadQueryLog m,
    MonadTrace m,
    MonadError QErr m
  ) =>
  RequestId ->
  GQLReqUnparsed ->
  RootFieldAlias ->
  UserInfo ->
  L.Logger L.Hasura ->
  SourceConfig 'BigQuery ->
  Tracing.TraceT (ExceptT QErr IO) EncJSON ->
  Maybe Text ->
  -- | Also return the time spent in the PG query; for telemetry.
  m (DiffTime, EncJSON)
runQuery :: RequestId
-> GQLReqUnparsed
-> RootFieldAlias
-> UserInfo
-> Logger Hasura
-> SourceConfig 'BigQuery
-> TraceT (ExceptT QErr IO) EncJSON
-> Maybe Text
-> m (DiffTime, EncJSON)
runQuery RequestId
reqId GQLReqUnparsed
query RootFieldAlias
fieldName UserInfo
_userInfo Logger Hasura
logger SourceConfig 'BigQuery
_sourceConfig TraceT (ExceptT QErr IO) EncJSON
tx Maybe Text
genSql = do
  -- log the generated SQL and the graphql query
  -- FIXME: fix logging by making logQueryLog expect something backend agnostic!
  Logger Hasura -> QueryLog -> m ()
forall (m :: * -> *).
MonadQueryLog m =>
Logger Hasura -> QueryLog -> m ()
logQueryLog Logger Hasura
logger (QueryLog -> m ()) -> QueryLog -> m ()
forall a b. (a -> b) -> a -> b
$ GQLReqUnparsed
-> RootFieldAlias -> Maybe Text -> RequestId -> QueryLog
mkQueryLog GQLReqUnparsed
query RootFieldAlias
fieldName Maybe Text
genSql RequestId
reqId
  m EncJSON -> m (DiffTime, EncJSON)
forall (m :: * -> *) a. MonadIO m => m a -> m (DiffTime, a)
withElapsedTime (m EncJSON -> m (DiffTime, EncJSON))
-> m EncJSON -> m (DiffTime, EncJSON)
forall a b. (a -> b) -> a -> b
$ (ExceptT QErr IO (EncJSON, TracingMetadata)
 -> m (EncJSON, TracingMetadata))
-> TraceT (ExceptT QErr IO) EncJSON -> m EncJSON
forall (n :: * -> *) (m :: * -> *) a b.
MonadTrace n =>
(m (a, TracingMetadata) -> n (b, TracingMetadata))
-> TraceT m a -> n b
Tracing.interpTraceT ExceptT QErr IO (EncJSON, TracingMetadata)
-> m (EncJSON, TracingMetadata)
forall (m :: * -> *) a.
(MonadIO m, MonadError QErr m) =>
ExceptT QErr IO a -> m a
run TraceT (ExceptT QErr IO) EncJSON
tx

runQueryExplain ::
  ( MonadIO m,
    MonadError QErr m
  ) =>
  DBStepInfo 'BigQuery ->
  m EncJSON
runQueryExplain :: DBStepInfo 'BigQuery -> m EncJSON
runQueryExplain (DBStepInfo SourceName
_ SourceConfig 'BigQuery
_ Maybe (PreparedQuery 'BigQuery)
_ ExecutionMonad 'BigQuery EncJSON
action) = ExceptT QErr IO EncJSON -> m EncJSON
forall (m :: * -> *) a.
(MonadIO m, MonadError QErr m) =>
ExceptT QErr IO a -> m a
run (ExceptT QErr IO EncJSON -> m EncJSON)
-> ExceptT QErr IO EncJSON -> m EncJSON
forall a b. (a -> b) -> a -> b
$ Reporter
-> Text
-> TraceT (ExceptT QErr IO) EncJSON
-> ExceptT QErr IO EncJSON
forall (m :: * -> *) a.
MonadIO m =>
Reporter -> Text -> TraceT m a -> m a
runTraceTWithReporter Reporter
noReporter Text
"explain" TraceT (ExceptT QErr IO) EncJSON
ExecutionMonad 'BigQuery EncJSON
action

runMutation ::
  ( MonadError QErr m
  ) =>
  RequestId ->
  GQLReqUnparsed ->
  RootFieldAlias ->
  UserInfo ->
  L.Logger L.Hasura ->
  SourceConfig 'BigQuery ->
  Tracing.TraceT (ExceptT QErr IO) EncJSON ->
  Maybe Text ->
  -- | Also return 'Mutation' when the operation was a mutation, and the time
  -- spent in the PG query; for telemetry.
  m (DiffTime, EncJSON)
runMutation :: RequestId
-> GQLReqUnparsed
-> RootFieldAlias
-> UserInfo
-> Logger Hasura
-> SourceConfig 'BigQuery
-> TraceT (ExceptT QErr IO) EncJSON
-> Maybe Text
-> m (DiffTime, EncJSON)
runMutation RequestId
_reqId GQLReqUnparsed
_query RootFieldAlias
_fieldName UserInfo
_userInfo Logger Hasura
_logger SourceConfig 'BigQuery
_sourceConfig TraceT (ExceptT QErr IO) EncJSON
_tx Maybe Text
_genSql =
  -- do
  Text -> m (DiffTime, EncJSON)
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 Text
"BigQuery does not support mutations!"

run :: (MonadIO m, MonadError QErr m) => ExceptT QErr IO a -> m a
run :: ExceptT QErr IO a -> m a
run ExceptT QErr IO a
action = do
  Either QErr a
result <- IO (Either QErr a) -> m (Either QErr a)
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (Either QErr a) -> m (Either QErr a))
-> IO (Either QErr a) -> m (Either QErr a)
forall a b. (a -> b) -> a -> b
$ ExceptT QErr IO a -> IO (Either QErr a)
forall e (m :: * -> *) a. ExceptT e m a -> m (Either e a)
runExceptT ExceptT QErr IO a
action
  Either QErr a
result Either QErr a -> (QErr -> m a) -> m a
forall (m :: * -> *) e a.
Applicative m =>
Either e a -> (e -> m a) -> m a
`onLeft` QErr -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError

mkQueryLog ::
  GQLReqUnparsed ->
  RootFieldAlias ->
  Maybe Text ->
  RequestId ->
  QueryLog
mkQueryLog :: GQLReqUnparsed
-> RootFieldAlias -> Maybe Text -> RequestId -> QueryLog
mkQueryLog GQLReqUnparsed
gqlQuery RootFieldAlias
fieldName Maybe Text
preparedSql RequestId
requestId =
  GQLReqUnparsed
-> Maybe (RootFieldAlias, GeneratedQuery)
-> RequestId
-> QueryLogKind
-> QueryLog
QueryLog GQLReqUnparsed
gqlQuery ((RootFieldAlias
fieldName,) (GeneratedQuery -> (RootFieldAlias, GeneratedQuery))
-> Maybe GeneratedQuery -> Maybe (RootFieldAlias, GeneratedQuery)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe GeneratedQuery
generatedQuery) RequestId
requestId QueryLogKind
QueryLogKindDatabase
  where
    generatedQuery :: Maybe GeneratedQuery
generatedQuery = Maybe Text
preparedSql Maybe Text -> (Text -> GeneratedQuery) -> Maybe GeneratedQuery
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \Text
qs -> Text -> Value -> GeneratedQuery
GeneratedQuery Text
qs Value
J.Null