ChilliCream / ChilliCream/graphql-platform
HotChocolate not detecting syntax error
Nobody has claimed this yet.
- Dominant language
- C#
- Stars
- 5.8k
- Forks
- 810
- Avg merge
- 15h 39m
- Merged PRs (30d)
- 98
Description
Is there an existing issue for this?
- I have searched the existing issues
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
- 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<Animal>(cm => {
cm.AutoMap();
cm.AddKnownType(typeof(Cat));
cm.AddKnownType(typeof(Dog));
});
BsonClassMap.RegisterClassMap<Cat>(cm => {
cm.AutoMap();
});
BsonClassMap.RegisterClassMap<Dog>(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>("person"));
builder.Services.AddControllers();
builder.Services.AddGraphQLServer()
.AddQueryType<PersonLookup>()
.AddType<CatType>()
.AddType<DogType>()
.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<Animal>
{
protected override void Configure(IInterfaceTypeDescriptor<Animal> descriptor)
{
descriptor.Name(nameof(Animal));
}
}
public class CatType : ObjectType<Cat>
{
protected override void Configure(IObjectTypeDescriptor<Cat> descriptor)
{
descriptor.Name(nameof(Cat));
descriptor.Implements<AnimalType>();
descriptor.Field("_t").Type<StringType>().IsProjected().Resolve((context, ct) =>
{
//code won't run without resolver even if it is not used
return nameof(Cat);
});
}
}
public class DogType : ObjectType<Dog>
{
protected override void Configure(IObjectTypeDescriptor<Dog> descriptor)
{
descriptor.Name(nameof(Dog));
descriptor.Implements<AnimalType>();
descriptor.Field("_t").Type<StringType>().IsProjected().Resolve((context, ct) =>
{
return nameof(Dog);
});
}
}
- My sample data in DB looks like this - please note all the fields are in camel case
{
"_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"
}
]
}
- 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
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by comparing the filter visitor and combinator paths shown in the v12 stack trace, especially MongoDbFilterCombinator.cs and FilterVisitor.cs, with the v13 MongoDB paging path in FindFluentPagingContainer.cs. Reproduce the supplied query against both versions and trace when the empty some filter reaches MongoDB. Done means the invalid filter is rejected before database execution, with a covered regression test.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp, graphql, mongodb
- Domain
- api, backend, database
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 32/100