Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Multi-directional relationships will cause the runtime to fail when building the schema #906

Closed
Tracked by #1576
sajeetharan opened this issue Oct 26, 2022 · 6 comments
Assignees
Labels
cosmos graphql mssql pgsql mysql an issue that applies to all relational databases, same as labeling with `mssql` `mysql` and `pgsql` needs discussion

Comments

@sajeetharan
Copy link
Member

sajeetharan commented Oct 26, 2022

Currently the engine throws an error with the getting started sample

Here is the query to get list of books and authors:


{
  books(filter: { title: { eq: "Foundation" } })
  {
    items {
      id
      title
      authors {
          first_name
          last_name
        }
    }
  }
}

and the schema as follows,

type Author @model {
    id : ID,
    first_name : String,
    middle_name: String,
    last_name: String,
    Books: [Book]
}

type Book @model {
    id : ID,
    title : String,
    Authors: [Author]
}

it throws an error as The runtime refused to evaluate expression at this time

@sajeetharan sajeetharan added this to the Oct2022 milestone Oct 26, 2022
@sajeetharan sajeetharan changed the title DAB Engine : Cosmos - "The type Authors is not a known GraphQL type, and cannot be used in this schema." DAB Engine : Cosmos - The runtime refused to evaluate expression at this time Oct 28, 2022
@aaronpowell
Copy link
Contributor

I'm currently having a look at this (managed to write a unit test that can validate schemas in a much simpler way).

The problem is that when it is trying to create the InputType's for the @model types, it becomes recursive, and as a result, crashes the runtime.

Now this is only a problem on the MutationBuilder phase of the schema compiler, the QueryBuilder doesn't have this problem, despite having recursive input types (on the filter), so I'm investigating whether something changed or was just missed.

@aaronpowell
Copy link
Contributor

aaronpowell commented Oct 31, 2022

Actually, it does raise an interesting question, how do we handle relationships within a mutation?

The problem exists because it's trying to create an input type that allows you to insert a multiple entities in a single pass, so you could do this:

