mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-11-10 10:29:12 +03:00
server: allow fragments to use variables (fix hasura/graphql-engine#6303) (#225)
GitOrigin-RevId: a60b6816212b749836d5d88f296e229e581ab452
This commit is contained in:
parent
4ff84756ca
commit
4bbd2fd4dc
@ -72,6 +72,7 @@ and be accessible according to the permissions that were configured for the role
|
||||
|
||||
(Add entries here in the order of: server, console, cli, docs, others)
|
||||
|
||||
- server: fix a regression where variables in fragments weren't accepted (fix #6303)
|
||||
- server: output stack traces when encountering conflicting GraphQL types in the schema
|
||||
- server: add `--websocket-compression` command-line flag for enabling websocket compression (fix #3292)
|
||||
- server: some mutations that cannot be performed will no longer be in the schema (for instance, `delete_by_pk` mutations won't be shown to users that do not have select permissions on all primary keys) (#4111)
|
||||
|
@ -48,7 +48,7 @@ source-repository-package
|
||||
source-repository-package
|
||||
type: git
|
||||
location: https://github.com/hasura/graphql-parser-hs.git
|
||||
tag: f2e51dbde21ad1c596f659144128d80b69254e98
|
||||
tag: f3a20ab6201669bd683d5a0c8580410af264c7d0
|
||||
|
||||
source-repository-package
|
||||
type: git
|
||||
|
@ -61,8 +61,8 @@ data InlineEnv = InlineEnv
|
||||
}
|
||||
|
||||
-- | Internal bookkeeping used during inlining.
|
||||
newtype InlineState var = InlineState
|
||||
{ _isFragmentCache :: HashMap Name (InlineFragment NoFragments var)
|
||||
newtype InlineState = InlineState
|
||||
{ _isFragmentCache :: HashMap Name (InlineFragment NoFragments Name)
|
||||
-- ^ A cache of fragment definitions we’ve already inlined, so we don’t need
|
||||
-- to inline them again.
|
||||
}
|
||||
@ -70,10 +70,10 @@ newtype InlineState var = InlineState
|
||||
$(makeLensesFor [("_ieFragmentStack", "ieFragmentStack")] ''InlineEnv)
|
||||
$(makeLenses ''InlineState)
|
||||
|
||||
type MonadInline var m =
|
||||
type MonadInline m =
|
||||
( MonadError QErr m
|
||||
, MonadReader InlineEnv m
|
||||
, MonadState (InlineState var) m
|
||||
, MonadState InlineState m
|
||||
)
|
||||
|
||||
-- | Inlines all fragment spreads in a 'SelectionSet'; see the module
|
||||
@ -81,8 +81,8 @@ type MonadInline var m =
|
||||
inlineSelectionSet
|
||||
:: (MonadError QErr m, Foldable t)
|
||||
=> t FragmentDefinition
|
||||
-> SelectionSet FragmentSpread var
|
||||
-> m (SelectionSet NoFragments var)
|
||||
-> SelectionSet FragmentSpread Name
|
||||
-> m (SelectionSet NoFragments Name)
|
||||
inlineSelectionSet fragmentDefinitions selectionSet = do
|
||||
let fragmentDefinitionMap = Map.groupOnNE _fdName fragmentDefinitions
|
||||
uniqueFragmentDefinitions <- flip Map.traverseWithKey fragmentDefinitionMap
|
||||
@ -109,19 +109,19 @@ inlineSelectionSet fragmentDefinitions selectionSet = do
|
||||
{ _ieFragmentDefinitions = uniqueFragmentDefinitions
|
||||
, _ieFragmentStack = [] }
|
||||
where
|
||||
fragmentsInSelectionSet :: SelectionSet FragmentSpread var -> [Name]
|
||||
fragmentsInSelectionSet :: SelectionSet FragmentSpread Name -> [Name]
|
||||
fragmentsInSelectionSet selectionSet' = concatMap getFragFromSelection selectionSet'
|
||||
|
||||
getFragFromSelection :: Selection FragmentSpread var -> [Name]
|
||||
getFragFromSelection :: Selection FragmentSpread Name -> [Name]
|
||||
getFragFromSelection = \case
|
||||
SelectionField fld -> fragmentsInSelectionSet $ _fSelectionSet fld
|
||||
SelectionFragmentSpread fragmentSpread -> [_fsName fragmentSpread]
|
||||
SelectionInlineFragment inlineFragment -> fragmentsInSelectionSet $ _ifSelectionSet inlineFragment
|
||||
|
||||
inlineSelection
|
||||
:: MonadInline var m
|
||||
=> Selection FragmentSpread var
|
||||
-> m (Selection NoFragments var)
|
||||
:: MonadInline m
|
||||
=> Selection FragmentSpread Name
|
||||
-> m (Selection NoFragments Name)
|
||||
inlineSelection (SelectionField field@Field{ _fSelectionSet }) =
|
||||
withPathK "selectionSet" $ withPathK (unName $ _fName field) $ do
|
||||
selectionSet <- traverse inlineSelection _fSelectionSet
|
||||
@ -134,9 +134,9 @@ inlineSelection (SelectionInlineFragment fragment@InlineFragment{ _ifSelectionSe
|
||||
pure $! SelectionInlineFragment fragment{ _ifSelectionSet = selectionSet }
|
||||
|
||||
inlineFragmentSpread
|
||||
:: MonadInline var m
|
||||
=> FragmentSpread var
|
||||
-> m (InlineFragment NoFragments var)
|
||||
:: MonadInline m
|
||||
=> FragmentSpread Name
|
||||
-> m (InlineFragment NoFragments Name)
|
||||
inlineFragmentSpread FragmentSpread{ _fsName, _fsDirectives } = do
|
||||
InlineEnv{ _ieFragmentDefinitions, _ieFragmentStack } <- ask
|
||||
InlineState{ _isFragmentCache } <- get
|
||||
@ -158,7 +158,7 @@ inlineFragmentSpread FragmentSpread{ _fsName, _fsDirectives } = do
|
||||
<- Map.lookup _fsName _ieFragmentDefinitions -> withPathK (unName _fsName) $ do
|
||||
|
||||
selectionSet <- locally ieFragmentStack (_fsName :) $
|
||||
traverse inlineSelection (fmap absurd <$> _fdSelectionSet)
|
||||
traverse inlineSelection _fdSelectionSet
|
||||
|
||||
let fragment = InlineFragment
|
||||
{ _ifTypeCondition = Just _fdTypeCondition
|
||||
|
@ -0,0 +1,21 @@
|
||||
description: select query on author with id = 1, passed through a fragment with variables
|
||||
url: /v1/graphql
|
||||
status: 200
|
||||
response:
|
||||
data:
|
||||
author_by_pk:
|
||||
id: 2
|
||||
name: Author 2
|
||||
query:
|
||||
variables:
|
||||
authorId: 2
|
||||
query: |
|
||||
fragment MyFragment on query_root {
|
||||
author_by_pk(id: $authorId){
|
||||
id
|
||||
name
|
||||
}
|
||||
}
|
||||
query ($authorId : Int!) {
|
||||
...MyFragment
|
||||
}
|
@ -100,6 +100,9 @@ class TestGraphQLQueryFragments:
|
||||
def test_select_query_fragment_cycles(self, hge_ctx, transport):
|
||||
check_query_f(hge_ctx, self.dir() + '/select_query_fragment_cycles.yaml', transport)
|
||||
|
||||
def test_select_query_fragment_with_variable(self, hge_ctx, transport):
|
||||
check_query_f(hge_ctx, self.dir() + '/select_query_fragment_with_variable.yaml', transport)
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
return 'queries/graphql_query/basic'
|
||||
|
Loading…
Reference in New Issue
Block a user