2020-12-28 15:56:00 +03:00
|
|
|
{-# LANGUAGE AllowAmbiguousTypes #-}
|
2020-12-01 18:50:18 +03:00
|
|
|
|
|
|
|
module Hasura.GraphQL.Schema.Backend where
|
|
|
|
|
|
|
|
import Hasura.Prelude
|
|
|
|
|
|
|
|
import Data.Aeson
|
2020-12-28 15:56:00 +03:00
|
|
|
import Data.Has
|
2020-12-01 18:50:18 +03:00
|
|
|
|
2020-12-28 15:56:00 +03:00
|
|
|
import qualified Hasura.RQL.IR.Select as IR
|
2021-01-08 22:45:33 +03:00
|
|
|
import qualified Hasura.RQL.IR.Update as IR
|
2020-12-01 18:50:18 +03:00
|
|
|
|
2020-12-28 15:56:00 +03:00
|
|
|
import Hasura.GraphQL.Parser (Definition, EnumValueInfo, FieldParser,
|
|
|
|
InputFieldsParser, Kind (..), Opaque, Parser,
|
|
|
|
UnpreparedValue (..))
|
2020-12-01 18:50:18 +03:00
|
|
|
import Hasura.GraphQL.Parser.Class
|
|
|
|
import Hasura.GraphQL.Schema.Common
|
2020-12-28 15:56:00 +03:00
|
|
|
import Hasura.RQL.Types hiding (EnumValueInfo)
|
|
|
|
import Language.GraphQL.Draft.Syntax (Name, Nullability)
|
2020-12-01 18:50:18 +03:00
|
|
|
|
|
|
|
|
|
|
|
class Backend b => BackendSchema (b :: BackendType) where
|
|
|
|
columnParser
|
|
|
|
:: (MonadSchema n m, MonadError QErr m)
|
|
|
|
=> ColumnType b
|
|
|
|
-> Nullability
|
|
|
|
-> m (Parser 'Both n (Opaque (ColumnValue b)))
|
|
|
|
-- | The "path" argument for json column fields
|
|
|
|
jsonPathArg
|
|
|
|
:: MonadParse n
|
|
|
|
=> ColumnType b
|
|
|
|
-> InputFieldsParser n (Maybe (IR.ColumnOp b))
|
|
|
|
-- | Helper function to get the table GraphQL name. A table may have an
|
|
|
|
-- identifier configured with it. When the identifier exists, the GraphQL nodes
|
|
|
|
-- that are generated according to the identifier. For example: Let's say,
|
|
|
|
-- we have a table called `users address`, the name of the table is not GraphQL
|
|
|
|
-- compliant so we configure the table with a GraphQL compliant name,
|
|
|
|
-- say `users_address`
|
|
|
|
-- The generated top-level nodes of this table will be like `users_address`,
|
|
|
|
-- `insert_users_address` etc
|
|
|
|
getTableGQLName
|
|
|
|
:: MonadTableInfo b r m
|
|
|
|
=> TableName b
|
|
|
|
-> m Name
|
|
|
|
orderByOperators
|
|
|
|
:: NonEmpty (Definition EnumValueInfo, (BasicOrderType b, NullsOrderType b))
|
|
|
|
comparisonExps
|
|
|
|
:: (MonadSchema n m, MonadError QErr m)
|
|
|
|
=> ColumnType b
|
|
|
|
-> m (Parser 'Input n [ComparisonExp b])
|
2021-01-08 22:45:33 +03:00
|
|
|
updateOperators
|
|
|
|
:: (MonadSchema n m, MonadTableInfo b r m)
|
|
|
|
=> TableName b
|
|
|
|
-> UpdPermInfo b
|
|
|
|
-> m (Maybe (InputFieldsParser n [(Column b, IR.UpdOpExpG (UnpreparedValue b))]))
|
2020-12-01 18:50:18 +03:00
|
|
|
parseScalarValue
|
|
|
|
:: (MonadError QErr m)
|
|
|
|
=> ColumnType b
|
|
|
|
-> Value
|
2020-12-03 15:21:27 +03:00
|
|
|
-> m (ScalarValue b)
|
2020-12-01 18:50:18 +03:00
|
|
|
-- TODO: THIS IS A TEMPORARY FIX
|
|
|
|
-- while offset is exposed in the schema as a GraphQL Int, which
|
|
|
|
-- is a bounded Int32, previous versions of the code used to also
|
|
|
|
-- silently accept a string as an input for the offset as a way to
|
|
|
|
-- support int64 values (postgres bigint)
|
|
|
|
-- a much better way of supporting this would be to expose the
|
|
|
|
-- offset in the code as a postgres bigint, but for now, to avoid
|
|
|
|
-- a breaking change, we are defining a custom parser that also
|
|
|
|
-- accepts a string
|
|
|
|
offsetParser :: MonadParse n => Parser 'Both n (SQLExpression b)
|
|
|
|
mkCountType :: Maybe Bool -> Maybe [Column b] -> CountType b
|
|
|
|
aggregateOrderByCountType :: ScalarType b
|
|
|
|
-- | Computed field parser
|
|
|
|
computedField
|
2021-01-19 23:56:53 +03:00
|
|
|
:: ( BackendSchema b
|
|
|
|
, MonadSchema n m
|
|
|
|
, MonadTableInfo b r m
|
|
|
|
, MonadRole r m
|
|
|
|
, Has QueryContext r
|
|
|
|
)
|
2020-12-01 18:50:18 +03:00
|
|
|
=> ComputedFieldInfo b
|
|
|
|
-> SelPermInfo b
|
|
|
|
-> m (Maybe (FieldParser n (AnnotatedField b)))
|
|
|
|
-- | The 'node' root field of a Relay request.
|
|
|
|
node
|
|
|
|
:: ( BackendSchema b
|
|
|
|
, MonadSchema n m
|
|
|
|
, MonadTableInfo b r m
|
|
|
|
, MonadRole r m
|
|
|
|
, Has QueryContext r
|
|
|
|
)
|
2020-12-28 15:56:00 +03:00
|
|
|
=> m (Parser 'Output n (HashMap (TableName b) (SourceName, SourceConfig b, SelPermInfo b, PrimaryKeyColumns b, AnnotatedFields b)))
|
2021-01-19 23:56:53 +03:00
|
|
|
remoteRelationshipField
|
|
|
|
:: ( BackendSchema b
|
|
|
|
, MonadSchema n m
|
|
|
|
, MonadRole r m
|
|
|
|
, MonadError QErr m
|
|
|
|
, Has QueryContext r
|
|
|
|
)
|
|
|
|
=> RemoteFieldInfo b
|
|
|
|
-> m (Maybe [FieldParser n (AnnotatedField b)])
|
2020-12-01 18:50:18 +03:00
|
|
|
|
|
|
|
type ComparisonExp b = OpExpG b (UnpreparedValue b)
|