ChilliCream / graphql-platform

Welcome to the home of the Hot Chocolate GraphQL server for .NET, the Strawberry Shake GraphQL client for .NET and Banana Cake Pop the awesome Monaco based GraphQL IDE.
https://chillicream.com
MIT License
5.16k stars 736 forks source link

HotChocolate not detecting syntax error #6300

Open Sonic198 opened 1 year ago

Sonic198 commented 1 year ago

Is there an existing issue for this?

Product

Hot Chocolate

Describe the bug

Hi, If I send following query to graphql v13.2.1 it will try to execute it against DB when in v12.12.0 this throws syntax error.

query MyQuery {
  userProfiles(where: {id: {eq: "6495c776a56246502b2515f2"}, and: {petList: {some: {}}}}) {
    items {
      id
      personProp1
    }
  }
}

Steps to reproduce

  1. I have following code:
    
    //Domain classes
    public class Person
    {
    public string Id { get; set; }
    public int PersonProp1 { get; set; }
    public IEnumerable<Animal> PetList { get; set; }
    }
    public abstract class Animal
    {
    public int AnimalProp1 { get; set; }
    public string AnimalProp2 { get; set; }
    }
    public class Cat : Animal
    {
    public int CatProp1 { get; set; }
    public string CatProp2 { get; set; }
    }
    public class Dog : Animal
    {
    public int DogProp1 { get; set; }
    public string DogProp2 { get; set; }
    }

//Program.cs var builder = WebApplication.CreateBuilder(args);

var pack = new ConventionPack { new CamelCaseElementNameConvention(), new StringIdStoredAsObjectIdConvention(), new IgnoreIfNullConvention(true), new IgnoreExtraElementsConvention(true) }; ConventionRegistry.Register("custom", pack, t => true);

BsonClassMap.RegisterClassMap(cm => { cm.AutoMap(); cm.AddKnownType(typeof(Cat)); cm.AddKnownType(typeof(Dog)); }); BsonClassMap.RegisterClassMap(cm => { cm.AutoMap(); }); BsonClassMap.RegisterClassMap(cm => { cm.AutoMap(); });

var connectionString = builder.Configuration.GetConnectionString("MongoDb"); var url = new MongoUrl(connectionString); var settings = MongoClientSettings.FromUrl(url);

var client = new MongoClient(settings); var database = client.GetDatabase(url.DatabaseName);

builder.Services.AddSingleton(client); builder.Services.AddSingleton(database); builder.Services.AddSingleton(database.GetCollection("person"));

builder.Services.AddControllers();

builder.Services.AddGraphQLServer() .AddQueryType() .AddType() .AddType() .ModifyOptions(opt => opt.RemoveUnreachableTypes = true) .AddMongoDbPagingProviders() .AddMongoDbProjections() .AddMongoDbFiltering() .AddMongoDbSorting() .InitializeOnStartup();

var app = builder.Build();

app.MapGraphQL("/graphql");

app.Run();

//Schema definition public class PersonLookup { private const int _maxPageSize = 1000;

[UseOffsetPaging(IncludeTotalCount = true, MaxPageSize = _maxPageSize)]
[UseProjection]
[UseFiltering]
[UseSorting]
public async Task<IExecutable<Person>> UserProfiles([Service] IMongoCollection<Person> collection)
{
    return collection.AsExecutable();
}

}

public class AnimalType : InterfaceType { protected override void Configure(IInterfaceTypeDescriptor descriptor) { descriptor.Name(nameof(Animal)); } }

