mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
Implement Schema Parsers for Native Query Interface
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/7574 GitOrigin-RevId: 0cb4638a7dd79abf6ccb05092c0c663c84675bbd
This commit is contained in:
parent
094b5e6db2
commit
cd5186be90
@ -713,6 +713,10 @@ library
|
||||
, Hasura.Incremental.Internal.Cache
|
||||
, Hasura.Incremental.Internal.Dependency
|
||||
, Hasura.Incremental.Internal.Rule
|
||||
, Hasura.NativeQuery.IR
|
||||
, Hasura.NativeQuery.Metadata
|
||||
, Hasura.NativeQuery.Schema
|
||||
, Hasura.NativeQuery.Types
|
||||
, Hasura.Server.Auth.WebHook
|
||||
, Hasura.Server.Middleware
|
||||
, Hasura.Server.Cors
|
||||
@ -848,13 +852,13 @@ library
|
||||
, Hasura.RQL.IR.Delete
|
||||
, Hasura.RQL.IR.Insert
|
||||
, Hasura.RQL.IR.OrderBy
|
||||
, Hasura.RQL.IR.Returning
|
||||
, Hasura.RQL.IR.Select
|
||||
, Hasura.RQL.IR.RemoteSchema
|
||||
, Hasura.RQL.IR.Returning
|
||||
, Hasura.RQL.IR.Root
|
||||
, Hasura.RQL.IR.Select
|
||||
, Hasura.RQL.IR.Update
|
||||
, Hasura.RQL.IR.Update.Batch
|
||||
, Hasura.RQL.IR.Value
|
||||
, Hasura.RQL.IR.Root
|
||||
, Hasura.RQL.IR
|
||||
, Hasura.GraphQL.Analyse
|
||||
, Hasura.GraphQL.ApolloFederation
|
||||
|
@ -66,6 +66,7 @@ import Hasura.GraphQL.Schema.Select
|
||||
import Hasura.GraphQL.Schema.Update qualified as SU
|
||||
import Hasura.GraphQL.Schema.Update.Batch qualified as SUB
|
||||
import Hasura.Name qualified as Name
|
||||
import Hasura.NativeQuery.Schema qualified as NativeQueries
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp
|
||||
import Hasura.RQL.IR.Root (RemoteRelationshipField)
|
||||
@ -297,6 +298,7 @@ instance
|
||||
buildFunctionQueryFields = buildFunctionQueryFieldsPG
|
||||
buildFunctionRelayQueryFields = pgkBuildFunctionRelayQueryFields
|
||||
buildFunctionMutationFields = buildFunctionMutationFieldsPG
|
||||
buildNativeQueryRootFields = NativeQueries.defaultBuildNativeQueryRootFields
|
||||
|
||||
mkRelationshipParser = GSB.mkDefaultRelationshipParser backendInsertParser ()
|
||||
|
||||
|
@ -27,6 +27,8 @@ import Hasura.Backends.Postgres.Types.Function qualified as Postgres
|
||||
import Hasura.Backends.Postgres.Types.Insert qualified as Postgres (BackendInsert)
|
||||
import Hasura.Backends.Postgres.Types.Update qualified as Postgres
|
||||
import Hasura.Base.Error
|
||||
import Hasura.NativeQuery.IR (NativeQueryImpl)
|
||||
import Hasura.NativeQuery.Metadata
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.BoolExp.AggregationPredicates qualified as Agg
|
||||
import Hasura.RQL.Types.Backend
|
||||
@ -115,6 +117,9 @@ instance
|
||||
type ExtraTableMetadata ('Postgres pgKind) = PgExtraTableMetadata pgKind
|
||||
type BackendInsert ('Postgres pgKind) = Postgres.BackendInsert pgKind
|
||||
|
||||
type NativeQueryInfo ('Postgres pgKind) = NativeQueryInfoImpl ('Postgres pgKind)
|
||||
type NativeQuery ('Postgres pgKind) = NativeQueryImpl ('Postgres pgKind)
|
||||
|
||||
type XComputedField ('Postgres pgKind) = XEnable
|
||||
type XRelay ('Postgres pgKind) = XEnable
|
||||
type XNodesAgg ('Postgres pgKind) = XEnable
|
||||
|
@ -114,6 +114,8 @@ selectFromToFromItem prefix = \case
|
||||
S.mkFunctionAlias
|
||||
qf
|
||||
(fmap (fmap (first S.toColumnAlias)) defListM)
|
||||
-- This behavior is hidden behind a flag, so cannot be triggered yet.
|
||||
FromNativeQuery _ -> error "unimplemented"
|
||||
|
||||
-- | Converts a function name to an 'Identifier'.
|
||||
--
|
||||
|
@ -165,6 +165,8 @@ processSelectParams
|
||||
FromTable table -> S.QualTable table
|
||||
FromIdentifier i -> S.QualifiedIdentifier (TableIdentifier $ unFIIdentifier i) Nothing
|
||||
FromFunction qf _ _ -> S.QualifiedIdentifier (TableIdentifier $ qualifiedObjectToText qf) Nothing
|
||||
-- This behavior is hidden behind a flag, so cannot be triggered yet.
|
||||
FromNativeQuery _ -> error "unimplemented"
|
||||
|
||||
processAnnAggregateSelect ::
|
||||
forall pgKind m.
|
||||
|
@ -3,6 +3,8 @@
|
||||
-- | Types concerned with user-specified custom SQL fragments.
|
||||
module Hasura.CustomSQL
|
||||
( CustomSQLParameter (..),
|
||||
CustomSQLParameterName (..),
|
||||
CustomSQLParameterType (..),
|
||||
)
|
||||
where
|
||||
|
||||
|
@ -332,15 +332,18 @@ buildRoleContext options sources remotes actions customTypes role remoteSchemaPe
|
||||
runSourceSchema schemaContext schemaOptions sourceInfo do
|
||||
let validFunctions = takeValidFunctions functions
|
||||
validTables = takeValidTables tables
|
||||
nativeQueries = _siNativeQueries _customSQL
|
||||
mkRootFieldName = _rscRootFields sourceCustomization
|
||||
makeTypename = SC._rscTypeNames sourceCustomization
|
||||
(uncustomizedQueryRootFields, uncustomizedSubscriptionRootFields, apolloFedTableParsers) <-
|
||||
buildQueryAndSubscriptionFields mkRootFieldName sourceInfo validTables validFunctions
|
||||
(nativeQueryRootFields) <-
|
||||
buildNativeQueryFields sourceInfo nativeQueries
|
||||
(,,,,apolloFedTableParsers)
|
||||
<$> customizeFields
|
||||
sourceCustomization
|
||||
(makeTypename <> MkTypename (<> Name.__query))
|
||||
(pure uncustomizedQueryRootFields)
|
||||
(pure (uncustomizedQueryRootFields <> nativeQueryRootFields))
|
||||
<*> customizeFields
|
||||
sourceCustomization
|
||||
(makeTypename <> MkTypename (<> Name.__mutation_frontend))
|
||||
@ -674,6 +677,33 @@ buildQueryAndSubscriptionFields mkRootFieldName sourceInfo tables (takeExposedAs
|
||||
sourceConfig = _siConfiguration sourceInfo
|
||||
queryTagsConfig = _siQueryTagsConfig sourceInfo
|
||||
|
||||
runMaybeTmempty :: (Monad m, Monoid a) => MaybeT m a -> m a
|
||||
runMaybeTmempty = (`onNothingM` (pure mempty)) . runMaybeT
|
||||
|
||||
buildNativeQueryFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
SourceInfo b ->
|
||||
NativeQueryCache b ->
|
||||
SchemaT r m [P.FieldParser n (QueryRootField UnpreparedValue)]
|
||||
buildNativeQueryFields sourceInfo nativeQueries = runMaybeTmempty $ do
|
||||
roleName <- retrieve scRole
|
||||
|
||||
-- Native queries are only enabled for the admin role, pending the design of
|
||||
-- permissions for native queries.
|
||||
guard $ roleName == adminRoleName
|
||||
|
||||
map mkRF . catMaybes <$> for (Map.elems nativeQueries) \nativeQuery -> do
|
||||
lift $ (buildNativeQueryRootFields nativeQuery)
|
||||
where
|
||||
mkRF ::
|
||||
FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b)) ->
|
||||
FieldParser n (QueryRootField UnpreparedValue)
|
||||
mkRF = mkRootField sourceName sourceConfig queryTagsConfig QDBR
|
||||
sourceName = _siName sourceInfo
|
||||
sourceConfig = _siConfiguration sourceInfo
|
||||
queryTagsConfig = _siQueryTagsConfig sourceInfo
|
||||
|
||||
buildRelayQueryAndSubscriptionFields ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
|
@ -180,6 +180,15 @@ class
|
||||
TableName b ->
|
||||
SchemaT r m [FieldParser n (MutationDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))]
|
||||
|
||||
buildNativeQueryRootFields ::
|
||||
MonadBuildSchema b r m n =>
|
||||
NativeQueryInfo b ->
|
||||
SchemaT
|
||||
r
|
||||
m
|
||||
(Maybe (FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))))
|
||||
buildNativeQueryRootFields _ = pure Nothing
|
||||
|
||||
-- | Make a parser for relationships. Default implementaton elides
|
||||
-- relationships altogether.
|
||||
mkRelationshipParser ::
|
||||
|
22
server/src-lib/Hasura/NativeQuery/IR.hs
Normal file
22
server/src-lib/Hasura/NativeQuery/IR.hs
Normal file
@ -0,0 +1,22 @@
|
||||
-- | This module contains the default types and functions that model Native
|
||||
-- Queries.
|
||||
module Hasura.NativeQuery.IR
|
||||
( NativeQueryImpl (..),
|
||||
)
|
||||
where
|
||||
|
||||
import Hasura.NativeQuery.Metadata
|
||||
import Hasura.NativeQuery.Types
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Column (ColumnValue)
|
||||
|
||||
-- | The default implementation of an invocation of a native query.
|
||||
data NativeQueryImpl b field = NativeQueryImpl
|
||||
{ -- | The defined name of the native query.
|
||||
-- When translating this is used as a key to look up the actual
|
||||
-- native query definition.
|
||||
nqName :: NativeQueryName,
|
||||
-- | The arguments passed to the native query, if any.
|
||||
nqArgs :: HashMap NativeQueryArgumentName (ColumnValue b)
|
||||
}
|
||||
deriving (Eq, Functor, Foldable, Traversable, Show)
|
23
server/src-lib/Hasura/NativeQuery/Metadata.hs
Normal file
23
server/src-lib/Hasura/NativeQuery/Metadata.hs
Normal file
@ -0,0 +1,23 @@
|
||||
-- | This module houses the types and functions associated with the default
|
||||
-- implementation of the metadata of native queries.
|
||||
module Hasura.NativeQuery.Metadata
|
||||
( NativeQueryArgumentName (..),
|
||||
NativeQueryInfoImpl (..),
|
||||
)
|
||||
where
|
||||
|
||||
import Hasura.NativeQuery.Types
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend
|
||||
|
||||
newtype NativeQueryArgumentName = NativeQueryArgumentName {getNativeQueryArgumentName :: Text}
|
||||
deriving (Eq, Ord, Hashable, Show)
|
||||
|
||||
-- | Provisional data type for modelling metadata
|
||||
data NativeQueryInfoImpl b = NativeQueryInfoImpl
|
||||
{ nqiiName :: NativeQueryName,
|
||||
nqiiCode :: Text,
|
||||
nqiiReturns :: TableName b,
|
||||
nqiiArgs :: HashMap NativeQueryArgumentName (ScalarType b),
|
||||
nqiiComment :: Text
|
||||
}
|
132
server/src-lib/Hasura/NativeQuery/Schema.hs
Normal file
132
server/src-lib/Hasura/NativeQuery/Schema.hs
Normal file
@ -0,0 +1,132 @@
|
||||
{-# LANGUAGE QuasiQuotes #-}
|
||||
|
||||
module Hasura.NativeQuery.Schema (defaultBuildNativeQueryRootFields) where
|
||||
|
||||
import Data.Has (Has (getter))
|
||||
import Data.HashMap.Strict qualified as HM
|
||||
import Data.Monoid (Ap (Ap, getAp))
|
||||
import Hasura.GraphQL.Schema.Backend
|
||||
( BackendSchema (columnParser),
|
||||
BackendTableSelectSchema (tableArguments),
|
||||
MonadBuildSchema,
|
||||
)
|
||||
import Hasura.GraphQL.Schema.Common
|
||||
( SchemaContext (scRole),
|
||||
SchemaT,
|
||||
askTableInfo,
|
||||
retrieve,
|
||||
)
|
||||
import Hasura.GraphQL.Schema.Options qualified as Options
|
||||
import Hasura.GraphQL.Schema.Parser qualified as P
|
||||
import Hasura.GraphQL.Schema.Select
|
||||
( tablePermissionsInfo,
|
||||
tableSelectionList,
|
||||
)
|
||||
import Hasura.GraphQL.Schema.Table (tableSelectPermissions)
|
||||
import Hasura.NativeQuery.IR (NativeQueryImpl (..))
|
||||
import Hasura.NativeQuery.Metadata
|
||||
( NativeQueryArgumentName (..),
|
||||
NativeQueryInfoImpl (..),
|
||||
)
|
||||
import Hasura.NativeQuery.Types (NativeQueryName (..))
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.IR.Root (RemoteRelationshipField)
|
||||
import Hasura.RQL.IR.Select (QueryDB (QDBSingleRow))
|
||||
import Hasura.RQL.IR.Select qualified as IR
|
||||
import Hasura.RQL.IR.Value (UnpreparedValue, openValueOrigin)
|
||||
import Hasura.RQL.Types.Backend
|
||||
( Backend (NativeQuery, ScalarType),
|
||||
)
|
||||
import Hasura.RQL.Types.Column qualified as Column
|
||||
import Hasura.RQL.Types.Metadata.Object qualified as MO
|
||||
import Hasura.RQL.Types.Source
|
||||
( SourceInfo (_siCustomization, _siName),
|
||||
)
|
||||
import Hasura.RQL.Types.SourceCustomization
|
||||
( ResolvedSourceCustomization (_rscNamingConvention),
|
||||
)
|
||||
import Hasura.RQL.Types.Table (tableInfoName)
|
||||
import Hasura.SQL.AnyBackend (mkAnyBackend)
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
import Language.GraphQL.Draft.Syntax.QQ qualified as G
|
||||
|
||||
defaultBuildNativeQueryRootFields ::
|
||||
forall b r m n.
|
||||
( MonadBuildSchema b r m n,
|
||||
BackendTableSelectSchema b,
|
||||
NativeQuery b ~ NativeQueryImpl b
|
||||
) =>
|
||||
NativeQueryInfoImpl b ->
|
||||
SchemaT
|
||||
r
|
||||
m
|
||||
(Maybe (P.FieldParser n (QueryDB b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b))))
|
||||
defaultBuildNativeQueryRootFields NativeQueryInfoImpl {..} = runMaybeT $ do
|
||||
tableInfo <- askTableInfo @b nqiiReturns
|
||||
fieldName <- hoistMaybe (G.mkName $ getNativeQueryName nqiiName)
|
||||
nativeQueryArgsParser <- nativeQueryArgumentsSchema @b @r @m @n fieldName nqiiArgs
|
||||
sourceInfo :: SourceInfo b <- asks getter
|
||||
let sourceName = _siName sourceInfo
|
||||
tableName = tableInfoName tableInfo
|
||||
tCase = _rscNamingConvention $ _siCustomization sourceInfo
|
||||
description = Just $ G.Description $ "A native query called " <> getNativeQueryName nqiiName
|
||||
stringifyNumbers <- retrieve Options.soStringifyNumbers
|
||||
roleName <- retrieve scRole
|
||||
|
||||
selectionSetParser <- MaybeT $ tableSelectionList @b @r @m @n tableInfo
|
||||
tableArgsParser <- lift $ tableArguments @b @r @m @n tableInfo
|
||||
selectPermissions <- hoistMaybe $ tableSelectPermissions roleName tableInfo
|
||||
pure $
|
||||
P.setFieldParserOrigin (MO.MOSourceObjId sourceName (mkAnyBackend $ MO.SMOTable @b tableName)) $
|
||||
P.subselection fieldName description ((,) <$> tableArgsParser <*> nativeQueryArgsParser) selectionSetParser
|
||||
<&> \((args, nqArgs), fields) ->
|
||||
QDBSingleRow $
|
||||
IR.AnnSelectG
|
||||
{ IR._asnFields = fields,
|
||||
IR._asnFrom =
|
||||
IR.FromNativeQuery
|
||||
NativeQueryImpl
|
||||
{ nqName = nqiiName,
|
||||
nqArgs
|
||||
},
|
||||
IR._asnPerm = tablePermissionsInfo selectPermissions,
|
||||
IR._asnArgs = args,
|
||||
IR._asnStrfyNum = stringifyNumbers,
|
||||
IR._asnNamingConvention = Just tCase
|
||||
}
|
||||
|
||||
nativeQueryArgumentsSchema ::
|
||||
forall b r m n.
|
||||
MonadBuildSchema b r m n =>
|
||||
G.Name ->
|
||||
HashMap NativeQueryArgumentName (ScalarType b) ->
|
||||
MaybeT (SchemaT r m) (P.InputFieldsParser n (HashMap NativeQueryArgumentName (Column.ColumnValue b)))
|
||||
nativeQueryArgumentsSchema nativeQueryName argsSignature = do
|
||||
-- Lift 'SchemaT r m (InputFieldsParser ..)' into a monoid using Applicative.
|
||||
-- This lets us use 'foldMap' + monoid structure of hashmaps to avoid awkwardly
|
||||
-- traversing the arguments and building the resulting parser.
|
||||
argsParser <-
|
||||
getAp $
|
||||
foldMap
|
||||
( \(name, ty) -> Ap do
|
||||
argValueParser <-
|
||||
fmap (HM.singleton name . openValueOrigin)
|
||||
<$> lift (columnParser (Column.ColumnScalar ty) (G.Nullability False))
|
||||
-- TODO: Break in some interesting way if we cannot make a name?
|
||||
-- TODO: Naming conventions?
|
||||
-- TODO: Custom fields? (Probably not)
|
||||
argName <- hoistMaybe (G.mkName (getNativeQueryArgumentName name))
|
||||
return $
|
||||
P.field
|
||||
argName
|
||||
(Just $ G.Description ("Native query argument " <> getNativeQueryArgumentName name))
|
||||
argValueParser
|
||||
)
|
||||
(HM.toList argsSignature)
|
||||
|
||||
let desc = Just $ G.Description $ G.unName nativeQueryName <> " Native Query Arguments"
|
||||
pure $
|
||||
P.field
|
||||
[G.name|args|]
|
||||
desc
|
||||
(P.object (nativeQueryName <> [G.name|_arguments|]) desc argsParser)
|
11
server/src-lib/Hasura/NativeQuery/Types.hs
Normal file
11
server/src-lib/Hasura/NativeQuery/Types.hs
Normal file
@ -0,0 +1,11 @@
|
||||
-- | This module houses the types that are necessary to even talk about native
|
||||
-- queries abstractly of a concrete implementation.
|
||||
module Hasura.NativeQuery.Types
|
||||
( NativeQueryName (..),
|
||||
)
|
||||
where
|
||||
|
||||
import Hasura.Prelude
|
||||
|
||||
newtype NativeQueryName = NativeQueryName {getNativeQueryName :: Text}
|
||||
deriving (Eq, Ord, Show, Hashable)
|
@ -381,6 +381,7 @@ data SelectFromG (b :: BackendType) v
|
||||
(FunctionArgsExp b v)
|
||||
-- a definition list
|
||||
(Maybe [(Column b, ScalarType b)])
|
||||
| FromNativeQuery (NativeQuery b v)
|
||||
deriving stock (Generic)
|
||||
|
||||
deriving stock instance (Backend b) => Functor (SelectFromG b)
|
||||
@ -389,11 +390,29 @@ deriving stock instance (Backend b) => Foldable (SelectFromG b)
|
||||
|
||||
deriving stock instance (Backend b) => Traversable (SelectFromG b)
|
||||
|
||||
deriving stock instance (Backend b, Eq v, Eq (FunctionArgumentExp b v)) => Eq (SelectFromG b v)
|
||||
deriving stock instance
|
||||
( Backend b,
|
||||
Eq v,
|
||||
Eq (FunctionArgumentExp b v),
|
||||
Eq (NativeQuery b v)
|
||||
) =>
|
||||
Eq (SelectFromG b v)
|
||||
|
||||
deriving stock instance (Backend b, Show v, Show (FunctionArgumentExp b v)) => Show (SelectFromG b v)
|
||||
deriving stock instance
|
||||
( Backend b,
|
||||
Show v,
|
||||
Show (FunctionArgumentExp b v),
|
||||
Show (NativeQuery b v)
|
||||
) =>
|
||||
Show (SelectFromG b v)
|
||||
|
||||
instance (Backend b, Hashable v, Hashable (FunctionArgumentExp b v)) => Hashable (SelectFromG b v)
|
||||
instance
|
||||
( Backend b,
|
||||
Hashable v,
|
||||
Hashable (FunctionArgumentExp b v),
|
||||
Hashable (NativeQuery b v)
|
||||
) =>
|
||||
Hashable (SelectFromG b v)
|
||||
|
||||
type SelectFrom b = SelectFromG b (SQLExpression b)
|
||||
|
||||
|
@ -178,7 +178,10 @@ class
|
||||
Traversable (BackendInsert b),
|
||||
Functor (AggregationPredicates b),
|
||||
Foldable (AggregationPredicates b),
|
||||
Traversable (AggregationPredicates b)
|
||||
Traversable (AggregationPredicates b),
|
||||
Functor (NativeQuery b),
|
||||
Foldable (NativeQuery b),
|
||||
Traversable (NativeQuery b)
|
||||
) =>
|
||||
Backend (b :: BackendType)
|
||||
where
|
||||
@ -309,6 +312,21 @@ class
|
||||
|
||||
type BackendInsert b = Const Void
|
||||
|
||||
-- | Intermediate representation of Native Queries
|
||||
-- The default implementation makes native queries uninstantiable.
|
||||
--
|
||||
-- It is parameterised over the type of fields, which changes during the IR
|
||||
-- translation phases.
|
||||
type NativeQuery b :: Type -> Type
|
||||
|
||||
type NativeQuery b = Const Void
|
||||
|
||||
-- | Metadata representation of definitions of native queries.
|
||||
-- The default implementation makes native queries uninstantiable.
|
||||
type NativeQueryInfo b :: Type
|
||||
|
||||
type NativeQueryInfo b = Void
|
||||
|
||||
-- extension types
|
||||
type XComputedField b :: Type
|
||||
type XRelay b :: Type
|
||||
|
@ -18,6 +18,8 @@ module Hasura.RQL.Types.Source
|
||||
siQueryTagsConfig,
|
||||
siTables,
|
||||
siCustomization,
|
||||
NativeQueryCache,
|
||||
_siNativeQueries,
|
||||
|
||||
-- * Schema cache
|
||||
ResolvedSource (..),
|
||||
@ -42,16 +44,23 @@ where
|
||||
|
||||
import Control.Lens hiding ((.=))
|
||||
import Data.Aeson.Extended
|
||||
import Data.HashMap.Strict qualified as HM
|
||||
import Data.Maybe (fromJust)
|
||||
import Data.Text.Lazy qualified as TL
|
||||
import Data.Text.Lazy.Encoding qualified as BS
|
||||
import Database.PG.Query qualified as PG
|
||||
import Hasura.Base.Error
|
||||
import Hasura.CustomSQL (CustomSQLParameter (..), CustomSQLParameterName (..), CustomSQLParameterType (..))
|
||||
import Hasura.Logging qualified as L
|
||||
import Hasura.NativeQuery.Metadata (NativeQueryArgumentName (..), NativeQueryInfoImpl (..))
|
||||
import Hasura.NativeQuery.Types (NativeQueryName (..))
|
||||
import Hasura.Prelude
|
||||
import Hasura.RQL.Types.Backend
|
||||
import Hasura.RQL.Types.Common
|
||||
import Hasura.RQL.Types.Function
|
||||
import Hasura.RQL.Types.HealthCheck
|
||||
import Hasura.RQL.Types.Instances ()
|
||||
import Hasura.RQL.Types.Metadata.Common (CustomSQLFields)
|
||||
import Hasura.RQL.Types.Metadata.Common (CustomSQLFields, CustomSQLMetadata (..))
|
||||
import Hasura.RQL.Types.QueryTags
|
||||
import Hasura.RQL.Types.SourceCustomization
|
||||
import Hasura.RQL.Types.Table
|
||||
@ -60,6 +69,7 @@ import Hasura.SQL.Backend
|
||||
import Hasura.SQL.Tag
|
||||
import Hasura.Tracing qualified as Tracing
|
||||
import Language.GraphQL.Draft.Syntax qualified as G
|
||||
import Unsafe.Coerce (unsafeCoerce)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
-- Metadata (FIXME: this grouping is inaccurate)
|
||||
@ -74,6 +84,45 @@ data SourceInfo b = SourceInfo
|
||||
_siCustomization :: ResolvedSourceCustomization
|
||||
}
|
||||
|
||||
-- This function is a temporary integration between metadata and schema of the Native Queries MVP.
|
||||
-- It is **not** representative of the code quality we strive for, and will be properly dealt with.
|
||||
_siNativeQueries :: forall b. Backend b => CustomSQLFields b -> NativeQueryCache b
|
||||
_siNativeQueries = foldMap toItem
|
||||
where
|
||||
toItem :: CustomSQLMetadata b -> HashMap NativeQueryName (NativeQueryInfo b)
|
||||
toItem csm = HM.fromList [(toNativeQueryName (_csmRootFieldName csm), toInfo csm)]
|
||||
|
||||
toNativeQueryName :: G.Name -> NativeQueryName
|
||||
toNativeQueryName = NativeQueryName . G.unName
|
||||
|
||||
toInfo :: CustomSQLMetadata b -> NativeQueryInfo b
|
||||
toInfo CustomSQLMetadata {..} =
|
||||
-- '_siNativeQueries' would have to be defined in some type class over
|
||||
-- 'b' in order to avoid this unsafeCoerce.
|
||||
-- But since this is a temporary stop-gap which we won't release it's fine.
|
||||
unsafeCoerce $ (NativeQueryInfoImpl {..} :: NativeQueryInfoImpl b)
|
||||
where
|
||||
nqiiName = toNativeQueryName _csmRootFieldName
|
||||
nqiiCode = _csmSql
|
||||
nqiiReturns = _csmReturns
|
||||
nqiiArgs = toArgs _csmParameters
|
||||
nqiiComment = "TBD"
|
||||
|
||||
toArgs :: NonEmpty CustomSQLParameter -> HashMap NativeQueryArgumentName (ScalarType b)
|
||||
toArgs = foldMap toArg
|
||||
|
||||
toArg :: CustomSQLParameter -> HashMap NativeQueryArgumentName (ScalarType b)
|
||||
toArg CustomSQLParameter {..} = HM.fromList [(toArgName cspName, toScalarType cspType)]
|
||||
|
||||
toArgName :: CustomSQLParameterName -> NativeQueryArgumentName
|
||||
toArgName CustomSQLParameterName {..} = NativeQueryArgumentName cspnName
|
||||
|
||||
-- This mismatch is the worst part.
|
||||
toScalarType :: CustomSQLParameterType -> ScalarType b
|
||||
toScalarType CustomSQLParameterType {..} = fromJust $ decode (BS.encodeUtf8 $ TL.fromStrict cspnType)
|
||||
|
||||
type NativeQueryCache b = HashMap NativeQueryName (NativeQueryInfo b)
|
||||
|
||||
$(makeLenses ''SourceInfo)
|
||||
|
||||
instance
|
||||
|
Loading…
Reference in New Issue
Block a user