Repository: edgedb/edgedb

Issue:
unresolved type: std::Movie_Type
<!-- Please search existing issues to avoid creating duplicates. -->
- EdgeDB Version: 1.0.0
- OS Version: MacOs

Steps to Reproduce:

1. Setup the DB from the quick start: https://www.edgedb.com/docs/guides/quickstart
2. enable graphql
3. query graphql using:
```gql
query {
  Movie{
    id
    __typename
    ... on Movie_Type {
      id
    }
  }
}
```
recieve:
```
{
  "errors": [
    {
      "message": "AssertionError: unresolved type: std::Movie_Type"
    }
  ]
}
```

n.b. this works:
```gql
query {
  Movie{
    id
    __typename
    ... on BaseObject {
      id
    }
  }
}
```

<!-- If the issue is about a query error, please also provide your schema -->
Schema:
```
using extension graphql;

module default {
    type Person {
        required property first_name -> str;
        property last_name -> str;

        property full_name :=
        .first_name ++ ' ' ++ .last_name
        if exists .last_name
        else .first_name;
    }

    type Movie {
        required property title -> str;
        property year -> int64;
        link director -> Person;
        multi link actors -> Person;
    }
}
```


Discussion:
I'm not 100% sure why `Movie_Type` is the actual `type` whereas `Movie` is an interface. @vpetrovykh? 

In the meantime, changing `Movie_Type` to `Movie` resolves this.
The issue comes up when trying to use schema stitching as the `graphql-tools` library seems to insert a fragment which then triggers the error (at least when trying to extend the schema.
```js
  const ret = stitchSchemas({
    inheritResolversFromInterfaces: true,
    subschemas: [schema],
    typeDefs: /* GraphQL */ `
      extend interface Movie {
        foo: String
      }
      extend type Movie_Type {
        foo: String
      }
    `,
    resolvers: {
      Movie: {
        foo: () => "foo",
      },
    },
  });
```

Resolving patch:
diff --git a/edb/graphql/types.py b/edb/graphql/types.py
--- a/edb/graphql/types.py
+++ b/edb/graphql/types.py
@@ -1344,36 +1344,46 @@ def get(self, name: str, *, dummy: bool = False) -> GQLBaseType:
         kwargs: Dict[str, Any] = {'dummy': dummy}
 
         if not name.startswith('__graphql__::'):
-            if edb_base is None:
-                if '::' in name:
-                    edb_base = self.edb_schema.get(
-                        name,
-                        type=s_types.Type,
-                    )
-                else:
-                    for module in self.modules:
+            # The name may potentially contain the suffix "_Type",
+            # which in 99% cases indicates that it's a GraphQL
+            # internal type generated from the EdgeDB base type, but
+            # we technically need to check both.
+            if name.endswith('_Type'):
+                names = [name[:-len('_Type')], name]
+            else:
+                names = [name]
+
+            for tname in names:
+                if edb_base is None:
+                    if '::' in tname:
                         edb_base = self.edb_schema.get(
-                            f'{module}::{name}',
+                            tname,
                             type=s_types.Type,
-                            default=None,
-                        )
-                        if edb_base:
-                            break
-
-                    # XXX: find a better way to do this
-                    if edb_base is None:
-                        edb_base = self.edb_schema.get_global(
-                            s_types.Array, name, default=None
-                        )
-
-                    if edb_base is None:
-                        edb_base = self.edb_schema.get_global(
-                            s_types.Tuple, name, default=None
                         )
-
-                    if edb_base is None:
-                        raise AssertionError(
-                            f'unresolved type: {module}::{name}')
+                    else:
+                        for module in self.modules:
+                            edb_base = self.edb_schema.get(
+                                f'{module}::{tname}',
+                                type=s_types.Type,
+                                default=None,
+                            )
+                            if edb_base:
+                                break
+
+                        # XXX: find a better way to do this
+                        if edb_base is None:
+                            edb_base = self.edb_schema.get_global(
+                                s_types.Array, tname, default=None
+                            )
+
+                        if edb_base is None:
+                            edb_base = self.edb_schema.get_global(
+                                s_types.Tuple, tname, default=None
+                            )
+
+                if edb_base is None:
+                    raise AssertionError(
+                        f'unresolved type: {module}::{name}')
 
             kwargs['edb_base'] = edb_base
 


Test patch:
diff --git a/tests/test_http_graphql_query.py b/tests/test_http_graphql_query.py
--- a/tests/test_http_graphql_query.py
+++ b/tests/test_http_graphql_query.py
@@ -1648,6 +1648,34 @@ def test_graphql_functional_fragment_04(self):
             }],
         })
 
+    def test_graphql_functional_fragment_05(self):
+        # ISSUE #3514
+        #
+        # Fragment on the actual type should also work.
+        self.assert_graphql_query_result(r"""
+            fragment userFrag on User_Type {
+                active
+                profile {
+                    value
+                }
+            }
+
+            query {
+                User(filter: {name: {eq: "Alice"}}) {
+                    name
+                    ... userFrag
+                }
+            }
+        """, {
+            'User': [{
+                'name': 'Alice',
+                'active': True,
+                'profile': {
+                    'value': 'special',
+                }
+            }],
+        })
+
     def test_graphql_functional_fragment_type_01(self):
         self.assert_graphql_query_result(r"""
             fragment userFrag on User {
@@ -2145,6 +2173,32 @@ def test_graphql_functional_fragment_type_17(self):
             }],
         })
 
+    def test_graphql_functional_fragment_type_18(self):
+        # ISSUE #3514
+        #
+        # Fragment on the actual type should also work.
+        self.assert_graphql_query_result(r"""
+            query {
+                User(filter: {name: {eq: "Alice"}}) {
+                    ... on User_Type {
+                        active
+                        profile {
+                            value
+                        }
+                    }
+                    name
+                }
+            }
+        """, {
+            'User': [{
+                'name': 'Alice',
+                'active': True,
+                'profile': {
+                    'value': 'special',
+                }
+            }],
+        })
+
     def test_graphql_functional_directives_01(self):
         self.assert_graphql_query_result(r"""
             query {