module Hasura.GraphQL.Execute
( EB.ExecutionStep (..),
ResolvedExecutionPlan (..),
ET.GraphQLQueryType (..),
getResolvedExecPlan,
makeGQLContext,
execRemoteGQ,
SubscriptionExecution (..),
buildSubscriptionPlan,
EC.MonadGQLExecutionCheck (..),
checkQueryInAllowlist,
MultiplexedSubscriptionQueryPlan (..),
SubscriptionQueryPlan (..),
SourceSubscription (..),
)
where
import Control.Monad.Trans.Control (MonadBaseControl)
import Data.Aeson qualified as J
import Data.Aeson.Ordered qualified as JO
import Data.Containers.ListUtils (nubOrd)
import Data.Environment qualified as Env
import Data.HashMap.Strict qualified as HashMap
import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
import Data.HashSet qualified as HS
import Data.List (elemIndex)
import Data.Monoid (Endo (..))
import Data.Tagged qualified as Tagged
import Hasura.Backends.Postgres.Execute.Types
import Hasura.Base.Error
import Hasura.EncJSON
import Hasura.GraphQL.Context qualified as C
import Hasura.GraphQL.Execute.Action qualified as EA
import Hasura.GraphQL.Execute.Backend qualified as EB
import Hasura.GraphQL.Execute.Common qualified as EC
import Hasura.GraphQL.Execute.Mutation qualified as EM
import Hasura.GraphQL.Execute.Query qualified as EQ
import Hasura.GraphQL.Execute.RemoteJoin qualified as RJ
import Hasura.GraphQL.Execute.Resolve qualified as ER
import Hasura.GraphQL.Execute.Subscription.Plan qualified as ES
import Hasura.GraphQL.Execute.Types qualified as ET
import Hasura.GraphQL.Namespace
import Hasura.GraphQL.ParameterizedQueryHash
import Hasura.GraphQL.Parser.Directives
import Hasura.GraphQL.RemoteServer (execRemoteGQ)
import Hasura.GraphQL.Schema.Parser (runParse, toQErr)
import Hasura.GraphQL.Transport.HTTP.Protocol
import Hasura.Logging qualified as L
import Hasura.Metadata.Class
import Hasura.Prelude
import Hasura.QueryTags
import Hasura.RQL.IR qualified as IR
import Hasura.RQL.Types.Action
import Hasura.RQL.Types.Allowlist
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Roles (adminRoleName)
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.Subscription
import Hasura.SQL.AnyBackend qualified as AB
import Hasura.Server.Init qualified as Init
import Hasura.Server.Prometheus (PrometheusMetrics)
import Hasura.Server.Types (ReadOnlyMode (..), RequestId (..))
import Hasura.Services
import Hasura.Session (BackendOnlyFieldAccess (..), UserInfo (..))
import Hasura.Tracing qualified as Tracing
import Language.GraphQL.Draft.Syntax qualified as G
import Network.HTTP.Types qualified as HTTP
makeGQLContext ::
UserInfo ->
SchemaCache ->
ET.GraphQLQueryType ->
C.GQLContext
makeGQLContext :: UserInfo -> SchemaCache -> GraphQLQueryType -> GQLContext
makeGQLContext UserInfo
userInfo SchemaCache
sc GraphQLQueryType
queryType =
case RoleName
-> HashMap RoleName (RoleContext GQLContext)
-> Maybe (RoleContext GQLContext)
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup RoleName
role HashMap RoleName (RoleContext GQLContext)
contextMap of
Maybe (RoleContext GQLContext)
Nothing -> GQLContext
defaultContext
Just (C.RoleContext GQLContext
frontend Maybe GQLContext
backend) ->
case UserInfo -> BackendOnlyFieldAccess
_uiBackendOnlyFieldAccess UserInfo
userInfo of
BackendOnlyFieldAccess
BOFAAllowed -> GQLContext -> Maybe GQLContext -> GQLContext
forall a. a -> Maybe a -> a
fromMaybe GQLContext
frontend Maybe GQLContext
backend
BackendOnlyFieldAccess
BOFADisallowed -> GQLContext
frontend
where
role :: RoleName
role = UserInfo -> RoleName
_uiRole UserInfo
userInfo
contextMap :: HashMap RoleName (RoleContext GQLContext)
contextMap =
case GraphQLQueryType
queryType of
GraphQLQueryType
ET.QueryHasura -> SchemaCache -> HashMap RoleName (RoleContext GQLContext)
scGQLContext SchemaCache
sc
GraphQLQueryType
ET.QueryRelay -> SchemaCache -> HashMap RoleName (RoleContext GQLContext)
scRelayContext SchemaCache
sc
defaultContext :: GQLContext
defaultContext =
case GraphQLQueryType
queryType of
GraphQLQueryType
ET.QueryHasura -> SchemaCache -> GQLContext
scUnauthenticatedGQLContext SchemaCache
sc
GraphQLQueryType
ET.QueryRelay -> SchemaCache -> GQLContext
scUnauthenticatedRelayContext SchemaCache
sc
data ResolvedExecutionPlan
=
QueryExecutionPlan EB.ExecutionPlan [IR.QueryRootField IR.UnpreparedValue] DirectiveMap
|
MutationExecutionPlan EB.ExecutionPlan
|
SubscriptionExecutionPlan (SubscriptionExecution, Maybe (Endo JO.Value))
newtype MultiplexedSubscriptionQueryPlan (b :: BackendType)
= MultiplexedSubscriptionQueryPlan (ES.SubscriptionQueryPlan b (EB.MultiplexedQuery b))
newtype SubscriptionQueryPlan = SubscriptionQueryPlan (AB.AnyBackend MultiplexedSubscriptionQueryPlan)
data SourceSubscription
= SSLivequery !(HashSet ActionId) !(ActionLogResponseMap -> ExceptT QErr IO (SourceName, SubscriptionQueryPlan))
| SSStreaming !RootFieldAlias !(SourceName, SubscriptionQueryPlan)
data SubscriptionExecution
= SEAsyncActionsWithNoRelationships !(RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
| SEOnSourceDB !SourceSubscription
buildSubscriptionPlan ::
forall m.
(MonadError QErr m, MonadQueryTags m, MonadIO m, MonadBaseControl IO m) =>
UserInfo ->
RootFieldMap (IR.QueryRootField IR.UnpreparedValue) ->
ParameterizedQueryHash ->
[HTTP.Header] ->
Maybe G.Name ->
m (SubscriptionExecution, Maybe (Endo JO.Value))
buildSubscriptionPlan :: forall (m :: * -> *).
(MonadError QErr m, MonadQueryTags m, MonadIO m,
MonadBaseControl IO m) =>
UserInfo
-> RootFieldMap (QueryRootField UnpreparedValue)
-> ParameterizedQueryHash
-> [Header]
-> Maybe Name
-> m (SubscriptionExecution, Maybe (Endo Value))
buildSubscriptionPlan UserInfo
userInfo RootFieldMap (QueryRootField UnpreparedValue)
rootFields ParameterizedQueryHash
parameterizedQueryHash [Header]
reqHeaders Maybe Name
operationName = do
(((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
liveQueryOnSourceFields, RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)
noRelationActionFields), RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
streamingFields), Maybe (Endo Value)
modifier) <- ((((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> (RootFieldAlias, QueryRootField UnpreparedValue)
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value)))
-> (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> [(RootFieldAlias, QueryRootField UnpreparedValue)]
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
forall (t :: * -> *) (m :: * -> *) b a.
(Foldable t, Monad m) =>
(b -> a -> m b) -> b -> t a -> m b
foldlM (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> (RootFieldAlias, QueryRootField UnpreparedValue)
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
go (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
forall a. Monoid a => a
mempty, RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)
forall a. Monoid a => a
mempty), RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
forall a. Monoid a => a
mempty), Maybe (Endo Value)
forall a. Monoid a => a
mempty) (RootFieldMap (QueryRootField UnpreparedValue)
-> [(RootFieldAlias, QueryRootField UnpreparedValue)]
forall k v. InsOrdHashMap k v -> [(k, v)]
InsOrdHashMap.toList RootFieldMap (QueryRootField UnpreparedValue)
rootFields)
if
| RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> Bool
forall a. InsOrdHashMap RootFieldAlias a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
liveQueryOnSourceFields Bool -> Bool -> Bool
&& RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> Bool
forall a. InsOrdHashMap RootFieldAlias a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
streamingFields ->
(SubscriptionExecution, Maybe (Endo Value))
-> m (SubscriptionExecution, Maybe (Endo Value))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((SubscriptionExecution, Maybe (Endo Value))
-> m (SubscriptionExecution, Maybe (Endo Value)))
-> (SubscriptionExecution, Maybe (Endo Value))
-> m (SubscriptionExecution, Maybe (Endo Value))
forall a b. (a -> b) -> a -> b
$ (RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)
-> SubscriptionExecution
SEAsyncActionsWithNoRelationships RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)
noRelationActionFields, Maybe (Endo Value)
modifier)
| RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)
-> Bool
forall a. InsOrdHashMap RootFieldAlias a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)
noRelationActionFields -> do
if
| RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> Bool
forall a. InsOrdHashMap RootFieldAlias a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
liveQueryOnSourceFields -> do
case RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> [(RootFieldAlias,
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))]
forall k v. InsOrdHashMap k v -> [(k, v)]
InsOrdHashMap.toList RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
streamingFields of
[] -> Text -> m (SubscriptionExecution, Maybe (Endo Value))
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 Text
"empty selset for subscription"
[(RootFieldAlias
rootFieldName, (SourceName
sourceName, AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))
exists))] -> do
SubscriptionQueryPlan
subscriptionPlan <- forall (c :: BackendType -> Constraint) (i :: BackendType -> *) r.
AllBackendsSatisfy c =>
AnyBackend i -> (forall (b :: BackendType). c b => i b -> r) -> r
AB.dispatchAnyBackend @EB.BackendExecute
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))
exists
\(IR.SourceConfigWith SourceConfig b
sourceConfig Maybe QueryTagsConfig
queryTagsConfig (IR.QDBR QueryDB b Void (UnpreparedValue b)
qdb) :: IR.SourceConfigWith db b) -> do
let subscriptionQueryTagsAttributes :: QueryTagsAttributes
subscriptionQueryTagsAttributes = QueryTags -> QueryTagsAttributes
encodeQueryTags (QueryTags -> QueryTagsAttributes)
-> QueryTags -> QueryTagsAttributes
forall a b. (a -> b) -> a -> b
$ LivequeryMetadata -> QueryTags
QTLiveQuery (LivequeryMetadata -> QueryTags) -> LivequeryMetadata -> QueryTags
forall a b. (a -> b) -> a -> b
$ RootFieldAlias -> ParameterizedQueryHash -> LivequeryMetadata
LivequeryMetadata RootFieldAlias
rootFieldName ParameterizedQueryHash
parameterizedQueryHash
queryTagsComment :: QueryTagsComment
queryTagsComment = Tagged m QueryTagsComment -> QueryTagsComment
forall {k} (s :: k) b. Tagged s b -> b
Tagged.untag (Tagged m QueryTagsComment -> QueryTagsComment)
-> Tagged m QueryTagsComment -> QueryTagsComment
forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *).
MonadQueryTags m =>
QueryTagsAttributes
-> Maybe QueryTagsConfig -> Tagged m QueryTagsComment
createQueryTags @m QueryTagsAttributes
subscriptionQueryTagsAttributes Maybe QueryTagsConfig
queryTagsConfig
AnyBackend MultiplexedSubscriptionQueryPlan
-> SubscriptionQueryPlan
SubscriptionQueryPlan
(AnyBackend MultiplexedSubscriptionQueryPlan
-> SubscriptionQueryPlan)
-> (SubscriptionQueryPlan b (MultiplexedQuery b)
-> AnyBackend MultiplexedSubscriptionQueryPlan)
-> SubscriptionQueryPlan b (MultiplexedQuery b)
-> SubscriptionQueryPlan
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MultiplexedSubscriptionQueryPlan b
-> AnyBackend MultiplexedSubscriptionQueryPlan
forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
i b -> AnyBackend i
AB.mkAnyBackend
(MultiplexedSubscriptionQueryPlan b
-> AnyBackend MultiplexedSubscriptionQueryPlan)
-> (SubscriptionQueryPlan b (MultiplexedQuery b)
-> MultiplexedSubscriptionQueryPlan b)
-> SubscriptionQueryPlan b (MultiplexedQuery b)
-> AnyBackend MultiplexedSubscriptionQueryPlan
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SubscriptionQueryPlan b (MultiplexedQuery b)
-> MultiplexedSubscriptionQueryPlan b
forall (b :: BackendType).
SubscriptionQueryPlan b (MultiplexedQuery b)
-> MultiplexedSubscriptionQueryPlan b
MultiplexedSubscriptionQueryPlan
(SubscriptionQueryPlan b (MultiplexedQuery b)
-> SubscriptionQueryPlan)
-> m (SubscriptionQueryPlan b (MultiplexedQuery b))
-> m SubscriptionQueryPlan
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT
QueryTagsComment m (SubscriptionQueryPlan b (MultiplexedQuery b))
-> QueryTagsComment
-> m (SubscriptionQueryPlan b (MultiplexedQuery b))
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT
( UserInfo
-> SourceName
-> SourceConfig b
-> (RootFieldAlias, QueryDB b Void (UnpreparedValue b))
-> [Header]
-> Maybe Name
-> ReaderT
QueryTagsComment m (SubscriptionQueryPlan b (MultiplexedQuery b))
forall (b :: BackendType) (m :: * -> *).
(BackendExecute b, MonadError QErr m, MonadIO m,
MonadBaseControl IO m, MonadReader QueryTagsComment m) =>
UserInfo
-> SourceName
-> SourceConfig b
-> (RootFieldAlias, QueryDB b Void (UnpreparedValue b))
-> [Header]
-> Maybe Name
-> m (SubscriptionQueryPlan b (MultiplexedQuery b))
forall (m :: * -> *).
(MonadError QErr m, MonadIO m, MonadBaseControl IO m,
MonadReader QueryTagsComment m) =>
UserInfo
-> SourceName
-> SourceConfig b
-> (RootFieldAlias, QueryDB b Void (UnpreparedValue b))
-> [Header]
-> Maybe Name
-> m (SubscriptionQueryPlan b (MultiplexedQuery b))
EB.mkDBStreamingSubscriptionPlan
UserInfo
userInfo
SourceName
sourceName
SourceConfig b
sourceConfig
(RootFieldAlias
rootFieldName, QueryDB b Void (UnpreparedValue b)
qdb)
[Header]
reqHeaders
Maybe Name
operationName
)
QueryTagsComment
queryTagsComment
(SubscriptionExecution, Maybe (Endo Value))
-> m (SubscriptionExecution, Maybe (Endo Value))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
((SubscriptionExecution, Maybe (Endo Value))
-> m (SubscriptionExecution, Maybe (Endo Value)))
-> (SubscriptionExecution, Maybe (Endo Value))
-> m (SubscriptionExecution, Maybe (Endo Value))
forall a b. (a -> b) -> a -> b
$ (,Maybe (Endo Value)
modifier)
(SubscriptionExecution
-> (SubscriptionExecution, Maybe (Endo Value)))
-> SubscriptionExecution
-> (SubscriptionExecution, Maybe (Endo Value))
forall a b. (a -> b) -> a -> b
$ SourceSubscription -> SubscriptionExecution
SEOnSourceDB
(SourceSubscription -> SubscriptionExecution)
-> SourceSubscription -> SubscriptionExecution
forall a b. (a -> b) -> a -> b
$ RootFieldAlias
-> (SourceName, SubscriptionQueryPlan) -> SourceSubscription
SSStreaming RootFieldAlias
rootFieldName
((SourceName, SubscriptionQueryPlan) -> SourceSubscription)
-> (SourceName, SubscriptionQueryPlan) -> SourceSubscription
forall a b. (a -> b) -> a -> b
$ (SourceName
sourceName, SubscriptionQueryPlan
subscriptionPlan)
[(RootFieldAlias,
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))]
_ -> Code -> Text -> m (SubscriptionExecution, Maybe (Endo Value))
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"exactly one root field is allowed for streaming subscriptions"
| RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> Bool
forall a. InsOrdHashMap RootFieldAlias a -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
streamingFields -> do
let allActionIds :: HashSet ActionId
allActionIds = [ActionId] -> HashSet ActionId
forall a. (Eq a, Hashable a) => [a] -> HashSet a
HS.fromList ([ActionId] -> HashSet ActionId) -> [ActionId] -> HashSet ActionId
forall a b. (a -> b) -> a -> b
$ ((ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
-> ActionId)
-> [(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))]
-> [ActionId]
forall a b. (a -> b) -> [a] -> [b]
map (ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
-> ActionId
forall a b. (a, b) -> a
fst ([(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))]
-> [ActionId])
-> [(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))]
-> [ActionId]
forall a b. (a -> b) -> a -> b
$ [Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))]
-> [(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))]
forall a b. [Either a b] -> [a]
lefts ([Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))]
-> [(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))])
-> [Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))]
-> [(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))]
forall a b. (a -> b) -> a -> b
$ RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> [Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))]
forall a. InsOrdHashMap RootFieldAlias a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
liveQueryOnSourceFields
(SubscriptionExecution, Maybe (Endo Value))
-> m (SubscriptionExecution, Maybe (Endo Value))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure
((SubscriptionExecution, Maybe (Endo Value))
-> m (SubscriptionExecution, Maybe (Endo Value)))
-> (SubscriptionExecution, Maybe (Endo Value))
-> m (SubscriptionExecution, Maybe (Endo Value))
forall a b. (a -> b) -> a -> b
$ (,Maybe (Endo Value)
modifier)
(SubscriptionExecution
-> (SubscriptionExecution, Maybe (Endo Value)))
-> SubscriptionExecution
-> (SubscriptionExecution, Maybe (Endo Value))
forall a b. (a -> b) -> a -> b
$ SourceSubscription -> SubscriptionExecution
SEOnSourceDB
(SourceSubscription -> SubscriptionExecution)
-> SourceSubscription -> SubscriptionExecution
forall a b. (a -> b) -> a -> b
$ HashSet ActionId
-> (ActionLogResponseMap
-> ExceptT QErr IO (SourceName, SubscriptionQueryPlan))
-> SourceSubscription
SSLivequery HashSet ActionId
allActionIds
((ActionLogResponseMap
-> ExceptT QErr IO (SourceName, SubscriptionQueryPlan))
-> SourceSubscription)
-> (ActionLogResponseMap
-> ExceptT QErr IO (SourceName, SubscriptionQueryPlan))
-> SourceSubscription
forall a b. (a -> b) -> a -> b
$ \ActionLogResponseMap
actionLogMap -> do
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
sourceSubFields <- RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> (Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> ExceptT
QErr
IO
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> ExceptT
QErr
IO
(RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
t a -> (a -> f b) -> f (t b)
for RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
liveQueryOnSourceFields ((Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> ExceptT
QErr
IO
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> ExceptT
QErr
IO
(RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))))
-> (Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> ExceptT
QErr
IO
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> ExceptT
QErr
IO
(RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
forall a b. (a -> b) -> a -> b
$ \case
Right (SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
x -> (SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> ExceptT
QErr
IO
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
forall a. a -> ExceptT QErr IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
x
Left (ActionId
actionId, (PGSourceConfig
srcConfig, AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))
dbExecution)) -> do
let sourceName :: SourceName
sourceName = AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))
-> SourceName
forall v. AsyncActionQuerySourceExecution v -> SourceName
EA._aaqseSource AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))
dbExecution
ActionLogResponse
actionLogResponse <-
ActionId -> ActionLogResponseMap -> Maybe ActionLogResponse
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup ActionId
actionId ActionLogResponseMap
actionLogMap
Maybe ActionLogResponse
-> ExceptT QErr IO ActionLogResponse
-> ExceptT QErr IO ActionLogResponse
forall (m :: * -> *) a. Applicative m => Maybe a -> m a -> m a
`onNothing` Text -> ExceptT QErr IO ActionLogResponse
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 Text
"unexpected: cannot lookup action_id in the map"
let selectAST :: AnnSimpleSelectG
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
selectAST = AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))
-> ActionLogResponse
-> AnnSimpleSelectG
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
forall v.
AsyncActionQuerySourceExecution v
-> ActionLogResponse
-> AnnSimpleSelectG ('Postgres 'Vanilla) Void v
EA._aaqseSelectBuilder AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))
dbExecution (ActionLogResponse
-> AnnSimpleSelectG
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla)))
-> ActionLogResponse
-> AnnSimpleSelectG
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
forall a b. (a -> b) -> a -> b
$ ActionLogResponse
actionLogResponse
queryDB :: QueryDB
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
queryDB = case AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))
-> JsonAggSelect
forall v. AsyncActionQuerySourceExecution v -> JsonAggSelect
EA._aaqseJsonAggSelect AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))
dbExecution of
JsonAggSelect
JASMultipleRows -> AnnSimpleSelectG
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
-> QueryDB
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
forall (b :: BackendType) r v.
AnnSimpleSelectG b r v -> QueryDB b r v
IR.QDBMultipleRows AnnSimpleSelectG
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
selectAST
JsonAggSelect
JASSingleObject -> AnnSimpleSelectG
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
-> QueryDB
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
forall (b :: BackendType) r v.
AnnSimpleSelectG b r v -> QueryDB b r v
IR.QDBSingleRow AnnSimpleSelectG
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
selectAST
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> ExceptT
QErr
IO
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
forall a. a -> ExceptT QErr IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> ExceptT
QErr
IO
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> (SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> ExceptT
QErr
IO
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
forall a b. (a -> b) -> a -> b
$ (SourceName
sourceName, SourceConfigWith
(QueryDBRoot Void UnpreparedValue) ('Postgres 'Vanilla)
-> AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))
forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
i b -> AnyBackend i
AB.mkAnyBackend (SourceConfigWith
(QueryDBRoot Void UnpreparedValue) ('Postgres 'Vanilla)
-> AnyBackend
(SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> SourceConfigWith
(QueryDBRoot Void UnpreparedValue) ('Postgres 'Vanilla)
-> AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))
forall a b. (a -> b) -> a -> b
$ SourceConfig ('Postgres 'Vanilla)
-> Maybe QueryTagsConfig
-> QueryDBRoot Void UnpreparedValue ('Postgres 'Vanilla)
-> SourceConfigWith
(QueryDBRoot Void UnpreparedValue) ('Postgres 'Vanilla)
forall (db :: BackendType -> *) (b :: BackendType).
SourceConfig b
-> Maybe QueryTagsConfig -> db b -> SourceConfigWith db b
IR.SourceConfigWith SourceConfig ('Postgres 'Vanilla)
PGSourceConfig
srcConfig Maybe QueryTagsConfig
forall a. Maybe a
Nothing (QueryDB
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
-> QueryDBRoot Void UnpreparedValue ('Postgres 'Vanilla)
forall r (v :: BackendType -> *) (b :: BackendType).
QueryDB b r (v b) -> QueryDBRoot r v b
IR.QDBR QueryDB
('Postgres 'Vanilla) Void (UnpreparedValue ('Postgres 'Vanilla))
queryDB))
case RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> [(RootFieldAlias,
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))]
forall k v. InsOrdHashMap k v -> [(k, v)]
InsOrdHashMap.toList RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
sourceSubFields of
[] -> Text -> ExceptT QErr IO (SourceName, SubscriptionQueryPlan)
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 Text
"empty selset for subscription"
((RootFieldAlias
rootFieldName, (SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
sub) : [(RootFieldAlias,
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))]
_) -> (SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> RootFieldAlias
-> ExceptT QErr IO (SourceName, SubscriptionQueryPlan)
forall (b :: BackendType -> *).
(SourceName, AnyBackend (SourceConfigWith b))
-> RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> RootFieldAlias
-> ExceptT QErr IO (SourceName, SubscriptionQueryPlan)
buildAction (SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
sub RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
sourceSubFields RootFieldAlias
rootFieldName
| Bool
otherwise -> Code -> Text -> m (SubscriptionExecution, Maybe (Endo Value))
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"streaming and livequery subscriptions cannot be executed in the same subscription"
| Bool
otherwise ->
Code -> Text -> m (SubscriptionExecution, Maybe (Endo Value))
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400
Code
NotSupported
Text
"async action queries with no relationships aren't expected to mix with normal source database queries"
where
go ::
( ( ( RootFieldMap
( Either
(ActionId, (PGSourceConfig, EA.AsyncActionQuerySourceExecution (IR.UnpreparedValue ('Postgres 'Vanilla))))
(SourceName, AB.AnyBackend (IR.SourceConfigWith (IR.QueryDBRoot Void IR.UnpreparedValue)))
),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)
),
RootFieldMap (SourceName, AB.AnyBackend (IR.SourceConfigWith (IR.QueryDBRoot Void IR.UnpreparedValue)))
),
Maybe (Endo JO.Value)
) ->
(RootFieldAlias, IR.QueryRootField IR.UnpreparedValue) ->
m
( ( ( RootFieldMap
( Either
(ActionId, (PGSourceConfig, EA.AsyncActionQuerySourceExecution (IR.UnpreparedValue ('Postgres 'Vanilla))))
(SourceName, AB.AnyBackend (IR.SourceConfigWith (IR.QueryDBRoot Void IR.UnpreparedValue)))
),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)
),
RootFieldMap (SourceName, AB.AnyBackend (IR.SourceConfigWith (IR.QueryDBRoot Void IR.UnpreparedValue)))
),
Maybe (Endo JO.Value)
)
go :: (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> (RootFieldAlias, QueryRootField UnpreparedValue)
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
go (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
accLiveQueryFields, RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
accStreamingFields), Maybe (Endo Value)
modifier) (RootFieldAlias
gName, QueryRootField UnpreparedValue
field) = case QueryRootField UnpreparedValue
field of
IR.RFRemote RemoteSchemaRootField
(RemoteRelationshipField UnpreparedValue) RemoteSchemaVariable
_ -> Code
-> Text
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"subscription to remote server is not supported"
IR.RFRaw Value
val -> do
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe Name -> Bool
forall a. Maybe a -> Bool
isNothing (RootFieldAlias -> Maybe Name
_rfaNamespace RootFieldAlias
gName)) do
Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"Introspection at root field level is not supported over subscriptions"
let fieldIndex :: Int
fieldIndex = Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 (Maybe Int -> Int) -> Maybe Int -> Int
forall a b. (a -> b) -> a -> b
$ RootFieldAlias -> [RootFieldAlias] -> Maybe Int
forall a. Eq a => a -> [a] -> Maybe Int
elemIndex RootFieldAlias
gName ([RootFieldAlias] -> Maybe Int) -> [RootFieldAlias] -> Maybe Int
forall a b. (a -> b) -> a -> b
$ RootFieldMap (QueryRootField UnpreparedValue) -> [RootFieldAlias]
forall k v. InsOrdHashMap k v -> [k]
InsOrdHashMap.keys RootFieldMap (QueryRootField UnpreparedValue)
rootFields
newModifier :: Value -> Value
newModifier Value
oldResponse =
case Value -> Either String Object
forall s. IsString s => Value -> Either s Object
JO.asObject Value
oldResponse of
Left (String
_err :: String) -> Value
oldResponse
Right Object
responseObj ->
Object -> Value
JO.Object (Object -> Value) -> Object -> Value
forall a b. (a -> b) -> a -> b
$ (Int, Text) -> Value -> Object -> Object
JO.insert (Int
fieldIndex, Name -> Text
G.unName (Name -> Text) -> Name -> Text
forall a b. (a -> b) -> a -> b
$ RootFieldAlias -> Name
_rfaAlias RootFieldAlias
gName) Value
val Object
responseObj
(((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
accLiveQueryFields, RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
accStreamingFields), Endo Value -> Maybe (Endo Value)
forall a. a -> Maybe a
Just ((Value -> Value) -> Endo Value
forall a. (a -> a) -> Endo a
Endo Value -> Value
newModifier) Maybe (Endo Value) -> Maybe (Endo Value) -> Maybe (Endo Value)
forall a. Semigroup a => a -> a -> a
<> Maybe (Endo Value)
modifier)
IR.RFMulti [QueryRootField UnpreparedValue]
_ -> Code
-> Text
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"not supported over subscriptions"
IR.RFDB SourceName
src AnyBackend
(SourceConfigWith
(QueryDBRoot
(RemoteRelationshipField UnpreparedValue) UnpreparedValue))
e -> do
let subscriptionType :: SubscriptionType
subscriptionType =
case forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
AnyBackend i -> Maybe (i b)
AB.unpackAnyBackend @('Postgres 'Vanilla) AnyBackend
(SourceConfigWith
(QueryDBRoot
(RemoteRelationshipField UnpreparedValue) UnpreparedValue))
e of
Just (IR.SourceConfigWith SourceConfig ('Postgres 'Vanilla)
_ Maybe QueryTagsConfig
_ (IR.QDBR (IR.QDBStreamMultipleRows AnnSimpleStreamSelectG
('Postgres 'Vanilla)
(RemoteRelationshipField UnpreparedValue)
(UnpreparedValue ('Postgres 'Vanilla))
_))) -> SubscriptionType
Streaming
Maybe
(SourceConfigWith
(QueryDBRoot
(RemoteRelationshipField UnpreparedValue) UnpreparedValue)
('Postgres 'Vanilla))
_ -> case forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
AnyBackend i -> Maybe (i b)
AB.unpackAnyBackend @('Postgres 'Citus) AnyBackend
(SourceConfigWith
(QueryDBRoot
(RemoteRelationshipField UnpreparedValue) UnpreparedValue))
e of
Just (IR.SourceConfigWith SourceConfig ('Postgres 'Citus)
_ Maybe QueryTagsConfig
_ (IR.QDBR (IR.QDBStreamMultipleRows AnnSimpleStreamSelectG
('Postgres 'Citus)
(RemoteRelationshipField UnpreparedValue)
(UnpreparedValue ('Postgres 'Citus))
_))) -> SubscriptionType
Streaming
Maybe
(SourceConfigWith
(QueryDBRoot
(RemoteRelationshipField UnpreparedValue) UnpreparedValue)
('Postgres 'Citus))
_ -> case forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
AnyBackend i -> Maybe (i b)
AB.unpackAnyBackend @('Postgres 'Cockroach) AnyBackend
(SourceConfigWith
(QueryDBRoot
(RemoteRelationshipField UnpreparedValue) UnpreparedValue))
e of
Just (IR.SourceConfigWith SourceConfig ('Postgres 'Cockroach)
_ Maybe QueryTagsConfig
_ (IR.QDBR (IR.QDBStreamMultipleRows AnnSimpleStreamSelectG
('Postgres 'Cockroach)
(RemoteRelationshipField UnpreparedValue)
(UnpreparedValue ('Postgres 'Cockroach))
_))) -> SubscriptionType
Streaming
Maybe
(SourceConfigWith
(QueryDBRoot
(RemoteRelationshipField UnpreparedValue) UnpreparedValue)
('Postgres 'Cockroach))
_ -> SubscriptionType
LiveQuery
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))
newQDB <- forall (c :: BackendType -> Constraint) (i :: BackendType -> *)
(j :: BackendType -> *) (f :: * -> *).
(AllBackendsSatisfy c, Functor f) =>
AnyBackend i
-> (forall (b :: BackendType). c b => i b -> f (j b))
-> f (AnyBackend j)
AB.traverseBackend @EB.BackendExecute AnyBackend
(SourceConfigWith
(QueryDBRoot
(RemoteRelationshipField UnpreparedValue) UnpreparedValue))
e \(IR.SourceConfigWith SourceConfig b
srcConfig Maybe QueryTagsConfig
queryTagsConfig (IR.QDBR QueryDB
b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b)
qdb)) -> do
let (QueryDB b Void (UnpreparedValue b)
newQDB, Maybe RemoteJoins
remoteJoins) = QueryDB
b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b)
-> (QueryDB b Void (UnpreparedValue b), Maybe RemoteJoins)
forall (b :: BackendType).
Backend b =>
QueryDB
b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b)
-> (QueryDB b Void (UnpreparedValue b), Maybe RemoteJoins)
RJ.getRemoteJoinsQueryDB QueryDB
b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b)
qdb
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Maybe RemoteJoins -> Bool
forall a. Maybe a -> Bool
isNothing Maybe RemoteJoins
remoteJoins)
(m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"Remote relationships are not allowed in subscriptions"
SourceConfigWith (QueryDBRoot Void UnpreparedValue) b
-> m (SourceConfigWith (QueryDBRoot Void UnpreparedValue) b)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SourceConfigWith (QueryDBRoot Void UnpreparedValue) b
-> m (SourceConfigWith (QueryDBRoot Void UnpreparedValue) b))
-> SourceConfigWith (QueryDBRoot Void UnpreparedValue) b
-> m (SourceConfigWith (QueryDBRoot Void UnpreparedValue) b)
forall a b. (a -> b) -> a -> b
$ SourceConfig b
-> Maybe QueryTagsConfig
-> QueryDBRoot Void UnpreparedValue b
-> SourceConfigWith (QueryDBRoot Void UnpreparedValue) b
forall (db :: BackendType -> *) (b :: BackendType).
SourceConfig b
-> Maybe QueryTagsConfig -> db b -> SourceConfigWith db b
IR.SourceConfigWith SourceConfig b
srcConfig Maybe QueryTagsConfig
queryTagsConfig (QueryDB b Void (UnpreparedValue b)
-> QueryDBRoot Void UnpreparedValue b
forall r (v :: BackendType -> *) (b :: BackendType).
QueryDB b r (v b) -> QueryDBRoot r v b
IR.QDBR QueryDB b Void (UnpreparedValue b)
newQDB)
case SubscriptionType
subscriptionType of
SubscriptionType
Streaming -> (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
accLiveQueryFields, RootFieldAlias
-> (SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
forall k v.
(Eq k, Hashable k) =>
k -> v -> InsOrdHashMap k v -> InsOrdHashMap k v
InsOrdHashMap.insert RootFieldAlias
gName (SourceName
src, AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))
newQDB) RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
accStreamingFields), Maybe (Endo Value)
modifier)
SubscriptionType
LiveQuery -> (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))))
-> (RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
-> (RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
forall b c d. (b -> c) -> (b, d) -> (c, d)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (RootFieldAlias
-> Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
forall k v.
(Eq k, Hashable k) =>
k -> v -> InsOrdHashMap k v -> InsOrdHashMap k v
InsOrdHashMap.insert RootFieldAlias
gName ((SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
forall a b. b -> Either a b
Right (SourceName
src, AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))
newQDB))) (RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
accLiveQueryFields, RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
accStreamingFields), Maybe (Endo Value)
modifier)
IR.RFAction QueryActionRoot UnpreparedValue
action -> do
let (ActionQuery Void
noRelsDBAST, Maybe RemoteJoins
remoteJoins) = QueryActionRoot UnpreparedValue
-> (ActionQuery Void, Maybe RemoteJoins)
RJ.getRemoteJoinsActionQuery QueryActionRoot UnpreparedValue
action
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Maybe RemoteJoins -> Bool
forall a. Maybe a -> Bool
isNothing Maybe RemoteJoins
remoteJoins)
(m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"Remote relationships are not allowed in subscriptions"
case ActionQuery Void
noRelsDBAST of
IR.AQAsync AnnActionAsyncQuery ('Postgres 'Vanilla) Void
q -> do
let actionId :: ActionId
actionId = AnnActionAsyncQuery ('Postgres 'Vanilla) Void -> ActionId
forall (b :: BackendType) r. AnnActionAsyncQuery b r -> ActionId
IR._aaaqActionId AnnActionAsyncQuery ('Postgres 'Vanilla) Void
q
case UserInfo
-> AnnActionAsyncQuery ('Postgres 'Vanilla) Void
-> AsyncActionQueryExecution (UnpreparedValue ('Postgres 'Vanilla))
EA.resolveAsyncActionQuery UserInfo
userInfo AnnActionAsyncQuery ('Postgres 'Vanilla) Void
q of
EA.AAQENoRelationships ActionLogResponse -> Either QErr EncJSON
respMaker ->
(((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value)))
-> (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
forall a b. (a -> b) -> a -> b
$ (((RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)
-> RootFieldMap
(ActionId, ActionLogResponse -> Either QErr EncJSON))
-> (RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
-> (RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
forall b c d. (b -> c) -> (d, b) -> (d, c)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (RootFieldAlias
-> (ActionId, ActionLogResponse -> Either QErr EncJSON)
-> RootFieldMap
(ActionId, ActionLogResponse -> Either QErr EncJSON)
-> RootFieldMap
(ActionId, ActionLogResponse -> Either QErr EncJSON)
forall k v.
(Eq k, Hashable k) =>
k -> v -> InsOrdHashMap k v -> InsOrdHashMap k v
InsOrdHashMap.insert RootFieldAlias
gName (ActionId
actionId, ActionLogResponse -> Either QErr EncJSON
respMaker)) (RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
accLiveQueryFields, RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
accStreamingFields), Maybe (Endo Value)
modifier)
EA.AAQEOnSourceDB SourceConfig ('Postgres 'Vanilla)
srcConfig AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))
dbExecution ->
(((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value)))
-> (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
forall a b. (a -> b) -> a -> b
$ (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))))
-> (RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
-> (RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
forall b c d. (b -> c) -> (b, d) -> (c, d)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (b, d) (c, d)
first (RootFieldAlias
-> Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
-> RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))))
forall k v.
(Eq k, Hashable k) =>
k -> v -> InsOrdHashMap k v -> InsOrdHashMap k v
InsOrdHashMap.insert RootFieldAlias
gName ((ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
-> Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
forall a b. a -> Either a b
Left (ActionId
actionId, (SourceConfig ('Postgres 'Vanilla)
PGSourceConfig
srcConfig, AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))
dbExecution)))) (RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON))
accLiveQueryFields, RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
accStreamingFields), Maybe (Endo Value)
modifier)
IR.AQQuery AnnActionExecution Void
_ -> Code
-> Text
-> m (((RootFieldMap
(Either
(ActionId,
(PGSourceConfig,
AsyncActionQuerySourceExecution
(UnpreparedValue ('Postgres 'Vanilla))))
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
RootFieldMap (ActionId, ActionLogResponse -> Either QErr EncJSON)),
RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))),
Maybe (Endo Value))
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"query actions cannot be run as a subscription"
buildAction ::
(SourceName, AB.AnyBackend (IR.SourceConfigWith b)) ->
RootFieldMap
(SourceName, AB.AnyBackend (IR.SourceConfigWith (IR.QueryDBRoot Void IR.UnpreparedValue))) ->
RootFieldAlias ->
ExceptT QErr IO (SourceName, SubscriptionQueryPlan)
buildAction :: forall (b :: BackendType -> *).
(SourceName, AnyBackend (SourceConfigWith b))
-> RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> RootFieldAlias
-> ExceptT QErr IO (SourceName, SubscriptionQueryPlan)
buildAction (SourceName
sourceName, AnyBackend (SourceConfigWith b)
exists) RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
allFields RootFieldAlias
rootFieldName = do
SubscriptionQueryPlan
subscriptionPlan <- forall (c :: BackendType -> Constraint) (i :: BackendType -> *) r.
AllBackendsSatisfy c =>
AnyBackend i -> (forall (b :: BackendType). c b => i b -> r) -> r
AB.dispatchAnyBackend @EB.BackendExecute
AnyBackend (SourceConfigWith b)
exists
\(IR.SourceConfigWith SourceConfig b
sourceConfig Maybe QueryTagsConfig
queryTagsConfig b b
_ :: IR.SourceConfigWith db b) -> do
InsOrdHashMap RootFieldAlias (QueryDB b Void (UnpreparedValue b))
qdbs <- ((SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> ExceptT QErr IO (QueryDB b Void (UnpreparedValue b)))
-> RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> ExceptT
QErr
IO
(InsOrdHashMap RootFieldAlias (QueryDB b Void (UnpreparedValue b)))
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b)
-> InsOrdHashMap RootFieldAlias a
-> f (InsOrdHashMap RootFieldAlias b)
traverse (forall (b :: BackendType) (m1 :: * -> *).
(Backend b, MonadError QErr m1) =>
SourceName
-> (SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> m1 (QueryDB b Void (UnpreparedValue b))
checkField @b SourceName
sourceName) RootFieldMap
(SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
allFields
let subscriptionQueryTagsAttributes :: QueryTagsAttributes
subscriptionQueryTagsAttributes = QueryTags -> QueryTagsAttributes
encodeQueryTags (QueryTags -> QueryTagsAttributes)
-> QueryTags -> QueryTagsAttributes
forall a b. (a -> b) -> a -> b
$ LivequeryMetadata -> QueryTags
QTLiveQuery (LivequeryMetadata -> QueryTags) -> LivequeryMetadata -> QueryTags
forall a b. (a -> b) -> a -> b
$ RootFieldAlias -> ParameterizedQueryHash -> LivequeryMetadata
LivequeryMetadata RootFieldAlias
rootFieldName ParameterizedQueryHash
parameterizedQueryHash
let queryTagsComment :: QueryTagsComment
queryTagsComment = Tagged m QueryTagsComment -> QueryTagsComment
forall {k} (s :: k) b. Tagged s b -> b
Tagged.untag (Tagged m QueryTagsComment -> QueryTagsComment)
-> Tagged m QueryTagsComment -> QueryTagsComment
forall a b. (a -> b) -> a -> b
$ forall (m :: * -> *).
MonadQueryTags m =>
QueryTagsAttributes
-> Maybe QueryTagsConfig -> Tagged m QueryTagsComment
createQueryTags @m QueryTagsAttributes
subscriptionQueryTagsAttributes Maybe QueryTagsConfig
queryTagsConfig
AnyBackend MultiplexedSubscriptionQueryPlan
-> SubscriptionQueryPlan
SubscriptionQueryPlan
(AnyBackend MultiplexedSubscriptionQueryPlan
-> SubscriptionQueryPlan)
-> (SubscriptionQueryPlan b (MultiplexedQuery b)
-> AnyBackend MultiplexedSubscriptionQueryPlan)
-> SubscriptionQueryPlan b (MultiplexedQuery b)
-> SubscriptionQueryPlan
forall b c a. (b -> c) -> (a -> b) -> a -> c
. MultiplexedSubscriptionQueryPlan b
-> AnyBackend MultiplexedSubscriptionQueryPlan
forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
i b -> AnyBackend i
AB.mkAnyBackend
(MultiplexedSubscriptionQueryPlan b
-> AnyBackend MultiplexedSubscriptionQueryPlan)
-> (SubscriptionQueryPlan b (MultiplexedQuery b)
-> MultiplexedSubscriptionQueryPlan b)
-> SubscriptionQueryPlan b (MultiplexedQuery b)
-> AnyBackend MultiplexedSubscriptionQueryPlan
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SubscriptionQueryPlan b (MultiplexedQuery b)
-> MultiplexedSubscriptionQueryPlan b
forall (b :: BackendType).
SubscriptionQueryPlan b (MultiplexedQuery b)
-> MultiplexedSubscriptionQueryPlan b
MultiplexedSubscriptionQueryPlan
(SubscriptionQueryPlan b (MultiplexedQuery b)
-> SubscriptionQueryPlan)
-> ExceptT QErr IO (SubscriptionQueryPlan b (MultiplexedQuery b))
-> ExceptT QErr IO SubscriptionQueryPlan
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT
QueryTagsComment
(ExceptT QErr IO)
(SubscriptionQueryPlan b (MultiplexedQuery b))
-> QueryTagsComment
-> ExceptT QErr IO (SubscriptionQueryPlan b (MultiplexedQuery b))
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (UserInfo
-> SourceName
-> SourceConfig b
-> Maybe Name
-> InsOrdHashMap
RootFieldAlias (QueryDB b Void (UnpreparedValue b))
-> [Header]
-> Maybe Name
-> ReaderT
QueryTagsComment
(ExceptT QErr IO)
(SubscriptionQueryPlan b (MultiplexedQuery b))
forall (b :: BackendType) (m :: * -> *).
(BackendExecute b, MonadError QErr m, MonadIO m,
MonadBaseControl IO m, MonadReader QueryTagsComment m) =>
UserInfo
-> SourceName
-> SourceConfig b
-> Maybe Name
-> RootFieldMap (QueryDB b Void (UnpreparedValue b))
-> [Header]
-> Maybe Name
-> m (SubscriptionQueryPlan b (MultiplexedQuery b))
forall (m :: * -> *).
(MonadError QErr m, MonadIO m, MonadBaseControl IO m,
MonadReader QueryTagsComment m) =>
UserInfo
-> SourceName
-> SourceConfig b
-> Maybe Name
-> InsOrdHashMap
RootFieldAlias (QueryDB b Void (UnpreparedValue b))
-> [Header]
-> Maybe Name
-> m (SubscriptionQueryPlan b (MultiplexedQuery b))
EB.mkLiveQuerySubscriptionPlan UserInfo
userInfo SourceName
sourceName SourceConfig b
sourceConfig (RootFieldAlias -> Maybe Name
_rfaNamespace RootFieldAlias
rootFieldName) InsOrdHashMap RootFieldAlias (QueryDB b Void (UnpreparedValue b))
qdbs [Header]
reqHeaders Maybe Name
operationName) QueryTagsComment
queryTagsComment
(SourceName, SubscriptionQueryPlan)
-> ExceptT QErr IO (SourceName, SubscriptionQueryPlan)
forall a. a -> ExceptT QErr IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (SourceName
sourceName, SubscriptionQueryPlan
subscriptionPlan)
checkField ::
forall b m1.
(Backend b, MonadError QErr m1) =>
SourceName ->
(SourceName, AB.AnyBackend (IR.SourceConfigWith (IR.QueryDBRoot Void IR.UnpreparedValue))) ->
m1 (IR.QueryDB b Void (IR.UnpreparedValue b))
checkField :: forall (b :: BackendType) (m1 :: * -> *).
(Backend b, MonadError QErr m1) =>
SourceName
-> (SourceName,
AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue)))
-> m1 (QueryDB b Void (UnpreparedValue b))
checkField SourceName
sourceName (SourceName
src, AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))
exists)
| SourceName
sourceName SourceName -> SourceName -> Bool
forall a. Eq a => a -> a -> Bool
/= SourceName
src = Code -> Text -> m1 (QueryDB b Void (UnpreparedValue b))
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"all fields of a subscription must be from the same source"
| Bool
otherwise = case AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))
-> Maybe (SourceConfigWith (QueryDBRoot Void UnpreparedValue) b)
forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
AnyBackend i -> Maybe (i b)
AB.unpackAnyBackend AnyBackend (SourceConfigWith (QueryDBRoot Void UnpreparedValue))
exists of
Maybe (SourceConfigWith (QueryDBRoot Void UnpreparedValue) b)
Nothing -> Text -> m1 (QueryDB b Void (UnpreparedValue b))
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 Text
"internal error: two sources share the same name but are tied to different backends"
Just (IR.SourceConfigWith SourceConfig b
_ Maybe QueryTagsConfig
_ (IR.QDBR QueryDB b Void (UnpreparedValue b)
qdb)) -> QueryDB b Void (UnpreparedValue b)
-> m1 (QueryDB b Void (UnpreparedValue b))
forall a. a -> m1 a
forall (f :: * -> *) a. Applicative f => a -> f a
pure QueryDB b Void (UnpreparedValue b)
qdb
checkQueryInAllowlist ::
(MonadError QErr m) =>
Init.AllowListStatus ->
AllowlistMode ->
UserInfo ->
GQLReqParsed ->
SchemaCache ->
m ()
checkQueryInAllowlist :: forall (m :: * -> *).
MonadError QErr m =>
AllowListStatus
-> AllowlistMode -> UserInfo -> GQLReqParsed -> SchemaCache -> m ()
checkQueryInAllowlist AllowListStatus
allowListStatus AllowlistMode
allowlistMode UserInfo
userInfo GQLReqParsed
req SchemaCache
schemaCache =
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (AllowListStatus -> Bool
Init.isAllowListEnabled AllowListStatus
allowListStatus Bool -> Bool -> Bool
&& RoleName
role RoleName -> RoleName -> Bool
forall a. Eq a => a -> a -> Bool
/= RoleName
adminRoleName) do
let query :: ExecutableDocument Name
query = [ExecutableDefinition Name] -> ExecutableDocument Name
forall var. [ExecutableDefinition var] -> ExecutableDocument var
G.ExecutableDocument ([ExecutableDefinition Name] -> ExecutableDocument Name)
-> (GQLExecDoc -> [ExecutableDefinition Name])
-> GQLExecDoc
-> ExecutableDocument Name
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GQLExecDoc -> [ExecutableDefinition Name]
unGQLExecDoc (GQLExecDoc -> ExecutableDocument Name)
-> GQLExecDoc -> ExecutableDocument Name
forall a b. (a -> b) -> a -> b
$ GQLReqParsed -> GQLExecDoc
forall a. GQLReq a -> a
_grQuery GQLReqParsed
req
allowlist :: InlinedAllowlist
allowlist = SchemaCache -> InlinedAllowlist
scAllowlist SchemaCache
schemaCache
allowed :: Bool
allowed = InlinedAllowlist
-> AllowlistMode -> RoleName -> ExecutableDocument Name -> Bool
allowlistAllowsQuery InlinedAllowlist
allowlist AllowlistMode
allowlistMode RoleName
role ExecutableDocument Name
query
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
allowed
(m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ (QErr -> QErr) -> m () -> m ()
forall (m :: * -> *) a. QErrM m => (QErr -> QErr) -> m a -> m a
modifyQErr QErr -> QErr
modErr
(m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
ValidationFailed Text
"query is not allowed"
where
role :: RoleName
role = UserInfo -> RoleName
_uiRole UserInfo
userInfo
modErr :: QErr -> QErr
modErr QErr
e =
let msg :: Text
msg = Text
"query is not in any of the allowlists"
in QErr
e {qeInternal :: Maybe QErrExtra
qeInternal = QErrExtra -> Maybe QErrExtra
forall a. a -> Maybe a
Just (QErrExtra -> Maybe QErrExtra) -> QErrExtra -> Maybe QErrExtra
forall a b. (a -> b) -> a -> b
$ Value -> QErrExtra
ExtraInternal (Value -> QErrExtra) -> Value -> QErrExtra
forall a b. (a -> b) -> a -> b
$ [Pair] -> Value
J.object [Key
"message" Key -> Value -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Key -> v -> kv
forall v. ToJSON v => Key -> v -> Pair
J..= Text -> Value
J.String Text
msg]}
{-# INLINEABLE getResolvedExecPlan #-}
getResolvedExecPlan ::
forall m.
( MonadError QErr m,
MonadMetadataStorage m,
MonadIO m,
MonadBaseControl IO m,
Tracing.MonadTrace m,
EC.MonadGQLExecutionCheck m,
MonadQueryTags m,
ProvidesNetwork m
) =>
Env.Environment ->
L.Logger L.Hasura ->
PrometheusMetrics ->
UserInfo ->
SQLGenCtx ->
ReadOnlyMode ->
SchemaCache ->
ET.GraphQLQueryType ->
[HTTP.Header] ->
GQLReqUnparsed ->
SingleOperation ->
Maybe G.Name ->
RequestId ->
m (ParameterizedQueryHash, ResolvedExecutionPlan)
getResolvedExecPlan :: forall (m :: * -> *).
(MonadError QErr m, MonadMetadataStorage m, MonadIO m,
MonadBaseControl IO m, MonadTrace m, MonadGQLExecutionCheck m,
MonadQueryTags m, ProvidesNetwork m) =>
Environment
-> Logger Hasura
-> PrometheusMetrics
-> UserInfo
-> SQLGenCtx
-> ReadOnlyMode
-> SchemaCache
-> GraphQLQueryType
-> [Header]
-> GQLReqUnparsed
-> SingleOperation
-> Maybe Name
-> RequestId
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
getResolvedExecPlan
Environment
env
Logger Hasura
logger
PrometheusMetrics
prometheusMetrics
UserInfo
userInfo
SQLGenCtx
sqlGenCtx
ReadOnlyMode
readOnlyMode
SchemaCache
sc
GraphQLQueryType
queryType
[Header]
reqHeaders
GQLReqUnparsed
reqUnparsed
SingleOperation
queryParts
Maybe Name
maybeOperationName
RequestId
reqId = do
let gCtx :: GQLContext
gCtx = UserInfo -> SchemaCache -> GraphQLQueryType -> GQLContext
makeGQLContext UserInfo
userInfo SchemaCache
sc GraphQLQueryType
queryType
(ParameterizedQueryHash
parameterizedQueryHash, ResolvedExecutionPlan
resolvedExecPlan) <-
case SingleOperation
queryParts of
G.TypedOperationDefinition OperationType
G.OperationTypeQuery Maybe Name
_ [VariableDefinition]
varDefs [Directive Name]
directives SelectionSet NoFragments Name
inlinedSelSet -> Text
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
forall (m :: * -> *) a.
(MonadIO m, MonadTrace m) =>
Text -> m a -> m a
Tracing.newSpan Text
"Resolve query execution plan" (m (ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan))
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
forall a b. (a -> b) -> a -> b
$ do
(ExecutionPlan
executionPlan, [QueryRootField UnpreparedValue]
queryRootFields, DirectiveMap
dirMap, ParameterizedQueryHash
parameterizedQueryHash) <-
Environment
-> Logger Hasura
-> PrometheusMetrics
-> GQLContext
-> UserInfo
-> [Header]
-> [Directive Name]
-> SelectionSet NoFragments Name
-> [VariableDefinition]
-> GQLReqUnparsed
-> SetGraphqlIntrospectionOptions
-> RequestId
-> Maybe Name
-> m (ExecutionPlan, [QueryRootField UnpreparedValue],
DirectiveMap, ParameterizedQueryHash)
forall (m :: * -> *).
(MonadError QErr m, MonadTrace m, MonadIO m,
MonadGQLExecutionCheck m, MonadQueryTags m, ProvidesNetwork m) =>
Environment
-> Logger Hasura
-> PrometheusMetrics
-> GQLContext
-> UserInfo
-> [Header]
-> [Directive Name]
-> SelectionSet NoFragments Name
-> [VariableDefinition]
-> GQLReqUnparsed
-> SetGraphqlIntrospectionOptions
-> RequestId
-> Maybe Name
-> m (ExecutionPlan, [QueryRootField UnpreparedValue],
DirectiveMap, ParameterizedQueryHash)
EQ.convertQuerySelSet
Environment
env
Logger Hasura
logger
PrometheusMetrics
prometheusMetrics
GQLContext
gCtx
UserInfo
userInfo
[Header]
reqHeaders
[Directive Name]
directives
SelectionSet NoFragments Name
inlinedSelSet
[VariableDefinition]
varDefs
GQLReqUnparsed
reqUnparsed
(SchemaCache -> SetGraphqlIntrospectionOptions
scSetGraphqlIntrospectionOptions SchemaCache
sc)
RequestId
reqId
Maybe Name
maybeOperationName
TraceMetadata -> m ()
forall (m :: * -> *). MonadTrace m => TraceMetadata -> m ()
Tracing.attachMetadata [(Text
"graphql.operation.type", Text
"query"), (Text
"parameterized_query_hash", ByteString -> Text
bsToTxt (ByteString -> Text) -> ByteString -> Text
forall a b. (a -> b) -> a -> b
$ ParameterizedQueryHash -> ByteString
unParamQueryHash ParameterizedQueryHash
parameterizedQueryHash)]
(ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ParameterizedQueryHash
parameterizedQueryHash, ExecutionPlan
-> [QueryRootField UnpreparedValue]
-> DirectiveMap
-> ResolvedExecutionPlan
QueryExecutionPlan ExecutionPlan
executionPlan [QueryRootField UnpreparedValue]
queryRootFields DirectiveMap
dirMap)
G.TypedOperationDefinition OperationType
G.OperationTypeMutation Maybe Name
_ [VariableDefinition]
varDefs [Directive Name]
directives SelectionSet NoFragments Name
inlinedSelSet -> Text
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
forall (m :: * -> *) a.
(MonadIO m, MonadTrace m) =>
Text -> m a -> m a
Tracing.newSpan Text
"Resolve mutation execution plan" (m (ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan))
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
forall a b. (a -> b) -> a -> b
$ do
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ReadOnlyMode
readOnlyMode ReadOnlyMode -> ReadOnlyMode -> Bool
forall a. Eq a => a -> a -> Bool
== ReadOnlyMode
ReadOnlyModeEnabled)
(m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported Text
"Mutations are not allowed when read-only mode is enabled"
(ExecutionPlan
executionPlan, ParameterizedQueryHash
parameterizedQueryHash) <-
Environment
-> Logger Hasura
-> PrometheusMetrics
-> GQLContext
-> SQLGenCtx
-> UserInfo
-> [Header]
-> [Directive Name]
-> SelectionSet NoFragments Name
-> [VariableDefinition]
-> GQLReqUnparsed
-> SetGraphqlIntrospectionOptions
-> RequestId
-> Maybe Name
-> m (ExecutionPlan, ParameterizedQueryHash)
forall (m :: * -> *).
(MonadTrace m, MonadIO m, MonadError QErr m,
MonadMetadataStorage m, MonadGQLExecutionCheck m, MonadQueryTags m,
ProvidesNetwork m) =>
Environment
-> Logger Hasura
-> PrometheusMetrics
-> GQLContext
-> SQLGenCtx
-> UserInfo
-> [Header]
-> [Directive Name]
-> SelectionSet NoFragments Name
-> [VariableDefinition]
-> GQLReqUnparsed
-> SetGraphqlIntrospectionOptions
-> RequestId
-> Maybe Name
-> m (ExecutionPlan, ParameterizedQueryHash)
EM.convertMutationSelectionSet
Environment
env
Logger Hasura
logger
PrometheusMetrics
prometheusMetrics
GQLContext
gCtx
SQLGenCtx
sqlGenCtx
UserInfo
userInfo
[Header]
reqHeaders
[Directive Name]
directives
SelectionSet NoFragments Name
inlinedSelSet
[VariableDefinition]
varDefs
GQLReqUnparsed
reqUnparsed
(SchemaCache -> SetGraphqlIntrospectionOptions
scSetGraphqlIntrospectionOptions SchemaCache
sc)
RequestId
reqId
Maybe Name
maybeOperationName
TraceMetadata -> m ()
forall (m :: * -> *). MonadTrace m => TraceMetadata -> m ()
Tracing.attachMetadata [(Text
"graphql.operation.type", Text
"mutation")]
(ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ParameterizedQueryHash
parameterizedQueryHash, ExecutionPlan -> ResolvedExecutionPlan
MutationExecutionPlan ExecutionPlan
executionPlan)
G.TypedOperationDefinition OperationType
G.OperationTypeSubscription Maybe Name
_ [VariableDefinition]
varDefs [Directive Name]
directives SelectionSet NoFragments Name
inlinedSelSet -> Text
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
forall (m :: * -> *) a.
(MonadIO m, MonadTrace m) =>
Text -> m a -> m a
Tracing.newSpan Text
"Resolve subscription execution plan" (m (ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan))
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
forall a b. (a -> b) -> a -> b
$ do
([Directive Variable]
normalizedDirectives, SelectionSet NoFragments Variable
normalizedSelectionSet) <-
[VariableDefinition]
-> VariableValues
-> [Directive Name]
-> SelectionSet NoFragments Name
-> m ([Directive Variable], SelectionSet NoFragments Variable)
forall (m :: * -> *) (fragments :: * -> *).
(MonadError QErr m, Traversable fragments) =>
[VariableDefinition]
-> VariableValues
-> [Directive Name]
-> SelectionSet fragments Name
-> m ([Directive Variable], SelectionSet fragments Variable)
ER.resolveVariables
[VariableDefinition]
varDefs
(VariableValues -> Maybe VariableValues -> VariableValues
forall a. a -> Maybe a -> a
fromMaybe VariableValues
forall a. Monoid a => a
mempty (GQLReqUnparsed -> Maybe VariableValues
forall a. GQLReq a -> Maybe VariableValues
_grVariables GQLReqUnparsed
reqUnparsed))
[Directive Name]
directives
SelectionSet NoFragments Name
inlinedSelSet
ParserFn (RootFieldMap (QueryRootField UnpreparedValue))
subscriptionParser <- GQLContext
-> Maybe (ParserFn (RootFieldMap (QueryRootField UnpreparedValue)))
C.gqlSubscriptionParser GQLContext
gCtx Maybe (ParserFn (RootFieldMap (QueryRootField UnpreparedValue)))
-> m (ParserFn (RootFieldMap (QueryRootField UnpreparedValue)))
-> m (ParserFn (RootFieldMap (QueryRootField UnpreparedValue)))
forall (m :: * -> *) a. Applicative m => Maybe a -> m a -> m a
`onNothing` Code
-> Text
-> m (ParserFn (RootFieldMap (QueryRootField UnpreparedValue)))
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
ValidationFailed Text
"no subscriptions exist"
RootFieldMap (QueryRootField UnpreparedValue)
unpreparedAST <- Text
-> m (RootFieldMap (QueryRootField UnpreparedValue))
-> m (RootFieldMap (QueryRootField UnpreparedValue))
forall (m :: * -> *) a.
(MonadIO m, MonadTrace m) =>
Text -> m a -> m a
Tracing.newSpan Text
"Parse subscription IR" (m (RootFieldMap (QueryRootField UnpreparedValue))
-> m (RootFieldMap (QueryRootField UnpreparedValue)))
-> m (RootFieldMap (QueryRootField UnpreparedValue))
-> m (RootFieldMap (QueryRootField UnpreparedValue))
forall a b. (a -> b) -> a -> b
$ Either QErr (RootFieldMap (QueryRootField UnpreparedValue))
-> m (RootFieldMap (QueryRootField UnpreparedValue))
forall e (m :: * -> *) a. MonadError e m => Either e a -> m a
liftEither (Either QErr (RootFieldMap (QueryRootField UnpreparedValue))
-> m (RootFieldMap (QueryRootField UnpreparedValue)))
-> Either QErr (RootFieldMap (QueryRootField UnpreparedValue))
-> m (RootFieldMap (QueryRootField UnpreparedValue))
forall a b. (a -> b) -> a -> b
$ ParserFn (RootFieldMap (QueryRootField UnpreparedValue))
subscriptionParser SelectionSet NoFragments Variable
normalizedSelectionSet
let parameterizedQueryHash :: ParameterizedQueryHash
parameterizedQueryHash = SelectionSet NoFragments Variable -> ParameterizedQueryHash
calculateParameterizedQueryHash SelectionSet NoFragments Variable
normalizedSelectionSet
DirectiveMap
dirMap <-
Either ParseError DirectiveMap -> m DirectiveMap
forall (m :: * -> *) a.
MonadError QErr m =>
Either ParseError a -> m a
toQErr (Either ParseError DirectiveMap -> m DirectiveMap)
-> Either ParseError DirectiveMap -> m DirectiveMap
forall a b. (a -> b) -> a -> b
$ Parse DirectiveMap -> Either ParseError DirectiveMap
forall (m :: * -> *) a. MonadError ParseError m => Parse a -> m a
runParse ([Directive Any Parse]
-> DirectiveLocation -> [Directive Variable] -> Parse DirectiveMap
forall origin (m :: * -> *).
MonadParse m =>
[Directive origin m]
-> DirectiveLocation -> [Directive Variable] -> m DirectiveMap
parseDirectives [Directive Any Parse]
forall (m :: * -> *) origin. MonadParse m => [Directive origin m]
customDirectives (ExecutableDirectiveLocation -> DirectiveLocation
G.DLExecutable ExecutableDirectiveLocation
G.EDLSUBSCRIPTION) [Directive Variable]
normalizedDirectives)
Bool
allowMultipleRootFields <- DirectiveMap -> DirectiveKey () -> (Maybe () -> m Bool) -> m Bool
forall a (m :: * -> *) b.
DirectiveMap -> DirectiveKey a -> (Maybe a -> m b) -> m b
withDirective DirectiveMap
dirMap DirectiveKey ()
multipleRootFields ((Maybe () -> m Bool) -> m Bool) -> (Maybe () -> m Bool) -> m Bool
forall a b. (a -> b) -> a -> b
$ Bool -> m Bool
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Bool -> m Bool) -> (Maybe () -> Bool) -> Maybe () -> m Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Maybe () -> Bool
forall a. Maybe a -> Bool
isJust
case SelectionSet NoFragments Name
inlinedSelSet of
[] -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 Text
"empty selset for subscription"
[Selection NoFragments Name
_] -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()
SelectionSet NoFragments Name
_ ->
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Bool
allowMultipleRootFields Bool -> Bool -> Bool
&& RootFieldMap (QueryRootField UnpreparedValue) -> Bool
forall a. InsOrdHashMap RootFieldAlias a -> Bool
isSingleNamespace RootFieldMap (QueryRootField UnpreparedValue)
unpreparedAST)
(m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
ValidationFailed Text
"subscriptions must select one top level field"
(SubscriptionExecution, Maybe (Endo Value))
subscriptionPlan <- UserInfo
-> RootFieldMap (QueryRootField UnpreparedValue)
-> ParameterizedQueryHash
-> [Header]
-> Maybe Name
-> m (SubscriptionExecution, Maybe (Endo Value))
forall (m :: * -> *).
(MonadError QErr m, MonadQueryTags m, MonadIO m,
MonadBaseControl IO m) =>
UserInfo
-> RootFieldMap (QueryRootField UnpreparedValue)
-> ParameterizedQueryHash
-> [Header]
-> Maybe Name
-> m (SubscriptionExecution, Maybe (Endo Value))
buildSubscriptionPlan UserInfo
userInfo RootFieldMap (QueryRootField UnpreparedValue)
unpreparedAST ParameterizedQueryHash
parameterizedQueryHash [Header]
reqHeaders Maybe Name
maybeOperationName
TraceMetadata -> m ()
forall (m :: * -> *). MonadTrace m => TraceMetadata -> m ()
Tracing.attachMetadata [(Text
"graphql.operation.type", Text
"subscription")]
(ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (ParameterizedQueryHash
parameterizedQueryHash, (SubscriptionExecution, Maybe (Endo Value))
-> ResolvedExecutionPlan
SubscriptionExecutionPlan (SubscriptionExecution, Maybe (Endo Value))
subscriptionPlan)
(ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan))
-> (ParameterizedQueryHash, ResolvedExecutionPlan)
-> m (ParameterizedQueryHash, ResolvedExecutionPlan)
forall a b. (a -> b) -> a -> b
$ (ParameterizedQueryHash
parameterizedQueryHash, ResolvedExecutionPlan
resolvedExecPlan)
isSingleNamespace :: RootFieldMap a -> Bool
isSingleNamespace :: forall a. InsOrdHashMap RootFieldAlias a -> Bool
isSingleNamespace RootFieldMap a
fieldMap =
case [Maybe Name] -> [Maybe Name]
forall a. Ord a => [a] -> [a]
nubOrd (RootFieldAlias -> Maybe Name
_rfaNamespace (RootFieldAlias -> Maybe Name) -> [RootFieldAlias] -> [Maybe Name]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> RootFieldMap a -> [RootFieldAlias]
forall k v. InsOrdHashMap k v -> [k]
InsOrdHashMap.keys RootFieldMap a
fieldMap) of
[Maybe Name
_] -> Bool
True
[Maybe Name]
_ -> Bool
False