Skip to content

Can't resolve fields of inline fragments when inspecting a query #1718

@redhead

Description

@redhead

I've ran into similar issue as in already reported #973 but with no information about how to go around it.

Background
What we are doing is that, at the beginning of query execution, we inspect the whole query to create our custom graph data fetching strategy before the GQL data fetchers are called. Data fetchers, in the end, should just access the graph data fetching result, and should not do any DB fetching. The whole fetching should happen at once at the beginning of the query, not lazily.

So the pipeline goes something like this:

GQL query -> query inspection -> our graph selection strategy -> our strategy execution -> graph object result -> GQL data fetchers simply accessing the result

Inspection phase
To understand what to fetch in our fetching strategy, we are going through the query by using the root DataFetchingEnvironment and going through the SelectedFields coming from DataFetchingFieldSelectionSets. Thus resolving all the arguments, and all the nested fields we need to fetch.

This works fine.

The issue
The issue comes when the query contains inline fragments that contain additional fields (that we want to know about beforehand). From the above inspection, the GQL java API doesn't return such information (inline fragments are ignored, and the fields below don't get resolved), and so we don't know what to fetch.

We get that information only in the data fetcher of that field when it comes to it. But that is already late, as we want to make the whole graph fetching eager at the beginning, not lazily (based on the data fetchers of individual fields).

Example

{
    parent {
        ...on ChildA {
            fieldA
        }
        ...on ChildB {
            fieldB
        }
    }
}

Going through the env.getSelectionSet() of that query, the fields fieldA and fieldB are nowhere to be found.

Investigation
There is a piece of code in the GQL java which is connected to this issue:

// DataFetchingFieldSelectionSetImpl.java

private void traverseFields(MergedField fieldList, GraphQLFieldsContainer parentFieldType, String fieldPrefix) {

    FieldCollectorParameters parameters = FieldCollectorParameters.newParameters()
            .schema(graphQLSchema)
            .objectType(asObjectTypeOrNull(parentFieldType))            <-------------- this is important part
            .fragments(fragmentsByName)
            .variables(variables)
            .build();

Here the parentFieldType refers to the type of the parent field, which is, in this case, an interface. The information about the inline fragment and the type the fragment refers to is not present at this point, so the asObjectTypeOrNull() returns null. This causes the FieldCollector not to collect the fields of the inline fragment (checkTypeCondition() returns false).

Question
Now, I don't know if this is a bug or it's by design. The concrete GQL type of the inline fragment is known (childA, or childB), thus the fields should be possible to be resolved.

If it isn't a bug, how can I get the complete information about what graph structure I'm fetching before actually calling the GQL java data fetchers?

Note: as I need to resolve the arguments, and variables, etc. I can't use the MergedField API to get that information (that one contains the whole tree, as in the query, but it is unresolved)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions