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

module Hasura.Backends.DataConnector.Adapter.Execute
  (
  )
where

--------------------------------------------------------------------------------

import Data.Aeson qualified as J
import Data.ByteString.Lazy qualified as BL
import Data.Environment qualified as Env
import Data.Text.Encoding qualified as TE
import Data.Text.Extended (toTxt)
import Hasura.Backends.DataConnector.API qualified as API
import Hasura.Backends.DataConnector.Adapter.ConfigTransform (transformSourceConfig)
import Hasura.Backends.DataConnector.Adapter.Types (SourceConfig (..))
import Hasura.Backends.DataConnector.Agent.Client (AgentClientT)
import Hasura.Backends.DataConnector.IR.Query qualified as IR.Q
import Hasura.Backends.DataConnector.Plan qualified as DC
import Hasura.Base.Error (Code (..), QErr, throw400, throw500)
import Hasura.EncJSON (EncJSON, encJFromBuilder, encJFromJValue)
import Hasura.GraphQL.Execute.Backend (BackendExecute (..), DBStepInfo (..), ExplainPlan (..))
import Hasura.GraphQL.Namespace qualified as GQL
import Hasura.Prelude
import Hasura.RQL.Types.Common qualified as RQL
import Hasura.SQL.AnyBackend (mkAnyBackend)
import Hasura.SQL.Backend (BackendType (DataConnector))
import Hasura.Session
import Hasura.Tracing (MonadTrace)
import Hasura.Tracing qualified as Tracing
import Servant.Client.Core.HasClient ((//))
import Servant.Client.Generic (genericClient)
import Witch qualified

--------------------------------------------------------------------------------

instance BackendExecute 'DataConnector where
  type PreparedQuery 'DataConnector = IR.Q.QueryRequest
  type MultiplexedQuery 'DataConnector = Void
  type ExecutionMonad 'DataConnector = AgentClientT (Tracing.TraceT (ExceptT QErr IO))

  mkDBQueryPlan :: UserInfo
-> Environment
-> SourceName
-> SourceConfig 'DataConnector
-> QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector)
-> m (DBStepInfo 'DataConnector)
mkDBQueryPlan UserInfo {BackendOnlyFieldAccess
SessionVariables
RoleName
_uiBackendOnlyFieldAccess :: UserInfo -> BackendOnlyFieldAccess
_uiSession :: UserInfo -> SessionVariables
_uiRole :: UserInfo -> RoleName
_uiBackendOnlyFieldAccess :: BackendOnlyFieldAccess
_uiSession :: SessionVariables
_uiRole :: RoleName
..} Environment
env SourceName
sourceName SourceConfig 'DataConnector
sourceConfig QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector)
ir = do
    queryPlan :: QueryPlan
queryPlan@DC.QueryPlan {QueryRequest
forall (m :: * -> *).
MonadError QErr m =>
QueryResponse -> m Encoding
_qpResponseReshaper :: QueryPlan
-> forall (m :: * -> *).
   MonadError QErr m =>
   QueryResponse -> m Encoding
_qpRequest :: QueryPlan -> QueryRequest
_qpResponseReshaper :: forall (m :: * -> *).
MonadError QErr m =>
QueryResponse -> m Encoding
_qpRequest :: QueryRequest
..} <- SessionVariables
-> SourceConfig
-> QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector)
-> m QueryPlan
forall (m :: * -> *).
MonadError QErr m =>
SessionVariables
-> SourceConfig
-> QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector)
-> m QueryPlan
DC.mkPlan SessionVariables
_uiSession SourceConfig
SourceConfig 'DataConnector
sourceConfig QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector)
ir
    SourceConfig
transformedSourceConfig <- SourceConfig -> [(Text, Value)] -> Environment -> m SourceConfig
forall (m :: * -> *).
MonadError QErr m =>
SourceConfig -> [(Text, Value)] -> Environment -> m SourceConfig
transformSourceConfig SourceConfig
SourceConfig 'DataConnector
sourceConfig [(Text
"$session", SessionVariables -> Value
forall a. ToJSON a => a -> Value
J.toJSON SessionVariables
_uiSession), (Text
"$env", Environment -> Value
forall a. ToJSON a => a -> Value
J.toJSON Environment
env)] Environment
env
    DBStepInfo 'DataConnector -> m (DBStepInfo 'DataConnector)