public class CatType : ObjectType { protected override void Configure(IObjectTypeDescriptor descriptor) { descriptor.Name(nameof(Cat)); descriptor.Implements(); descriptor.Field("_t").Type().IsProjected().Resolve((context, ct) => { //code won't run without resolver even if it is not used return nameof(Cat); }); } }

public class DogType : ObjectType { protected override void Configure(IObjectTypeDescriptor descriptor) { descriptor.Name(nameof(Dog)); descriptor.Implements(); descriptor.Field("_t").Type().IsProjected().Resolve((context, ct) => { return nameof(Dog); }); } }

2. My sample data in DB looks like this - please note all the fields are in camel case
```json
{
    "_id" : ObjectId("6495c776a56246502b2515f2"),
    "personProp1" : 6,
    "petList" : [
        {
            "_t" : "Dog",
            "animalProp1" : 5,
            "animalProp2" : "Animal Prop 8",
            "dogProp1" : 1,
            "dogProp2" : "Dog Prop 4"
        },
        {
            "_t" : "Dog",
            "animalProp1" : 5,
            "animalProp2" : "Animal Prop 8",
            "dogProp1" : 1,
            "dogProp2" : "Dog Prop 5"
        },
        {
            "_t" : "Cat",
            "animalProp1" : 6,
            "animalProp2" : "Animal Prop 5",
            "catProp1" : 3,
            "catProp2" : "Cat Prop 1"
        }
    ]
}
  1. Query which use to get data
    query MyQuery {
    userProfiles(where: {id: {eq: "6495c776a56246502b2515f2"}, and: {petList: {some: {}}}}) {
    items {
      id
      personProp1
    }
    }
    }

Relevant log output

//output from v13.2.1
{
  "errors": [
    {
      "message": "Unexpected Execution Error",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "userProfiles"
      ],
      "extensions": {
        "message": "Command find failed: $and/$or/$nor must be a nonempty array.",
        "stackTrace": "   at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol`1.ProcessResponse(ConnectionId connectionId, CommandMessage responseMessage)\r\n   at MongoDB.Driver.Core.WireProtocol.CommandUsingCommandMessageWireProtocol`1.ExecuteAsync(IConnection connection, CancellationToken cancellationToken)\r\n   at MongoDB.Driver.Core.Servers.Server.ServerChannel.ExecuteProtocolAsync[TResult](IWireProtocol`1 protocol, ICoreSession session, CancellationToken cancellationToken)\r\n   at MongoDB.Driver.Core.Operations.RetryableReadOperationExecutor.ExecuteAsync[TResult](IRetryableReadOperation`1 operation, RetryableReadContext context, CancellationToken cancellationToken)\r\n   at MongoDB.Driver.Core.Operations.ReadCommandOperation`1.ExecuteAsync(RetryableReadContext context, CancellationToken cancellationToken)\r\n   at MongoDB.Driver.Core.Operations.FindOperation`1.ExecuteAsync(RetryableReadContext context, CancellationToken cancellationToken)\r\n   at MongoDB.Driver.Core.Operations.FindOperation`1.ExecuteAsync(IReadBinding binding, CancellationToken cancellationToken)\r\n   at MongoDB.Driver.OperationExecutor.ExecuteReadOperationAsync[TResult](IReadBinding binding, IReadOperation`1 operation, CancellationToken cancellationToken)\r\n   at MongoDB.Driver.MongoCollectionImpl`1.ExecuteReadOperationAsync[TResult](IClientSessionHandle session, IReadOperation`1 operation, ReadPreference readPreference, CancellationToken cancellationToken)\r\n   at MongoDB.Driver.MongoCollectionImpl`1.UsingImplicitSessionAsync[TResult](Func`2 funcAsync, CancellationToken cancellationToken)\r\n   at MongoDB.Driver.IAsyncCursorSourceExtensions.ToListAsync[TDocument](IAsyncCursorSource`1 source, CancellationToken cancellationToken)\r\n   at HotChocolate.Data.MongoDb.Paging.FindFluentPagingContainer`1.ToListAsync(CancellationToken cancellationToken) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\MongoDb\\src\\Data\\Paging\\FindFluentPagingContainer.cs:line 53\r\n   at HotChocolate.Data.MongoDb.Paging.MongoOffsetPagination`1.ExecuteAsync(IMongoPagingContainer`1 query, CancellationToken cancellationToken) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\MongoDb\\src\\Data\\Paging\\MongoOffsetPagination.cs:line 26\r\n   at HotChocolate.Types.Pagination.OffsetPaginationAlgorithm`2.ApplyPaginationAsync(TQuery query, OffsetPagingArguments arguments, Nullable`1 totalCount, CancellationToken cancellationToken) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Core\\src\\Types.OffsetPagination\\OffsetPaginationAlgorithm.cs:line 64\r\n   at HotChocolate.Data.MongoDb.Paging.MongoDbOffsetPagingHandler`1.SliceAsync(IResolverContext context, Object source, OffsetPagingArguments arguments) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\MongoDb\\src\\Data\\Paging\\MongoDbOffsetPagingHandler.cs:line 20\r\n   at HotChocolate.Types.Pagination.OffsetPagingHandler.HotChocolate.Types.Pagination.IPagingHandler.SliceAsync(IResolverContext context, Object source) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Core\\src\\Types.OffsetPagination\\OffsetPagingHandler.cs:line 87\r\n   at HotChocolate.Types.Pagination.PagingMiddleware.InvokeAsync(IMiddlewareContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Core\\src\\Types\\Types\\Pagination\\PagingMiddleware.cs:line 30\r\n   at HotChocolate.Utilities.MiddlewareCompiler`1.ExpressionHelper.AwaitTaskHelper(Task task) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Utilities\\src\\Utilities\\MiddlewareCompiler.cs:line 185\r\n   at HotChocolate.Execution.Processing.Tasks.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Core\\src\\Execution\\Processing\\Tasks\\ResolverTask.Execute.cs:line 134\r\n   at HotChocolate.Execution.Processing.Tasks.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Core\\src\\Execution\\Processing\\Tasks\\ResolverTask.Execute.cs:line 113"
      }
    }
  ],
  "data": {
    "userProfiles": null
  }
}

//output from v12.12.0
{
  "errors": [
    {
      "message": "Unexpected Execution Error",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "userProfiles"
      ],
      "extensions": {
        "message": "MongoDbCombinator HotChocolate.Data.MongoDb.Filters.MongoDbFilterCombinator could not combine expressions. There were no expressions to combine.",
        "stackTrace": "   at HotChocolate.Data.MongoDb.Filters.MongoDbFilterCombinator.TryCombineOperations(MongoDbFilterVisitorContext context, Queue`1 operations, FilterCombinator combinator, MongoDbFilterDefinition& combined) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\MongoDb\\src\\Data\\Filters\\MongoDbFilterCombinator.cs:line 23\r\n   at HotChocolate.Data.Filters.FilterVisitor`2.TryCombineOperations(TContext context, Queue`1 operations, FilterCombinator combinator, T& combined) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Data\\src\\Data\\Filters\\Visitor\\FilterVisitor.cs:line 58\r\n   at HotChocolate.Data.Filters.FilterVisitorBase`2.Leave(ObjectValueNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Data\\src\\Data\\Filters\\Visitor\\FilterVisitorBase`2.cs:line 38\r\n   at HotChocolate.Language.Visitors.SyntaxWalker`1.Leave(ISyntaxNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxWalker~1.Leave.cs:line 46\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.Visit[T,P](T node, P parent, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.cs:line 83\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ObjectFieldNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 466\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ISyntaxNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 30\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.Visit[T,P](T node, P parent, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.cs:line 73\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ObjectValueNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 448\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ISyntaxNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 28\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.Visit[T,P](T node, P parent, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.cs:line 73\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ObjectFieldNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 466\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ISyntaxNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 30\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.Visit[T,P](T node, P parent, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.cs:line 73\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ObjectValueNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 448\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ISyntaxNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 28\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.Visit[T,P](T node, P parent, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.cs:line 73\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ObjectFieldNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 466\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ISyntaxNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 30\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.Visit[T,P](T node, P parent, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.cs:line 73\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ObjectValueNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 448\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.VisitChildren(ISyntaxNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.VisitationMap.cs:line 28\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.Visit[T,P](T node, P parent, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.cs:line 73\r\n   at HotChocolate.Language.Visitors.SyntaxVisitor`1.Visit(ISyntaxNode node, TContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Language\\src\\Language.Visitors\\SyntaxVisitor~1.cs:line 58\r\n   at HotChocolate.Data.MongoDb.Filters.MongoDbFilterProvider.<>c__DisplayClass5_0`1.<<CreateExecutor>g__ExecuteAsync|1>d.MoveNext() in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\MongoDb\\src\\Data\\Filters\\MongoDbFilterProvider.cs:line 53\r\n--- End of stack trace from previous location ---\r\n   at HotChocolate.Data.MongoDb.MongoDbProjectionProvider.<CreateExecutor>g__ExecuteAsync|2_1[TEntityType](FieldDelegate next, IMiddlewareContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\MongoDb\\src\\Data\\Projections\\Convention\\MongoDbProjectionProvider.cs:line 36\r\n   at HotChocolate.Types.Pagination.PagingMiddleware.InvokeAsync(IMiddlewareContext context) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Core\\src\\Types\\Types\\Pagination\\PagingMiddleware.cs:line 26\r\n   at HotChocolate.Utilities.MiddlewareCompiler`1.ExpressionHelper.AwaitTaskHelper(Task task) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Utilities\\src\\Utilities\\MiddlewareCompiler.cs:line 167\r\n   at HotChocolate.Execution.Processing.Tasks.ResolverTask.ExecuteResolverPipelineAsync(CancellationToken cancellationToken) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Core\\src\\Execution\\Processing\\Tasks\\ResolverTask.Execute.cs:line 95\r\n   at HotChocolate.Execution.Processing.Tasks.ResolverTask.TryExecuteAsync(CancellationToken cancellationToken) in C:\\D\\FDRRepo\\_TESTS\\graphql-platform\\src\\HotChocolate\\Core\\src\\Execution\\Processing\\Tasks\\ResolverTask.Execute.cs:line 73"
      }
    }
  ],
  "data": {
    "userProfiles": null
  }
}

Additional Context?

No response

Version

13.2.1

michaelstaib commented 1 year ago

This is not a syntax error. The syntax is valid GraphQL. However the translation layer should semantically analyse this and throw a proper exception.

cc @PascalSenn