module Hasura.GraphQL.Execute.Backend
( BackendExecute (..),
DBStepInfo (..),
ActionResult (..),
withNoStatistics,
ExecutionPlan,
ExecutionStep (..),
ExplainPlan (..),
OnBaseMonad (..),
convertRemoteSourceRelationship,
)
where
import Control.Monad.Trans.Control (MonadBaseControl)
import Data.Aeson qualified as J
import Data.Aeson.Casing qualified as J
import Data.Aeson.Ordered qualified as JO
import Data.Environment qualified as Env
import Data.Kind (Type)
import Data.Text.Extended
import Data.Text.NonEmpty (mkNonEmptyTextUnsafe)
import Hasura.Base.Error
import Hasura.EncJSON
import Hasura.GraphQL.Execute.Action.Types (ActionExecutionPlan)
import Hasura.GraphQL.Execute.RemoteJoin.Types
import Hasura.GraphQL.Execute.Subscription.Plan
import Hasura.GraphQL.Namespace (RootFieldAlias, RootFieldMap)
import Hasura.GraphQL.Parser.Variable qualified as G
import Hasura.GraphQL.Transport.HTTP.Protocol qualified as GH
import Hasura.Logging qualified as L
import Hasura.Prelude
import Hasura.QueryTags
import Hasura.RQL.IR
import Hasura.RQL.Types.Action
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Column (ColumnType, fromCol)
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.Relationships.Local (Nullable (..))
import Hasura.RQL.Types.ResultCustomization
import Hasura.RQL.Types.Schema.Options qualified as Options
import Hasura.RemoteSchema.SchemaCache
import Hasura.SQL.AnyBackend qualified as AB
import Hasura.Session
import Hasura.Tracing (MonadTrace)
import Hasura.Tracing qualified as Tracing
import Language.GraphQL.Draft.Syntax qualified as G
import Network.HTTP.Client qualified as HTTP
import Network.HTTP.Types qualified as HTTP
class
( Backend b,
ToTxt (MultiplexedQuery b),
Show (ResolvedConnectionTemplate b),
Eq (ResolvedConnectionTemplate b),
Hashable (ResolvedConnectionTemplate b)
) =>
BackendExecute (b :: BackendType)
where
type PreparedQuery b :: Type
type MultiplexedQuery b :: Type
type ExecutionMonad b :: (Type -> Type) -> (Type -> Type)
mkDBQueryPlan ::
forall m.
( MonadError QErr m,
MonadQueryTags m,
MonadReader QueryTagsComment m
) =>
UserInfo ->
SourceName ->
SourceConfig b ->
QueryDB b Void (UnpreparedValue b) ->
[HTTP.Header] ->
Maybe G.Name ->
m (DBStepInfo b)
mkDBMutationPlan ::
forall m.
( MonadError QErr m,
MonadIO m,
MonadQueryTags m,
MonadReader QueryTagsComment m,
Tracing.MonadTrace m
) =>
Env.Environment ->
HTTP.Manager ->
L.Logger L.Hasura ->
UserInfo ->
Options.StringifyNumbers ->
SourceName ->
SourceConfig b ->
MutationDB b Void (UnpreparedValue b) ->
[HTTP.Header] ->
Maybe G.Name ->
Maybe (HashMap G.Name (G.Value G.Variable)) ->
m (DBStepInfo b)
mkLiveQuerySubscriptionPlan ::
forall m.
( MonadError QErr m,
MonadIO m,
MonadBaseControl IO m,
MonadReader QueryTagsComment m
) =>
UserInfo ->
SourceName ->
SourceConfig b ->
Maybe G.Name ->
RootFieldMap (QueryDB b Void (UnpreparedValue b)) ->
[HTTP.Header] ->
Maybe G.Name ->
m (SubscriptionQueryPlan b (MultiplexedQuery b))
mkDBStreamingSubscriptionPlan ::
forall m.
( MonadError QErr m,
MonadIO m,
MonadBaseControl IO m,
MonadReader QueryTagsComment m
) =>
UserInfo ->
SourceName ->
SourceConfig b ->
(RootFieldAlias, (QueryDB b Void (UnpreparedValue b))) ->
[HTTP.Header] ->
Maybe G.Name ->
m (SubscriptionQueryPlan b (MultiplexedQuery b))
mkDBQueryExplain ::
forall m.
( MonadError QErr m
) =>
RootFieldAlias ->
UserInfo ->
SourceName ->
SourceConfig b ->
QueryDB b Void (UnpreparedValue b) ->
[HTTP.Header] ->
Maybe G.Name ->
m (AB.AnyBackend (DBStepInfo))
mkSubscriptionExplain ::
( MonadError QErr m,
MonadIO m,
MonadBaseControl IO m
) =>
SubscriptionQueryPlan b (MultiplexedQuery b) ->
m SubscriptionQueryPlanExplanation
mkDBRemoteRelationshipPlan ::
forall m.
( MonadError QErr m,
MonadQueryTags m
) =>
UserInfo ->
SourceName ->
SourceConfig b ->
NonEmpty J.Object ->
HashMap FieldName (Column b, ScalarType b) ->
FieldName ->
(FieldName, SourceRelationshipSelection b Void UnpreparedValue) ->
[HTTP.Header] ->
Maybe G.Name ->
Options.StringifyNumbers ->
m (DBStepInfo b)
convertRemoteSourceRelationship ::
forall b.
(Backend b) =>
HashMap (Column b) (Column b) ->
SelectFromG b (UnpreparedValue b) ->
Column b ->
ColumnType b ->
(FieldName, SourceRelationshipSelection b Void UnpreparedValue) ->
Options.StringifyNumbers ->
QueryDB b Void (UnpreparedValue b)
convertRemoteSourceRelationship :: forall (b :: BackendType).
Backend b =>
HashMap (Column b) (Column b)
-> SelectFromG b (UnpreparedValue b)
-> Column b
-> ColumnType b
-> (FieldName, SourceRelationshipSelection b Void UnpreparedValue)
-> StringifyNumbers
-> QueryDB b Void (UnpreparedValue b)
convertRemoteSourceRelationship
HashMap (Column b) (Column b)
columnMapping
SelectFromG b (UnpreparedValue b)
selectFrom
Column b
argumentIdColumn
ColumnType b
argumentIdColumnType
(FieldName
relationshipName, SourceRelationshipSelection b Void UnpreparedValue
relationship)
StringifyNumbers
stringifyNumbers =
AnnSimpleSelectG b Void (UnpreparedValue b)
-> QueryDB b Void (UnpreparedValue b)
forall (b :: BackendType) r v.
AnnSimpleSelectG b r v -> QueryDB b r v
QDBMultipleRows AnnSimpleSelectG b Void (UnpreparedValue b)
simpleSelect
where
relName :: RelName
relName = NonEmptyText -> RelName
RelName (NonEmptyText -> RelName) -> NonEmptyText -> RelName
forall a b. (a -> b) -> a -> b
$ Text -> NonEmptyText
mkNonEmptyTextUnsafe (Text -> NonEmptyText) -> Text -> NonEmptyText
forall a b. (a -> b) -> a -> b
$ FieldName -> Text
getFieldNameTxt FieldName
relationshipName
relationshipField :: AnnFieldG b Void (UnpreparedValue b)
relationshipField = case SourceRelationshipSelection b Void UnpreparedValue
relationship of
SourceRelationshipObject AnnObjectSelectG b Void (UnpreparedValue b)
s ->
ObjectRelationSelectG b Void (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b)
forall (b :: BackendType) r v.
ObjectRelationSelectG b r v -> AnnFieldG b r v
AFObjectRelation (ObjectRelationSelectG b Void (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b))
-> ObjectRelationSelectG b Void (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b)
forall a b. (a -> b) -> a -> b
$ RelName
-> HashMap (Column b) (Column b)
-> Nullable
-> AnnObjectSelectG b Void (UnpreparedValue b)
-> ObjectRelationSelectG b Void (UnpreparedValue b)
forall (b :: BackendType) a.
RelName
-> HashMap (Column b) (Column b)
-> Nullable
-> a
-> AnnRelationSelectG b a
AnnRelationSelectG RelName
relName HashMap (Column b) (Column b)
columnMapping Nullable
Nullable AnnObjectSelectG b Void (UnpreparedValue b)
s
SourceRelationshipArray AnnSimpleSelectG b Void (UnpreparedValue b)
s ->
ArraySelectG b Void (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b)
forall (b :: BackendType) r v.
ArraySelectG b r v -> AnnFieldG b r v
AFArrayRelation (ArraySelectG b Void (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b))
-> ArraySelectG b Void (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b)
forall a b. (a -> b) -> a -> b
$ ArrayRelationSelectG b Void (UnpreparedValue b)
-> ArraySelectG b Void (UnpreparedValue b)
forall (b :: BackendType) r v.
ArrayRelationSelectG b r v -> ArraySelectG b r v
ASSimple (ArrayRelationSelectG b Void (UnpreparedValue b)
-> ArraySelectG b Void (UnpreparedValue b))
-> ArrayRelationSelectG b Void (UnpreparedValue b)
-> ArraySelectG b Void (UnpreparedValue b)
forall a b. (a -> b) -> a -> b
$ RelName
-> HashMap (Column b) (Column b)
-> Nullable
-> AnnSimpleSelectG b Void (UnpreparedValue b)
-> ArrayRelationSelectG b Void (UnpreparedValue b)
forall (b :: BackendType) a.
RelName
-> HashMap (Column b) (Column b)
-> Nullable
-> a
-> AnnRelationSelectG b a
AnnRelationSelectG RelName
relName HashMap (Column b) (Column b)
columnMapping Nullable
Nullable AnnSimpleSelectG b Void (UnpreparedValue b)
s
SourceRelationshipArrayAggregate AnnAggregateSelectG b Void (UnpreparedValue b)
s ->
ArraySelectG b Void (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b)
forall (b :: BackendType) r v.
ArraySelectG b r v -> AnnFieldG b r v
AFArrayRelation (ArraySelectG b Void (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b))
-> ArraySelectG b Void (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b)
forall a b. (a -> b) -> a -> b
$ ArrayAggregateSelectG b Void (UnpreparedValue b)
-> ArraySelectG b Void (UnpreparedValue b)
forall (b :: BackendType) r v.
ArrayAggregateSelectG b r v -> ArraySelectG b r v
ASAggregate (ArrayAggregateSelectG b Void (UnpreparedValue b)
-> ArraySelectG b Void (UnpreparedValue b))
-> ArrayAggregateSelectG b Void (UnpreparedValue b)
-> ArraySelectG b Void (UnpreparedValue b)
forall a b. (a -> b) -> a -> b
$ RelName
-> HashMap (Column b) (Column b)
-> Nullable
-> AnnAggregateSelectG b Void (UnpreparedValue b)
-> ArrayAggregateSelectG b Void (UnpreparedValue b)
forall (b :: BackendType) a.
RelName
-> HashMap (Column b) (Column b)
-> Nullable
-> a
-> AnnRelationSelectG b a
AnnRelationSelectG RelName
relName HashMap (Column b) (Column b)
columnMapping Nullable
Nullable AnnAggregateSelectG b Void (UnpreparedValue b)
s
argumentIdField :: (FieldName, AnnFieldG b Void (UnpreparedValue b))
argumentIdField =
( forall (b :: BackendType). Backend b => Column b -> FieldName
fromCol @b Column b
argumentIdColumn,
AnnColumnField b (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b)
forall (b :: BackendType) r v.
AnnColumnField b v -> AnnFieldG b r v
AFColumn
(AnnColumnField b (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b))
-> AnnColumnField b (UnpreparedValue b)
-> AnnFieldG b Void (UnpreparedValue b)
forall a b. (a -> b) -> a -> b
$ AnnColumnField
{ $sel:_acfColumn:AnnColumnField :: Column b
_acfColumn = Column b
argumentIdColumn,
$sel:_acfType:AnnColumnField :: ColumnType b
_acfType = ColumnType b
argumentIdColumnType,
$sel:_acfAsText:AnnColumnField :: Bool
_acfAsText = Bool
False,
$sel:_acfArguments:AnnColumnField :: Maybe (ScalarSelectionArguments b)
_acfArguments = Maybe (ScalarSelectionArguments b)
forall a. Maybe a
Nothing,
$sel:_acfRedactionExpression:AnnColumnField :: AnnRedactionExp b (UnpreparedValue b)
_acfRedactionExpression = AnnRedactionExp b (UnpreparedValue b)
forall (b :: BackendType) v. AnnRedactionExp b v
NoRedaction
}
)
simpleSelect :: AnnSimpleSelectG b Void (UnpreparedValue b)
simpleSelect =
AnnSelectG
{ $sel:_asnFields:AnnSelectG :: Fields (AnnFieldG b Void (UnpreparedValue b))
_asnFields = [(FieldName, AnnFieldG b Void (UnpreparedValue b))
argumentIdField, (FieldName
relationshipName, AnnFieldG b Void (UnpreparedValue b)
relationshipField)],
$sel:_asnFrom:AnnSelectG :: SelectFromG b (UnpreparedValue b)
_asnFrom = SelectFromG b (UnpreparedValue b)
selectFrom,
$sel:_asnPerm:AnnSelectG :: TablePermG b (UnpreparedValue b)
_asnPerm = AnnBoolExp b (UnpreparedValue b)
-> Maybe Int -> TablePermG b (UnpreparedValue b)
forall (b :: BackendType) v.
AnnBoolExp b v -> Maybe Int -> TablePermG b v
TablePerm AnnBoolExp b (UnpreparedValue b)
forall (backend :: BackendType) scalar. AnnBoolExp backend scalar
annBoolExpTrue Maybe Int
forall a. Maybe a
Nothing,
$sel:_asnArgs:AnnSelectG :: SelectArgsG b (UnpreparedValue b)
_asnArgs = SelectArgsG b (UnpreparedValue b)
forall (backend :: BackendType) v. SelectArgsG backend v
noSelectArgs,
$sel:_asnStrfyNum:AnnSelectG :: StringifyNumbers
_asnStrfyNum = StringifyNumbers
stringifyNumbers,
$sel:_asnNamingConvention:AnnSelectG :: Maybe NamingCase
_asnNamingConvention = Maybe NamingCase
forall a. Maybe a
Nothing
}
data DBStepInfo b = DBStepInfo
{ forall (b :: BackendType). DBStepInfo b -> SourceName
dbsiSourceName :: SourceName,
forall (b :: BackendType). DBStepInfo b -> SourceConfig b
dbsiSourceConfig :: SourceConfig b,
forall (b :: BackendType). DBStepInfo b -> Maybe (PreparedQuery b)
dbsiPreparedQuery :: Maybe (PreparedQuery b),
forall (b :: BackendType).
DBStepInfo b -> OnBaseMonad (ExecutionMonad b) (ActionResult b)
dbsiAction :: OnBaseMonad (ExecutionMonad b) (ActionResult b),
forall (b :: BackendType).
DBStepInfo b -> ResolvedConnectionTemplate b
dbsiResolvedConnectionTemplate :: ResolvedConnectionTemplate b
}
data ActionResult b = ActionResult
{ forall (b :: BackendType).
ActionResult b -> Maybe (ExecutionStatistics b)
arStatistics :: Maybe (ExecutionStatistics b),
forall (b :: BackendType). ActionResult b -> EncJSON
arResult :: EncJSON
}
withNoStatistics :: EncJSON -> ActionResult b
withNoStatistics :: forall (b :: BackendType). EncJSON -> ActionResult b
withNoStatistics EncJSON
arResult = ActionResult {arStatistics :: Maybe (ExecutionStatistics b)
arStatistics = Maybe (ExecutionStatistics b)
forall a. Maybe a
Nothing, EncJSON
arResult :: EncJSON
arResult :: EncJSON
arResult}
newtype OnBaseMonad t a = OnBaseMonad
{ forall (t :: (* -> *) -> * -> *) a.
OnBaseMonad t a
-> forall (m :: * -> *).
(Functor (t m), MonadIO m, MonadBaseControl IO m, MonadTrace m,
MonadError QErr m) =>
t m a
runOnBaseMonad :: forall m. (Functor (t m), MonadIO m, MonadBaseControl IO m, MonadTrace m, MonadError QErr m) => t m a
}
instance Functor (OnBaseMonad t) where
fmap :: forall a b. (a -> b) -> OnBaseMonad t a -> OnBaseMonad t b
fmap a -> b
f (OnBaseMonad forall (m :: * -> *).
(Functor (t m), MonadIO m, MonadBaseControl IO m, MonadTrace m,
MonadError QErr m) =>
t m a
xs) = (forall (m :: * -> *).
(Functor (t m), MonadIO m, MonadBaseControl IO m, MonadTrace m,
MonadError QErr m) =>
t m b)
-> OnBaseMonad t b
forall (t :: (* -> *) -> * -> *) a.
(forall (m :: * -> *).
(Functor (t m), MonadIO m, MonadBaseControl IO m, MonadTrace m,
MonadError QErr m) =>
t m a)
-> OnBaseMonad t a
OnBaseMonad ((a -> b) -> t m a -> t m b
forall a b. (a -> b) -> t m a -> t m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f t m a
forall (m :: * -> *).
(Functor (t m), MonadIO m, MonadBaseControl IO m, MonadTrace m,
MonadError QErr m) =>
t m a
xs)
data ExplainPlan = ExplainPlan
{ ExplainPlan -> RootFieldAlias
_fpField :: !RootFieldAlias,
ExplainPlan -> Maybe Text
_fpSql :: !(Maybe Text),
ExplainPlan -> Maybe [Text]
_fpPlan :: !(Maybe [Text])
}
deriving (Int -> ExplainPlan -> ShowS
[ExplainPlan] -> ShowS
ExplainPlan -> String
(Int -> ExplainPlan -> ShowS)
-> (ExplainPlan -> String)
-> ([ExplainPlan] -> ShowS)
-> Show ExplainPlan
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ExplainPlan -> ShowS
showsPrec :: Int -> ExplainPlan -> ShowS
$cshow :: ExplainPlan -> String
show :: ExplainPlan -> String
$cshowList :: [ExplainPlan] -> ShowS
showList :: [ExplainPlan] -> ShowS
Show, ExplainPlan -> ExplainPlan -> Bool
(ExplainPlan -> ExplainPlan -> Bool)
-> (ExplainPlan -> ExplainPlan -> Bool) -> Eq ExplainPlan
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ExplainPlan -> ExplainPlan -> Bool
== :: ExplainPlan -> ExplainPlan -> Bool
$c/= :: ExplainPlan -> ExplainPlan -> Bool
/= :: ExplainPlan -> ExplainPlan -> Bool
Eq, (forall x. ExplainPlan -> Rep ExplainPlan x)
-> (forall x. Rep ExplainPlan x -> ExplainPlan)
-> Generic ExplainPlan
forall x. Rep ExplainPlan x -> ExplainPlan
forall x. ExplainPlan -> Rep ExplainPlan x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ExplainPlan -> Rep ExplainPlan x
from :: forall x. ExplainPlan -> Rep ExplainPlan x
$cto :: forall x. Rep ExplainPlan x -> ExplainPlan
to :: forall x. Rep ExplainPlan x -> ExplainPlan
Generic)
instance J.ToJSON ExplainPlan where
toJSON :: ExplainPlan -> Value
toJSON = Options -> ExplainPlan -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
J.genericToJSON (Options -> ExplainPlan -> Value)
-> Options -> ExplainPlan -> Value
forall a b. (a -> b) -> a -> b
$ ShowS -> Options
J.aesonPrefix ShowS
J.camelCase
data ExecutionStep where
ExecStepDB ::
HTTP.ResponseHeaders ->
AB.AnyBackend DBStepInfo ->
Maybe RemoteJoins ->
ExecutionStep
ExecStepAction ::
ActionExecutionPlan ->
ActionsInfo ->
Maybe RemoteJoins ->
ExecutionStep
ExecStepRemote ::
!RemoteSchemaInfo ->
!ResultCustomizer ->
!GH.GQLReqOutgoing ->
Maybe RemoteJoins ->
ExecutionStep
ExecStepRaw ::
JO.Value ->
ExecutionStep
ExecStepMulti ::
[ExecutionStep] ->
ExecutionStep
type ExecutionPlan = RootFieldMap ExecutionStep