forall (f :: * -> *) a. Applicative f => a -> f a
pure
      DBStepInfo :: forall (b :: BackendType).
SourceName
-> SourceConfig b
-> Maybe (PreparedQuery b)
-> ExecutionMonad b EncJSON
-> DBStepInfo b
DBStepInfo
        { dbsiSourceName :: SourceName
dbsiSourceName = SourceName
sourceName,
          dbsiSourceConfig :: SourceConfig 'DataConnector
dbsiSourceConfig = SourceConfig
SourceConfig 'DataConnector
transformedSourceConfig,
          dbsiPreparedQuery :: Maybe (PreparedQuery 'DataConnector)
dbsiPreparedQuery = QueryRequest -> Maybe QueryRequest
forall a. a -> Maybe a
Just QueryRequest
_qpRequest,
          dbsiAction :: ExecutionMonad 'DataConnector EncJSON
dbsiAction = SourceName
-> SourceConfig
-> QueryPlan
-> AgentClientT (TraceT (ExceptT QErr IO)) EncJSON
forall (m :: * -> *).
(MonadIO m, MonadTrace m, MonadError QErr m) =>
SourceName -> SourceConfig -> QueryPlan -> AgentClientT m EncJSON
buildQueryAction SourceName
sourceName SourceConfig
transformedSourceConfig QueryPlan
queryPlan
        }

  mkDBQueryExplain :: RootFieldAlias
-> UserInfo
-> SourceName
-> SourceConfig 'DataConnector
-> QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector)
-> m (AnyBackend DBStepInfo)
mkDBQueryExplain RootFieldAlias
fieldName UserInfo {BackendOnlyFieldAccess
SessionVariables
RoleName
_uiBackendOnlyFieldAccess :: BackendOnlyFieldAccess
_uiSession :: SessionVariables
_uiRole :: RoleName
_uiBackendOnlyFieldAccess :: UserInfo -> BackendOnlyFieldAccess
_uiSession :: UserInfo -> SessionVariables
_uiRole :: UserInfo -> RoleName
..} SourceName
sourceName SourceConfig 'DataConnector
sourceConfig QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector)
ir = do
    queryPlan :: QueryPlan
queryPlan@DC.QueryPlan {QueryRequest
forall (m :: * -> *).
MonadError QErr m =>
QueryResponse -> m Encoding
_qpResponseReshaper :: forall (m :: * -> *).
MonadError QErr m =>
QueryResponse -> m Encoding
_qpRequest :: QueryRequest
_qpResponseReshaper :: QueryPlan
-> forall (m :: * -> *).
   MonadError QErr m =>
   QueryResponse -> m Encoding
_qpRequest :: QueryPlan -> QueryRequest
..} <- SessionVariables
-> SourceConfig
-> QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector)
-> m QueryPlan
forall (m :: * -> *).
MonadError QErr m =>
SessionVariables
-> SourceConfig
-> QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector)
-> m QueryPlan
DC.mkPlan SessionVariables
_uiSession SourceConfig
SourceConfig 'DataConnector
sourceConfig QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector)
ir
    SourceConfig
transformedSourceConfig <- SourceConfig -> [(Text, Value)] -> Environment -> m SourceConfig
forall (m :: * -> *).
MonadError QErr m =>
SourceConfig -> [(Text, Value)] -> Environment -> m SourceConfig
transformSourceConfig SourceConfig
SourceConfig 'DataConnector
sourceConfig [(Text
"$session", SessionVariables -> Value
forall a. ToJSON a => a -> Value
J.toJSON SessionVariables
_uiSession), (Text
"$env", [Pair] -> Value
J.object [])] Environment
Env.emptyEnvironment
    AnyBackend DBStepInfo -> m (AnyBackend DBStepInfo)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (AnyBackend DBStepInfo -> m (AnyBackend DBStepInfo))