mutation {
  createBook(input: { id: "...", title: "...", Authors: [{ id: "...", first_name: "...", last_name: "...", middle_name: "...", Books: [{ id: "...", title: "..." }] }]) {
    id
  }
}

Is this expected? Should we be allowing you to create recursive items such as this? I don't think you should be able to.

Note: This isn't just a problem with Cosmos, this will manifest itself in the SQL variations as well, but it's a bit harder to do as you spend a lot more time setting up the relationships. This doesn't happen in SQL, see following comment.

@seantleonard seantleonard added mssql pgsql mysql an issue that applies to all relational databases, same as labeling with `mssql` `mysql` and `pgsql` needs discussion labels Oct 31, 2022
@Aniruddh25 Aniruddh25 modified the milestones: Oct2022, Nov2022 Oct 31, 2022
@aaronpowell
Copy link
Contributor

After doing some more digging, I've found that this bug is caused by a change introduced with #531

It doesn't impact the SQL engine, as it's only allowing nested models on Cosmos.

Looking at the tests that were included, they only tackle one-way relationships, not two-way, which is likely why it was never picked up then.

@aaronpowell aaronpowell changed the title DAB Engine : Cosmos - The runtime refused to evaluate expression at this time Multi-directional relationships will cause the runtime to fail when building the schema Nov 10, 2022
@Aniruddh25 Aniruddh25 modified the milestones: Nov2022, Jan2023 Nov 18, 2022
@Aniruddh25
Copy link
Contributor

Needs an RFC to specify what the behavior for nested mutations should be for both Cosmos and SQL - @sajeetharan, @yorek

@dgcaron
Copy link

dgcaron commented Jun 13, 2023

i am also running into this:

consider the following graphql schema:

type IndustryModel @model {
  id: ID
  type: String
  name: String
  description: String
  collections: [Collection]
}

type Collection {
  id: String
  name: String!
  description: String
  children: [Collection]
}

this will also cause the stack overflow

[dataApi]    at System.Collections.Generic.HashSet`1[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Resize(Int32, Boolean)
[dataApi]    at System.Collections.Generic.HashSet`1[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Resize()
[dataApi]    at System.Collections.Generic.HashSet`1[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].AddIfNotPresent(System.__Canon, Int32 ByRef)
[dataApi]    at System.Collections.Generic.HashSet`1[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].Add(System.__Canon)
[dataApi]    at Azure.DataApiBuilder.Service.GraphQLBuilder.GraphQLUtils.IsBuiltInType(HotChocolate.Language.ITypeNode)
[dataApi]    at Azure.DataApiBuilder.Service.GraphQLBuilder.Mutations.UpdateMutationBuilder+<>c__DisplayClass2_0.<GenerateUpdateInputType>b__1(HotChocolate.Language.FieldDefinitionNode)
[dataApi]    at System.Linq.Enumerable+WhereSelectListIterator`2[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ToList()
[dataApi]    at System.Linq.Enumerable.ToList[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable`1<System.__Canon>)
[dataApi]    at Azure.DataApiBuilder.Service.GraphQLBuilder.Mutations.UpdateMutationBuilder.GenerateUpdateInputType(System.Collections.Generic.Dictionary`2<HotChocolate.Language.NameNode,HotChocolate.Language.InputObjectTypeDefinitionNode>, HotChocolate.Language.ObjectTypeDefinitionNode, HotChocolate.Language.NameNode, System.Collections.Generic.IEnumerable`1<HotChocolate.Language.IHasName>, System.Collections.Generic.IDictionary`2<System.String,Azure.DataApiBuilder.Config.Entity>, Azure.DataApiBuilder.Config.DatabaseType)
[dataApi]    at Azure.DataApiBuilder.Service.GraphQLBuilder.Mutations.UpdateMutationBuilder.GetComplexInputType(System.Collections.Generic.Dictionary`2<HotChocolate.Language.NameNode,HotChocolate.Language.InputObjectTypeDefinitionNode>, System.Collections.Generic.IEnumerable`1<HotChocolate.Language.IHasName>, HotChocolate.Language.FieldDefinitionNode, System.String, HotChocolate.Language.ObjectTypeDefinitionNode, System.Collections.Generic.IDictionary`2<System.String,Azure.DataApiBuilder.Config.Entity>, Azure.DataApiBuilder.Config.DatabaseType)
[dataApi]    at Azure.DataApiBuilder.Service.GraphQLBuilder.Mutations.UpdateMutationBuilder+<>c__DisplayClass2_0.<GenerateUpdateInputType>b__1(HotChocolate.Language.FieldDefinitionNode)
[dataApi]    at System.Linq.Enumerable+WhereSelectListIterator`2[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ToList()
[dataApi]    at System.Linq.Enumerable.ToList[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable`1<System.__Canon>)
[dataApi]    at Azure.DataApiBuilder.Service.GraphQLBuilder.Mutations.UpdateMutationBuilder.GenerateUpdateInputType(System.Collections.Generic.Dictionary`2<HotChocolate.Language.NameNode,HotChocolate.Language.InputObjectTypeDefinitionNode>, HotChocolate.Language.ObjectTypeDefinitionNode, HotChocolate.Language.NameNode, System.Collections.Generic.IEnumerable`1<HotChocolate.Language.IHasName>, System.Collections.Generic.IDictionary`2<System.String,Azure.DataApiBuilder.Config.Entity>, Azure.DataApiBuilder.Config.DatabaseType)
[dataApi]    at Azure.DataApiBuilder.Service.GraphQLBuilder.Mutations.UpdateMutationBuilder.GetComplexInputType(System.Collections.Generic.Dictionary`2<HotChocolate.Language.NameNode,HotChocolate.Language.InputObjectTypeDefinitionNode>, System.Collections.Generic.IEnumerable`1<HotChocolate.Language.IHasName>, HotChocolate.Language.FieldDefinitionNode, System.String, HotChocolate.Language.ObjectTypeDefinitionNode, System.Collections.Generic.IDictionary`2<System.String,Azure.DataApiBuilder.Config.Entity>, Azure.DataApiBuilder.Config.DatabaseType)
[dataApi]    at Azure.DataApiBuilder.Service.GraphQLBuilder.Mutations.UpdateMutationBuilder+<>c__DisplayClass2_0.<GenerateUpdateInputType>b__1(HotChocolate.Language.FieldDefinitionNode)
[dataApi]    at System.Linq.Enumerable+WhereSelectListIterator`2[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e],[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].ToList()
[dataApi]    at System.Linq.Enumerable.ToList[[System.__Canon, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]](System.Collections.Generic.IEnumerable`1<System.__Canon>)
[dataApi]    at Azure.DataApiBuilder.Service.GraphQLBuilder.Mutations.UpdateMutationBuilder.GenerateUpdateInputType(System.Collections.Generic.Dictionary`2<HotChocolate.Language.NameNode,HotChocolate.Language.InputObjectTypeDefinitionNode>, HotChocolate.Language.ObjectTypeDefinitionNode, HotChocolate.Language.NameNode, System.Collections.Generic.IEnumerable`1<HotChocolate.Language.IHasName>, System.Collections.Generic.IDictionary`2<System.String,Azure.DataApiBuilder.Config.Entity>, Azure.DataApiBuilder.Config.DatabaseType)
[dataApi]    at Azure.DataApiBuilder.Service.GraphQLBuilder.Mutations.UpdateMutationBuilder.GetComplexInputType(System.Collections.Generic.Dictionary`2<HotChocolate.Language.NameNode,HotChocolate.Language.InputObjectTypeDefinitionNode>, System.Collections.Generic.IEnumerable`1<HotChocolate.Language.IHasName>, HotChocolate.Language.FieldDefinitionNode, System.String, HotChocolate.Language.ObjectTypeDefinitionNode, System.Collections.Generic.IDictionary`2<System.String,Azure.DataApiBuilder.Config.Entity>, Azure.DataApiBuilder.Config.DatabaseType)
[dataApi]    at Azure.DataApiBuilder.Service.GraphQLBuilder.Mutations.UpdateMutationBuilder+<>c__DisplayClass2_0.<GenerateUpdateInputType>b__1(HotChocolate.Language.FieldDefinitionNode)

maybe being able to specify a max depth for a recursive relationship might prevent this?

@severussundar
Copy link
Contributor

PR #2192 adds protection against circular references and throws an exception. This will prevent engine crashing rather throw helpful error messages to the user.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cosmos graphql mssql pgsql mysql an issue that applies to all relational databases, same as labeling with `mssql` `mysql` and `pgsql` needs discussion
Projects
None yet
Development

No branches or pull requests

9 participants