mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-17 20:41:49 +03:00
01f56735ac
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4620 GitOrigin-RevId: f732fff4f3f2449ebc97f76522ee6ad11bcfbc68
164 lines
5.8 KiB
Haskell
164 lines
5.8 KiB
Haskell
module Hasura.Backends.DataConnector.IR.Query
|
|
( Query (..),
|
|
Field (..),
|
|
Cardinality (..),
|
|
ColumnContents (..),
|
|
RelationshipContents (..),
|
|
RelType (..),
|
|
PrimaryKey (..),
|
|
ForeignKey (..),
|
|
)
|
|
where
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
import Autodocodec.Extended (ValueWrapper (ValueWrapper))
|
|
import Data.Aeson (ToJSON, ToJSONKey)
|
|
import Data.Aeson qualified as J
|
|
import Hasura.Backends.DataConnector.API qualified as API
|
|
import Hasura.Backends.DataConnector.IR.Column qualified as IR.C
|
|
import Hasura.Backends.DataConnector.IR.Expression qualified as IR.E
|
|
import Hasura.Backends.DataConnector.IR.OrderBy qualified as IR.O
|
|
import Hasura.Backends.DataConnector.IR.Table qualified as IR.T
|
|
import Hasura.Prelude
|
|
import Witch qualified
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | An abstract request to retrieve structured data from some source.
|
|
--
|
|
-- NOTE: The 'ToJSON' instance is only intended for logging purposes.
|
|
data Query = Query
|
|
{ -- NOTE: We should clarify what the 'Text' key is supposed to indicate.
|
|
fields :: HashMap Text Field,
|
|
-- | Reference to the table these fields are in.
|
|
from :: IR.T.Name,
|
|
-- | Optionally limit to N results.
|
|
limit :: Maybe Int,
|
|
-- | Optionally offset from the Nth result.
|
|
offset :: Maybe Int,
|
|
-- | Optionally constrain the results to satisfy some predicate.
|
|
where_ :: Maybe IR.E.Expression,
|
|
-- | Optionally order the results by the value of one or more fields.
|
|
orderBy :: [IR.O.OrderBy],
|
|
-- | The cardinality of response we expect from the Agent's response.
|
|
cardinality :: Cardinality
|
|
}
|
|
deriving stock (Data, Eq, Generic, Ord, Show)
|
|
|
|
instance ToJSON Query where
|
|
toJSON = J.genericToJSON J.defaultOptions
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | This data structure keeps track of what cardinality of response we should
|
|
-- send back to the client for a given query, which may be different from what
|
|
-- we receive from the backend (which is always possibly-many records).
|
|
data Cardinality
|
|
= Many
|
|
| OneOrZero
|
|
deriving stock (Data, Eq, Generic, Ord, Show)
|
|
|
|
instance ToJSON Cardinality where
|
|
toJSON = J.genericToJSON J.defaultOptions
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | The specific fields that are targeted by a 'Query'.
|
|
--
|
|
-- A field conceptually falls under one of the two following categories:
|
|
-- 1. a "column" within the data store that the query is being issued against
|
|
-- 2. a "relationship", which indicates that the field is the result of
|
|
-- another query that must be executed on its own
|
|
-- 3. a "literal", which represents a piece of text, such as a
|
|
-- '__typename' field, which will appear in the final output and is
|
|
-- provided by HGE and not the Agent.
|
|
-- NOTE: The 'ToJSON' instance is only intended for logging purposes.
|
|
data Field
|
|
= Column ColumnContents
|
|
| Relationship RelationshipContents
|
|
| Literal Text
|
|
deriving stock (Data, Eq, Generic, Ord, Show)
|
|
|
|
instance ToJSON Field where
|
|
toJSON = J.genericToJSON J.defaultOptions
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | TODO
|
|
--
|
|
-- NOTE: The 'ToJSON' instance is only intended for logging purposes.
|
|
newtype ColumnContents = ColumnContents
|
|
{ column :: IR.C.Name
|
|
}
|
|
deriving stock (Data, Eq, Generic, Ord, Show)
|
|
|
|
instance ToJSON ColumnContents where
|
|
toJSON = J.genericToJSON J.defaultOptions
|
|
|
|
instance Witch.From ColumnContents API.Field where
|
|
from (ColumnContents name) = API.ColumnField $ ValueWrapper $ Witch.from name
|
|
|
|
-- | A relationship consists of the following components:
|
|
-- - a sub-query, from the perspective that a relationship field will occur
|
|
-- within a broader 'Query'
|
|
-- - a join condition relating the data returned by the sub-query with that
|
|
-- of the broader 'Query'
|
|
--
|
|
-- cf. https://en.wikipedia.org/wiki/Join_(SQL)
|
|
-- https://www.postgresql.org/docs/13/tutorial-join.html
|
|
-- https://www.postgresql.org/docs/13/queries-table-expressions.html#QUERIES-FROM
|
|
--
|
|
-- NOTE: The 'ToJSON' instance is only intended for logging purposes.
|
|
data RelationshipContents = RelationshipContents
|
|
{ joinCondition :: HashMap PrimaryKey ForeignKey,
|
|
relationType :: RelType,
|
|
query :: Query
|
|
}
|
|
deriving stock (Eq, Ord, Show, Generic, Data)
|
|
|
|
instance ToJSON RelationshipContents where
|
|
toJSON = J.genericToJSON J.defaultOptions
|
|
|
|
-- | Relationships can either be Object (One-To-One) or Array (One-To-Many) type.
|
|
data RelType = ObjectRelationship | ArrayRelationship
|
|
deriving stock (Eq, Ord, Show, Generic, Data)
|
|
|
|
instance ToJSON RelType where
|
|
toJSON = J.genericToJSON J.defaultOptions
|
|
|
|
instance Witch.From RelType API.RelType where
|
|
from = \case
|
|
ObjectRelationship -> API.ObjectRelationship
|
|
ArrayRelationship -> API.ArrayRelationship
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | TODO
|
|
--
|
|
-- NOTE: The 'ToJSON' instance is only intended for logging purposes.
|
|
newtype PrimaryKey = PrimaryKey IR.C.Name
|
|
deriving stock (Data, Generic)
|
|
deriving newtype (Eq, Hashable, Ord, Show, ToJSON, ToJSONKey)
|
|
|
|
instance Witch.From API.PrimaryKey PrimaryKey where
|
|
from (API.PrimaryKey key) = PrimaryKey (Witch.from key)
|
|
|
|
instance Witch.From PrimaryKey API.PrimaryKey where
|
|
from (PrimaryKey key) = API.PrimaryKey (Witch.from key)
|
|
|
|
--------------------------------------------------------------------------------
|
|
|
|
-- | TODO
|
|
--
|
|
-- NOTE: The 'ToJSON' instance is only intended for logging purposes.
|
|
newtype ForeignKey = ForeignKey IR.C.Name
|
|
deriving stock (Data, Generic)
|
|
deriving newtype (Eq, Hashable, Ord, Show, ToJSON, ToJSONKey)
|
|
|
|
instance Witch.From API.ForeignKey ForeignKey where
|
|
from (API.ForeignKey key) = ForeignKey (Witch.from key)
|
|
|
|
instance Witch.From ForeignKey API.ForeignKey where
|
|
from (ForeignKey key) = API.ForeignKey (Witch.from key)
|