-> AnyBackend DBStepInfo -> m (AnyBackend DBStepInfo)
forall a b. (a -> b) -> a -> b
$
      DBStepInfo 'DataConnector -> AnyBackend DBStepInfo
forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
i b -> AnyBackend i
mkAnyBackend @'DataConnector
        DBStepInfo :: forall (b :: BackendType).
SourceName
-> SourceConfig b
-> Maybe (PreparedQuery b)
-> ExecutionMonad b EncJSON
-> DBStepInfo b
DBStepInfo
          { dbsiSourceName :: SourceName
dbsiSourceName = SourceName
sourceName,
            dbsiSourceConfig :: SourceConfig 'DataConnector
dbsiSourceConfig = SourceConfig
SourceConfig 'DataConnector
transformedSourceConfig,
            dbsiPreparedQuery :: Maybe (PreparedQuery 'DataConnector)
dbsiPreparedQuery = QueryRequest -> Maybe QueryRequest
forall a. a -> Maybe a
Just QueryRequest
_qpRequest,
            dbsiAction :: ExecutionMonad 'DataConnector EncJSON
dbsiAction = RootFieldAlias
-> SourceName
-> SourceConfig
-> QueryPlan
-> AgentClientT (TraceT (ExceptT QErr IO)) EncJSON
forall (m :: * -> *).
(MonadIO m, MonadTrace m, MonadError QErr m) =>
RootFieldAlias
-> SourceName
-> SourceConfig
-> QueryPlan
-> AgentClientT m EncJSON
buildExplainAction RootFieldAlias
fieldName SourceName
sourceName SourceConfig
transformedSourceConfig QueryPlan
queryPlan
          }
  mkDBMutationPlan :: UserInfo
-> StringifyNumbers
-> SourceName
-> SourceConfig 'DataConnector
-> MutationDB 'DataConnector Void (UnpreparedValue 'DataConnector)
-> m (DBStepInfo 'DataConnector)
mkDBMutationPlan UserInfo
_ StringifyNumbers
_ SourceName
_ SourceConfig 'DataConnector
_ MutationDB 'DataConnector Void (UnpreparedValue 'DataConnector)
_ =
    Code -> Text -> m (DBStepInfo 'DataConnector)
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"mkDBMutationPlan: not implemented for the Data Connector backend."
  mkLiveQuerySubscriptionPlan :: UserInfo
-> SourceName
-> SourceConfig 'DataConnector
-> Maybe Name
-> RootFieldMap
     (QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector))
-> m (SubscriptionQueryPlan
        'DataConnector (MultiplexedQuery 'DataConnector))
mkLiveQuerySubscriptionPlan UserInfo
_ SourceName
_ SourceConfig 'DataConnector
_ Maybe Name
_ RootFieldMap
  (QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector))
_ =
    Code -> Text -> m (SubscriptionQueryPlan 'DataConnector Void)
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"mkLiveQuerySubscriptionPlan: not implemented for the Data Connector backend."
  mkDBStreamingSubscriptionPlan :: UserInfo
-> SourceName
-> SourceConfig 'DataConnector
-> (RootFieldAlias,
    QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector))
-> m (SubscriptionQueryPlan
        'DataConnector (MultiplexedQuery 'DataConnector))
mkDBStreamingSubscriptionPlan UserInfo
_ SourceName
_ SourceConfig 'DataConnector
_ (RootFieldAlias,
 QueryDB 'DataConnector Void (UnpreparedValue 'DataConnector))
_ =
    Code -> Text -> m (SubscriptionQueryPlan 'DataConnector Void)
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"mkLiveQuerySubscriptionPlan: not implemented for the Data Connector backend."
  mkDBRemoteRelationshipPlan :: UserInfo
-> SourceName
-> SourceConfig 'DataConnector
-> NonEmpty Object
-> HashMap
     FieldName (Column 'DataConnector, ScalarType 'DataConnector)
-> FieldName
-> (FieldName,
    SourceRelationshipSelection 'DataConnector Void UnpreparedValue)
-> m (DBStepInfo 'DataConnector)
mkDBRemoteRelationshipPlan UserInfo
_ SourceName
_ SourceConfig 'DataConnector
_ NonEmpty Object
_ HashMap
  FieldName (Column 'DataConnector, ScalarType 'DataConnector)
_ FieldName
_ (FieldName,
 SourceRelationshipSelection 'DataConnector Void UnpreparedValue)
_ =
    Text -> m (DBStepInfo 'DataConnector)
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 Text
"mkDBRemoteRelationshipPlan: not implemented for the Data Connector backend."
  mkSubscriptionExplain :: SubscriptionQueryPlan
  'DataConnector (MultiplexedQuery 'DataConnector)
-> m SubscriptionQueryPlanExplanation
mkSubscriptionExplain SubscriptionQueryPlan
  'DataConnector (MultiplexedQuery 'DataConnector)
_ =
    Code -> Text -> m SubscriptionQueryPlanExplanation
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"mkSubscriptionExplain: not implemented for the Data Connector backend."

buildQueryAction :: (MonadIO m, MonadTrace m, MonadError QErr m) => RQL.SourceName -> SourceConfig -> DC.QueryPlan -> AgentClientT m EncJSON
buildQueryAction :: SourceName -> SourceConfig -> QueryPlan -> AgentClientT m EncJSON
buildQueryAction SourceName
sourceName SourceConfig {Maybe Int
Maybe Text
SchemaResponse
Capabilities
Config
Manager
BaseUrl
DataConnectorName
_scDataConnectorName :: SourceConfig -> DataConnectorName
_scTimeoutMicroseconds :: SourceConfig -> Maybe Int
_scManager :: SourceConfig -> Manager
_scSchema :: SourceConfig -> SchemaResponse
_scCapabilities :: SourceConfig -> Capabilities
_scTemplate :: SourceConfig -> Maybe Text
_scConfig :: SourceConfig -> Config
_scEndpoint :: SourceConfig -> BaseUrl
_scDataConnectorName :: DataConnectorName
_scTimeoutMicroseconds :: Maybe Int
_scManager :: Manager
_scSchema :: SchemaResponse
_scCapabilities :: Capabilities
_scTemplate :: Maybe Text
_scConfig :: Config
_scEndpoint :: BaseUrl
..} DC.QueryPlan {QueryRequest
forall (m :: * -> *).
MonadError QErr m =>
QueryResponse -> m Encoding
_qpResponseReshaper :: forall (m :: * -> *).
MonadError QErr m =>
QueryResponse -> m Encoding
_qpRequest :: QueryRequest
_qpResponseReshaper :: QueryPlan
-> forall (m :: * -> *).
   MonadError QErr m =>
   QueryResponse -> m Encoding
_qpRequest :: QueryPlan -> QueryRequest
..} = do
  -- NOTE: Should this check occur during query construction in 'mkPlan'?
  Bool -> AgentClientT m () -> AgentClientT m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (QueryRequest -> Bool
DC.queryHasRelations QueryRequest
_qpRequest Bool -> Bool -> Bool
&& Maybe RelationshipCapabilities -> Bool
forall a. Maybe a -> Bool
isNothing (Capabilities -> Maybe RelationshipCapabilities
API.cRelationships Capabilities
_scCapabilities)) (AgentClientT m () -> AgentClientT m ())
-> AgentClientT m () -> AgentClientT m ()
forall a b. (a -> b) -> a -> b
$
    Code -> Text -> AgentClientT m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"Agents must provide their own dataloader."
  let apiQueryRequest :: QueryRequest
apiQueryRequest = QueryRequest -> QueryRequest
forall target source. From source target => source -> target
Witch.into @API.QueryRequest QueryRequest
_qpRequest
  QueryResponse
queryResponse <- (Routes (AsClientT (AgentClientT m))
forall (routes :: * -> *) (m :: * -> *).
(HasClient m (ToServantApi routes),
 GenericServant routes (AsClientT m),
 Client m (ToServantApi routes) ~ ToServant routes (AsClientT m)) =>
routes (AsClientT m)
genericClient Routes (AsClientT (AgentClientT m))
-> (Routes (AsClientT (AgentClientT m))
    -> Text -> Config -> QueryRequest -> AgentClientT m QueryResponse)
-> Text
-> Config
-> QueryRequest
-> AgentClientT m QueryResponse
forall a b. a -> (a -> b) -> b
// Routes (AsClientT (AgentClientT m))
-> Text -> Config -> QueryRequest -> AgentClientT m QueryResponse
forall mode. Routes mode -> mode :- QueryApi
API._query) (SourceName -> Text
forall a. ToTxt a => a -> Text
toTxt SourceName
sourceName) Config
_scConfig QueryRequest
apiQueryRequest
  Encoding
reshapedResponse <- QueryResponse -> AgentClientT m Encoding
forall (m :: * -> *).
MonadError QErr m =>
QueryResponse -> m Encoding
_qpResponseReshaper QueryResponse
queryResponse
  EncJSON -> AgentClientT m EncJSON
forall (f :: * -> *) a. Applicative f => a -> f a
pure (EncJSON -> AgentClientT m EncJSON)
-> (Builder -> EncJSON) -> Builder -> AgentClientT m EncJSON
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Builder -> EncJSON
encJFromBuilder (Builder -> AgentClientT m EncJSON)
-> Builder -> AgentClientT m EncJSON
forall a b. (a -> b) -> a -> b
$ Encoding -> Builder
forall tag. Encoding' tag -> Builder
J.fromEncoding Encoding
reshapedResponse

-- Delegates the generation to the Agent's /explain endpoint if it has that capability,
-- otherwise, returns the IR sent to the agent.
buildExplainAction :: (MonadIO m, MonadTrace m, MonadError QErr m) => GQL.RootFieldAlias -> RQL.SourceName -> SourceConfig -> DC.QueryPlan -> AgentClientT m EncJSON
buildExplainAction :: RootFieldAlias
-> SourceName
-> SourceConfig
-> QueryPlan
-> AgentClientT m EncJSON
buildExplainAction RootFieldAlias
fieldName SourceName
sourceName SourceConfig {Maybe Int
Maybe Text
SchemaResponse
Capabilities
Config
Manager
BaseUrl
DataConnectorName
_scDataConnectorName :: DataConnectorName
_scTimeoutMicroseconds :: Maybe Int
_scManager :: Manager
_scSchema :: SchemaResponse
_scCapabilities :: Capabilities
_scTemplate :: Maybe Text
_scConfig :: Config
_scEndpoint :: BaseUrl
_scDataConnectorName :: SourceConfig -> DataConnectorName
_scTimeoutMicroseconds :: SourceConfig -> Maybe Int
_scManager :: SourceConfig -> Manager
_scSchema :: SourceConfig -> SchemaResponse
_scCapabilities :: SourceConfig -> Capabilities
_scTemplate :: SourceConfig -> Maybe Text
_scConfig :: SourceConfig -> Config
_scEndpoint :: SourceConfig -> BaseUrl
..} DC.QueryPlan {QueryRequest
forall (m :: * -> *).
MonadError QErr m =>
QueryResponse -> m Encoding
_qpResponseReshaper :: forall (m :: * -> *).
MonadError QErr m =>
QueryResponse -> m Encoding
_qpRequest :: QueryRequest
_qpResponseReshaper :: QueryPlan
-> forall (m :: * -> *).
   MonadError QErr m =>
   QueryResponse -> m Encoding
_qpRequest :: QueryPlan -> QueryRequest
..} =
  case Capabilities -> Maybe ExplainCapabilities
API.cExplain Capabilities
_scCapabilities of
    Maybe ExplainCapabilities
Nothing -> EncJSON -> AgentClientT m EncJSON
forall (f :: * -> *) a. Applicative f => a -> f a
pure (EncJSON -> AgentClientT m EncJSON)
-> (QueryRequest -> EncJSON)
-> QueryRequest
-> AgentClientT m EncJSON
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExplainPlan -> EncJSON
forall a. ToJSON a => a -> EncJSON
encJFromJValue (ExplainPlan -> EncJSON)
-> (QueryRequest -> ExplainPlan) -> QueryRequest -> EncJSON
forall b c a. (b -> c) -> (a -> b) -> a -> c
. RootFieldAlias -> QueryRequest -> ExplainPlan
toExplainPlan RootFieldAlias
fieldName (QueryRequest -> AgentClientT m EncJSON)
-> QueryRequest -> AgentClientT m EncJSON
forall a b. (a -> b) -> a -> b
$ QueryRequest
_qpRequest
    Just ExplainCapabilities
API.ExplainCapabilities -> do
      let apiQueryRequest :: QueryRequest
apiQueryRequest = QueryRequest -> QueryRequest
forall target source. From source target => source -> target
Witch.into @API.QueryRequest QueryRequest
_qpRequest
      ExplainResponse
explainResponse <- (Routes (AsClientT (AgentClientT m))
forall (routes :: * -> *) (m :: * -> *).
(HasClient m (ToServantApi routes),
 GenericServant routes (AsClientT m),
 Client m (ToServantApi routes) ~ ToServant routes (AsClientT m)) =>
routes (AsClientT m)
genericClient Routes (AsClientT (AgentClientT m))
-> (Routes (AsClientT (AgentClientT m))
    -> Text
    -> Config
    -> QueryRequest
    -> AgentClientT m ExplainResponse)
-> Text
-> Config
-> QueryRequest
-> AgentClientT m ExplainResponse
forall a b. a -> (a -> b) -> b
// Routes (AsClientT (AgentClientT m))
-> Text -> Config -> QueryRequest -> AgentClientT m ExplainResponse
forall mode. Routes mode -> mode :- ExplainApi
API._explain) (SourceName -> Text
forall a. ToTxt a => a -> Text
toTxt SourceName
sourceName) Config
_scConfig QueryRequest
apiQueryRequest
      EncJSON -> AgentClientT m EncJSON
forall (f :: * -> *) a. Applicative f => a -> f a
pure (EncJSON -> AgentClientT m EncJSON)
-> (ExplainPlan -> EncJSON)
-> ExplainPlan
-> AgentClientT m EncJSON
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ExplainPlan -> EncJSON
forall a. ToJSON a => a -> EncJSON
encJFromJValue (ExplainPlan -> AgentClientT m EncJSON)
-> ExplainPlan -> AgentClientT m EncJSON
forall a b. (a -> b) -> a -> b
$
        RootFieldAlias -> Maybe Text -> Maybe [Text] -> ExplainPlan
ExplainPlan
          RootFieldAlias
fieldName
          (Text -> Maybe Text
forall a. a -> Maybe a
Just (ExplainResponse -> Text
API._erQuery ExplainResponse
explainResponse))
          ([Text] -> Maybe [Text]
forall a. a -> Maybe a
Just (ExplainResponse -> [Text]
API._erLines ExplainResponse
explainResponse))

toExplainPlan :: GQL.RootFieldAlias -> IR.Q.QueryRequest -> ExplainPlan
toExplainPlan :: RootFieldAlias -> QueryRequest -> ExplainPlan
toExplainPlan RootFieldAlias
fieldName QueryRequest
queryRequest =
  RootFieldAlias -> Maybe Text -> Maybe [Text] -> ExplainPlan
ExplainPlan RootFieldAlias
fieldName (Text -> Maybe Text
forall a. a -> Maybe a
Just Text
"") ([Text] -> Maybe [Text]
forall a. a -> Maybe a
Just [ByteString -> Text
TE.decodeUtf8 (ByteString -> Text) -> ByteString -> Text
forall a b. (a -> b) -> a -> b
$ ByteString -> ByteString
BL.toStrict (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$ QueryRequest -> ByteString
forall a. ToJSON a => a -> ByteString
J.encode (QueryRequest -> ByteString) -> QueryRequest -> ByteString
forall a b. (a -> b) -> a -> b
$ QueryRequest
queryRequest])