diff --git a/DataGateway.Service.Tests/CosmosTests/MutationTests.cs b/DataGateway.Service.Tests/CosmosTests/MutationTests.cs index 703839846c..9621df58e9 100644 --- a/DataGateway.Service.Tests/CosmosTests/MutationTests.cs +++ b/DataGateway.Service.Tests/CosmosTests/MutationTests.cs @@ -10,23 +10,23 @@ public class MutationTests : TestBase { private static readonly string _containerName = Guid.NewGuid().ToString(); private static readonly string _mutationStringFormat = @" - mutation - {{ - addPlanet (id: ""{0}"", name: ""{1}"") - {{ + mutation ($id: String, $name: String) + { + addPlanet (id: $id, name: $name) + { id name - }} - }}"; + } + }"; private static readonly string _mutationDeleteItemStringFormat = @" - mutation - {{ - deletePlanet (id: ""{0}"") - {{ + mutation ($id: String) + { + deletePlanet (id: $id) + { id name - }} - }}"; + } + }"; /// /// Executes once for the test class. @@ -44,22 +44,76 @@ public static void TestFixtureSetup(TestContext context) } [TestMethod] - public async Task TestMutationRun() + public async Task CanCreateItemWithVariables() { // Run mutation Add planet; - String id = Guid.NewGuid().ToString(); - string mutation = String.Format(_mutationStringFormat, id, "test_name"); - JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", mutation); + string id = Guid.NewGuid().ToString(); + JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", _mutationStringFormat, new() { { "id", id }, { "name", "test_name" } }); // Validate results - Assert.IsFalse(response.ToString().Contains("Error")); + Assert.AreEqual(id, response.GetProperty("id").GetString()); + } + + [TestMethod] + public async Task CanDeleteItemWithVariables() + { + // Pop an item in to delete + string id = Guid.NewGuid().ToString(); + _ = await ExecuteGraphQLRequestAsync("addPlanet", _mutationStringFormat, new() { { "id", id }, { "name", "test_name" } }); + + // Run mutation delete item; + JsonElement response = await ExecuteGraphQLRequestAsync("deletePlanet", _mutationDeleteItemStringFormat, new() { { "id", id } }); + + // Validate results + Assert.IsNull(response.GetProperty("id").GetString()); + } + + [TestMethod] + public async Task CanCreateItemWithoutVariables() + { + // Run mutation Add planet; + string id = Guid.NewGuid().ToString(); + const string name = "test_name"; + string mutation = $@" +mutation {{ + addPlanet (id: ""{id}"", name: ""{name}"") {{ + id + name + }} +}}"; + JsonElement response = await ExecuteGraphQLRequestAsync("addPlanet", mutation, new()); + + // Validate results + Assert.AreEqual(id, response.GetProperty("id").GetString()); + } + + [TestMethod] + public async Task CanDeleteItemWithoutVariables() + { + // Pop an item in to delete + string id = Guid.NewGuid().ToString(); + const string name = "test_name"; + string addMutation = $@" +mutation {{ + addPlanet (id: ""{id}"", name: ""{name}"") {{ + id + name + }} +}}"; + _ = await ExecuteGraphQLRequestAsync("addPlanet", addMutation, new()); // Run mutation delete item; - mutation = String.Format(_mutationDeleteItemStringFormat, id); - response = await ExecuteGraphQLRequestAsync("deletePlanet", mutation); + string deleteMutation = $@" +mutation {{ + deletePlanet (id: ""{id}"") {{ + id + name + }} +}}"; + JsonElement response = await ExecuteGraphQLRequestAsync("deletePlanet", deleteMutation, new()); // Validate results - Assert.IsFalse(response.ToString().Contains("Error")); + Assert.IsNull(response.GetProperty("id").GetString()); } /// diff --git a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs index ec6b2caae8..8d111d7c1f 100644 --- a/DataGateway.Service.Tests/CosmosTests/QueryTests.cs +++ b/DataGateway.Service.Tests/CosmosTests/QueryTests.cs @@ -11,15 +11,25 @@ public class QueryTests : TestBase { private static readonly string _containerName = Guid.NewGuid().ToString(); - public static readonly string PlanetByIdQueryFormat = @"{{planetById (id: {0}){{ id, name}} }}"; + public static readonly string PlanetByIdQueryFormat = @" +query ($id: ID) { + planetById (id: $id) { + id + name + } +}"; public static readonly string PlanetListQuery = @"{planetList{ id, name}}"; public static readonly string PlanetConnectionQueryStringFormat = @" - {{planets (first: {0}, after: {1}){{ - items{{ id name }} - endCursor - hasNextPage - }} - }}"; +query ($first: Int!, $after: String) { + planets (first: $first, after: $after) { + items { + id + name + } + endCursor + hasNextPage + } +}"; private static List _idList; @@ -39,14 +49,14 @@ public static void TestFixtureSetup(TestContext context) } [TestMethod] - public async Task TestSimpleQuery() + public async Task GetByPrimaryKeyWithVariables() { // Run query - string query = string.Format(PlanetByIdQueryFormat, arg0: "\"" + _idList[0] + "\""); - JsonElement response = await ExecuteGraphQLRequestAsync("planetById", query); + string id = _idList[0]; + JsonElement response = await ExecuteGraphQLRequestAsync("planetById", PlanetByIdQueryFormat, new() { { "id", id } }); // Validate results - Assert.IsFalse(response.ToString().Contains("Error")); + Assert.AreEqual(id, response.GetProperty("id").GetString()); } /// @@ -54,27 +64,72 @@ public async Task TestSimpleQuery() /// running a paginated query that gets n items per page. We then make sure the number of documents match /// [TestMethod] - public async Task TestPaginatedQuery() + public async Task GetPaginatedWithVariables() { // Run query JsonElement response = await ExecuteGraphQLRequestAsync("planetList", PlanetListQuery); int actualElements = response.GetArrayLength(); // Run paginated query int totalElementsFromPaginatedQuery = 0; - string continuationToken = "null"; + string continuationToken = null; const int pagesize = 5; do { - if (continuationToken != "null") - { - // We need to append an escape quote to continuation token because of the way we are using string.format - // for generating the graphql paginated query stringformat for this test. - continuationToken = "\"" + continuationToken + "\""; - } - - string paginatedQuery = string.Format(PlanetConnectionQueryStringFormat, arg0: pagesize, arg1: continuationToken); - JsonElement page = await ExecuteGraphQLRequestAsync("planets", paginatedQuery); + JsonElement page = await ExecuteGraphQLRequestAsync("planets", PlanetConnectionQueryStringFormat, new() { { "first", pagesize }, { "after", continuationToken } }); + JsonElement continuation = page.GetProperty("endCursor"); + continuationToken = continuation.ToString(); + totalElementsFromPaginatedQuery += page.GetProperty("items").GetArrayLength(); + } while (!string.IsNullOrEmpty(continuationToken)); + + // Validate results + Assert.AreEqual(actualElements, totalElementsFromPaginatedQuery); + } + + [TestMethod] + public async Task GetByPrimaryKeyWithoutVariables() + { + // Run query + string id = _idList[0]; + string query = @$" +query {{ + planetById (id: ""{id}"") {{ + id + name + }} +}}"; + JsonElement response = await ExecuteGraphQLRequestAsync("planetById", query); + + // Validate results + Assert.AreEqual(id, response.GetProperty("id").GetString()); + } + + [TestMethod] + public async Task GetPaginatedWithoutVariables() + { + // Run query + JsonElement response = await ExecuteGraphQLRequestAsync("planetList", PlanetListQuery); + int actualElements = response.GetArrayLength(); + // Run paginated query + int totalElementsFromPaginatedQuery = 0; + string continuationToken = null; + const int pagesize = 5; + + do + { + string planetConnectionQueryStringFormat = @$" +query {{ + planets (first: {pagesize}, after: {(continuationToken == null ? "null" : "\"" + continuationToken + "\"")}) {{ + items {{ + id + name + }} + endCursor + hasNextPage + }} +}}"; + + JsonElement page = await ExecuteGraphQLRequestAsync("planets", planetConnectionQueryStringFormat, new()); JsonElement continuation = page.GetProperty("endCursor"); continuationToken = continuation.ToString(); totalElementsFromPaginatedQuery += page.GetProperty("items").GetArrayLength(); diff --git a/DataGateway.Service.Tests/CosmosTests/TestBase.cs b/DataGateway.Service.Tests/CosmosTests/TestBase.cs index 60ea2fc06e..e793714477 100644 --- a/DataGateway.Service.Tests/CosmosTests/TestBase.cs +++ b/DataGateway.Service.Tests/CosmosTests/TestBase.cs @@ -34,7 +34,39 @@ public static void Init(TestContext context) { _clientProvider = new CosmosClientProvider(TestHelper.DataGatewayConfig); _metadataStoreProvider = new MetadataStoreProviderForTest(); - string jsonString = File.ReadAllText("schema.gql"); + string jsonString = @" +type Query { + characterList: [Character] + characterById (id : ID!): Character + planetById (id: ID! = 1): Planet + getPlanet(id: ID, name: String): Planet + planetList: [Planet] + planets(first: Int, after: String): PlanetConnection +} + +type Mutation { + addPlanet(id: String, name: String): Planet + deletePlanet(id: String): Planet +} + +type PlanetConnection { + items: [Planet] + endCursor: String + hasNextPage: Boolean +} + +type Character { + id : ID, + name : String, + type: String, + homePlanet: Int, + primaryFunction: String +} + +type Planet { + id : ID, + name : String +}"; _metadataStoreProvider.GraphQLSchema = jsonString; _queryEngine = new CosmosQueryEngine(_clientProvider, _metadataStoreProvider); _mutationEngine = new CosmosMutationEngine(_clientProvider, _metadataStoreProvider); @@ -125,18 +157,27 @@ internal static void RegisterGraphQLType(string id, /// Executes the GraphQL request and returns the results /// /// Name of the GraphQL query/mutation - /// The GraphQL query/mutation + /// The GraphQL query/mutation + /// Variables to be included in the GraphQL request. If null, no variables property is included in the request, to pass an empty object provide an empty dictionary /// - internal static async Task ExecuteGraphQLRequestAsync(string queryName, string graphQLQuery) + internal static async Task ExecuteGraphQLRequestAsync(string queryName, string query, Dictionary variables = null) { - string queryJson = JObject.FromObject(new - { - query = graphQLQuery - }).ToString(); + string queryJson = variables == null ? + JObject.FromObject(new { query }).ToString() : + JObject.FromObject(new + { + query, + variables + }).ToString(); _controller.ControllerContext.HttpContext = GetHttpContextWithBody(queryJson); JsonElement graphQLResult = await _controller.PostAsync(); + + if (graphQLResult.TryGetProperty("errors", out JsonElement errors)) + { + Assert.Fail(errors.GetRawText()); + } + return graphQLResult.GetProperty("data").GetProperty(queryName); } - } } diff --git a/DataGateway.Service.Tests/SqlTests/MsSqlGraphQLQueryTests.cs b/DataGateway.Service.Tests/SqlTests/MsSqlGraphQLQueryTests.cs index 9e1888cc36..53c84ed6ea 100644 --- a/DataGateway.Service.Tests/SqlTests/MsSqlGraphQLQueryTests.cs +++ b/DataGateway.Service.Tests/SqlTests/MsSqlGraphQLQueryTests.cs @@ -58,6 +58,24 @@ public async Task MultipleResultQuery() SqlTestHelper.PerformTestEqualJsonStrings(expected, actual); } + [TestMethod] + public async Task MultipleResultQueryWithVariables() + { + string graphQLQueryName = "getBooks"; + string graphQLQuery = @"query ($first: Int!) { + getBooks(first: $first) { + id + title + } + }"; + string msSqlQuery = $"SELECT id, title FROM books ORDER BY id FOR JSON PATH, INCLUDE_NULL_VALUES"; + + string actual = await GetGraphQLResultAsync(graphQLQuery, graphQLQueryName, _graphQLController, new() { { "first", 100 } }); + string expected = await GetDatabaseResultAsync(msSqlQuery); + + SqlTestHelper.PerformTestEqualJsonStrings(expected, actual); + } + /// /// Gets array of results for querying more than one item. /// @@ -295,6 +313,75 @@ ORDER BY [id] SqlTestHelper.PerformTestEqualJsonStrings(expected, actual); } + /// + /// This deeply nests a many-to-many join multiple times to show that + /// it still results in a valid query. + /// + /// + [TestMethod] + public async Task DeeplyNestedManyToManyJoinQueryWithVariables() + { + string graphQLQueryName = "getBooks"; + string graphQLQuery = @"query ($first: Int) { + getBooks(first: $first) { + title + authors(first: $first) { + name + books(first: $first) { + title + authors(first: $first) { + name + } + } + } + } + }"; + + string msSqlQuery = @" + SELECT TOP 100 [table0].[title] AS [title], + JSON_QUERY(COALESCE([table6_subq].[data], '[]')) AS [authors] + FROM [books] AS [table0] + OUTER APPLY ( + SELECT TOP 100 [table6].[name] AS [name], + JSON_QUERY(COALESCE([table7_subq].[data], '[]')) AS [books] + FROM [authors] AS [table6] + INNER JOIN [book_author_link] AS [table11] ON [table11].[author_id] = [table6].[id] + OUTER APPLY ( + SELECT TOP 100 [table7].[title] AS [title], + JSON_QUERY(COALESCE([table8_subq].[data], '[]')) AS [authors] + FROM [books] AS [table7] + INNER JOIN [book_author_link] AS [table10] ON [table10].[book_id] = [table7].[id] + OUTER APPLY ( + SELECT TOP 100 [table8].[name] AS [name] + FROM [authors] AS [table8] + INNER JOIN [book_author_link] AS [table9] ON [table9].[author_id] = [table8].[id] + WHERE [table7].[id] = [table9].[book_id] + ORDER BY [id] + FOR JSON PATH, + INCLUDE_NULL_VALUES + ) AS [table8_subq]([data]) + WHERE [table6].[id] = [table10].[author_id] + ORDER BY [id] + FOR JSON PATH, + INCLUDE_NULL_VALUES + ) AS [table7_subq]([data]) + WHERE [table0].[id] = [table11].[book_id] + ORDER BY [id] + FOR JSON PATH, + INCLUDE_NULL_VALUES + ) AS [table6_subq]([data]) + WHERE 1 = 1 + ORDER BY [id] + FOR JSON PATH, + INCLUDE_NULL_VALUES + "; + + string actual = await GetGraphQLResultAsync(graphQLQuery, graphQLQueryName, _graphQLController, new() { { "first", 100 } }); + string expected = await GetDatabaseResultAsync(msSqlQuery); + + SqlTestHelper.PerformTestEqualJsonStrings(expected, actual); + } + [TestMethod] public async Task QueryWithSingleColumnPrimaryKey() { diff --git a/DataGateway.Service.Tests/SqlTests/MySqlGraphQLQueryTests.cs b/DataGateway.Service.Tests/SqlTests/MySqlGraphQLQueryTests.cs index 09c9cb9667..6ea4d93f95 100644 --- a/DataGateway.Service.Tests/SqlTests/MySqlGraphQLQueryTests.cs +++ b/DataGateway.Service.Tests/SqlTests/MySqlGraphQLQueryTests.cs @@ -60,6 +60,32 @@ ORDER BY `table0`.`id` SqlTestHelper.PerformTestEqualJsonStrings(expected, actual); } + [TestMethod] + public async Task MultipleResultQueryWithVariables() + { + string graphQLQueryName = "getBooks"; + string graphQLQuery = @"query ($first: Int!) { + getBooks(first: $first) { + id + title + } + }"; + string mySqlQuery = @" + SELECT COALESCE(JSON_ARRAYAGG(JSON_OBJECT('id', `subq1`.`id`, 'title', `subq1`.`title`)), '[]') AS `data` + FROM + (SELECT `table0`.`id` AS `id`, + `table0`.`title` AS `title` + FROM `books` AS `table0` + WHERE 1 = 1 + ORDER BY `table0`.`id` + LIMIT 100) AS `subq1`"; + + string actual = await GetGraphQLResultAsync(graphQLQuery, graphQLQueryName, _graphQLController, new() { { "first", 100 } }); + string expected = await GetDatabaseResultAsync(mySqlQuery); + + SqlTestHelper.PerformTestEqualJsonStrings(expected, actual); + } + [TestMethod] public async Task MultipleResultJoinQuery() { diff --git a/DataGateway.Service.Tests/SqlTests/PostgreSqlGraphQLQueryTests.cs b/DataGateway.Service.Tests/SqlTests/PostgreSqlGraphQLQueryTests.cs index 167a0537be..3d7f39a092 100644 --- a/DataGateway.Service.Tests/SqlTests/PostgreSqlGraphQLQueryTests.cs +++ b/DataGateway.Service.Tests/SqlTests/PostgreSqlGraphQLQueryTests.cs @@ -52,6 +52,24 @@ public async Task MultipleResultQuery() SqlTestHelper.PerformTestEqualJsonStrings(expected, actual); } + [TestMethod] + public async Task MultipleResultQueryWithVariables() + { + string graphQLQueryName = "getBooks"; + string graphQLQuery = @"query ($first: Int!) { + getBooks(first: $first) { + id + title + } + }"; + string postgresQuery = $"SELECT json_agg(to_jsonb(table0)) FROM (SELECT id, title FROM books ORDER BY id) as table0 LIMIT 100"; + + string actual = await GetGraphQLResultAsync(graphQLQuery, graphQLQueryName, _graphQLController, new() { { "first", 100 } }); + string expected = await GetDatabaseResultAsync(postgresQuery); + + SqlTestHelper.PerformTestEqualJsonStrings(expected, actual); + } + [TestMethod] public async Task MultipleResultJoinQuery() { diff --git a/DataGateway.Service.Tests/SqlTests/SqlTestBase.cs b/DataGateway.Service.Tests/SqlTests/SqlTestBase.cs index efe95afc06..ed271ae8d1 100644 --- a/DataGateway.Service.Tests/SqlTests/SqlTestBase.cs +++ b/DataGateway.Service.Tests/SqlTests/SqlTestBase.cs @@ -299,10 +299,11 @@ protected static void ConfigureRestController( /// /// /// + /// Variables to be included in the GraphQL request. If null, no variables property is included in the request, to pass an empty object provide an empty dictionary /// string in JSON format - protected static async Task GetGraphQLResultAsync(string graphQLQuery, string graphQLQueryName, GraphQLController graphQLController) + protected static async Task GetGraphQLResultAsync(string graphQLQuery, string graphQLQueryName, GraphQLController graphQLController, Dictionary variables = null) { - JsonElement graphQLResult = await GetGraphQLControllerResultAsync(graphQLQuery, graphQLQueryName, graphQLController); + JsonElement graphQLResult = await GetGraphQLControllerResultAsync(graphQLQuery, graphQLQueryName, graphQLController, variables); Console.WriteLine(graphQLResult.ToString()); JsonElement graphQLResultData = graphQLResult.GetProperty("data").GetProperty(graphQLQueryName); @@ -314,16 +315,20 @@ protected static async Task GetGraphQLResultAsync(string graphQLQuery, s /// Sends graphQL query through graphQL service, consisting of gql engine processing (resolvers, object serialization) /// returning the result as a JsonDocument /// - /// + /// /// /// + /// Variables to be included in the GraphQL request. If null, no variables property is included in the request, to pass an empty object provide an empty dictionary /// JsonDocument - protected static async Task GetGraphQLControllerResultAsync(string graphQLQuery, string graphQLQueryName, GraphQLController graphQLController) + protected static async Task GetGraphQLControllerResultAsync(string query, string graphQLQueryName, GraphQLController graphQLController, Dictionary variables = null) { - string graphqlQueryJson = JObject.FromObject(new - { - query = graphQLQuery - }).ToString(); + string graphqlQueryJson = variables == null ? + JObject.FromObject(new { query }).ToString() : + JObject.FromObject(new + { + query, + variables + }).ToString(); Console.WriteLine(graphqlQueryJson); diff --git a/DataGateway.Service/Resolvers/CosmosQueryStructure.cs b/DataGateway.Service/Resolvers/CosmosQueryStructure.cs index e341abb7d6..a54a301a59 100644 --- a/DataGateway.Service/Resolvers/CosmosQueryStructure.cs +++ b/DataGateway.Service/Resolvers/CosmosQueryStructure.cs @@ -17,7 +17,7 @@ public class CosmosQueryStructure : BaseSqlQueryStructure public string Container { get; internal set; } public string Database { get; internal set; } public string? Continuation { get; internal set; } - public long MaxItemCount { get; internal set; } + public int MaxItemCount { get; internal set; } public CosmosQueryStructure(IMiddlewareContext context, IDictionary parameters, @@ -59,7 +59,7 @@ private void Init(IDictionary queryParams) // TODO: Revisit 'first' while adding support for TOP queries if (parameter.Key == "first") { - MaxItemCount = (long)parameter.Value; + MaxItemCount = (int)parameter.Value; continue; } diff --git a/DataGateway.Service/Resolvers/Sql Query Structures/SqlQueryStructure.cs b/DataGateway.Service/Resolvers/Sql Query Structures/SqlQueryStructure.cs index 3f0e1733cc..a08a52c9a0 100644 --- a/DataGateway.Service/Resolvers/Sql Query Structures/SqlQueryStructure.cs +++ b/DataGateway.Service/Resolvers/Sql Query Structures/SqlQueryStructure.cs @@ -230,7 +230,7 @@ IncrementingInteger counter if (firstObject != null) { // due to the way parameters get resolved, - long first = (long)firstObject; + int first = (int)firstObject; if (first <= 0) { @@ -474,12 +474,13 @@ void AddGraphQLFields(IReadOnlyList Selections) { IObjectField? subschemaField = _underlyingFieldType.Fields[fieldName]; - IDictionary subqueryParams = ResolverMiddleware.GetParametersFromSchemaAndQueryFields(subschemaField, field); if (_ctx == null) { - throw new InvalidOperationException("No GraphQL context exists"); + throw new DataGatewayException("No GraphQL context exists", HttpStatusCode.InternalServerError, DataGatewayException.SubStatusCodes.UnexpectedError); } + IDictionary subqueryParams = ResolverMiddleware.GetParametersFromSchemaAndQueryFields(subschemaField, field, _ctx.Variables); + SqlQueryStructure subquery = new(_ctx, subqueryParams, MetadataStoreProvider, subschemaField, field, Counter); if (PaginationMetadata.IsPaginated) diff --git a/DataGateway.Service/Services/GraphQLService.cs b/DataGateway.Service/Services/GraphQLService.cs index 329417eaba..fecd8ae27b 100644 --- a/DataGateway.Service/Services/GraphQLService.cs +++ b/DataGateway.Service/Services/GraphQLService.cs @@ -9,6 +9,7 @@ using HotChocolate.Execution.Configuration; using HotChocolate.Types; using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; namespace Azure.DataGateway.Service.Services { @@ -131,6 +132,15 @@ private static IQueryRequest CompileRequest(string requestBody, Dictionary>(variables.ToString()!) + ); + } + // Individually adds each property to requestBuilder if they are provided. // Avoids using SetProperties() as it detrimentally overwrites // any properties other Middleware sets. diff --git a/DataGateway.Service/Services/ResolverMiddleware.cs b/DataGateway.Service/Services/ResolverMiddleware.cs index eb5ddba4a6..597ed0d523 100644 --- a/DataGateway.Service/Services/ResolverMiddleware.cs +++ b/DataGateway.Service/Services/ResolverMiddleware.cs @@ -5,6 +5,7 @@ using System.Threading.Tasks; using Azure.DataGateway.Service.Models; using Azure.DataGateway.Service.Resolvers; +using HotChocolate.Execution; using HotChocolate.Language; using HotChocolate.Resolvers; using HotChocolate.Types; @@ -119,17 +120,14 @@ protected static bool IsInnerObject(IMiddlewareContext context) return context.Selection.Field.Type.IsObjectType() && context.Parent() != default; } - static private object ArgumentValue(IValueNode value) + static private object ArgumentValue(IValueNode value, IVariableValueCollection variables) { - if (value.Kind == SyntaxKind.IntValue) + return value.Kind switch { - IntValueNode intValue = (IntValueNode)value; - return intValue.ToInt64(); - } - else - { - return value.Value; - } + SyntaxKind.IntValue => ((IntValueNode)value).ToInt32(), + SyntaxKind.Variable => variables.GetVariable(((VariableNode)value).Value), + _ => value.Value + }; } /// @@ -137,7 +135,7 @@ static private object ArgumentValue(IValueNode value) /// Extracts defualt parameter values from the schema or null if no default /// Overrides default values with actual values of parameters provided /// - public static IDictionary GetParametersFromSchemaAndQueryFields(IObjectField schema, FieldNode query) + public static IDictionary GetParametersFromSchemaAndQueryFields(IObjectField schema, FieldNode query, IVariableValueCollection variables) { IDictionary parameters = new Dictionary(); @@ -151,7 +149,7 @@ public static IDictionary GetParametersFromSchemaAndQueryFields( } else { - parameters.Add(argument.Name.Value, ArgumentValue(argument.DefaultValue)); + parameters.Add(argument.Name.Value, ArgumentValue(argument.DefaultValue, variables)); } } @@ -159,7 +157,7 @@ public static IDictionary GetParametersFromSchemaAndQueryFields( IReadOnlyList passedArguments = query.Arguments; foreach (ArgumentNode argument in passedArguments) { - parameters[argument.Name.Value] = ArgumentValue(argument.Value); + parameters[argument.Name.Value] = ArgumentValue(argument.Value, variables); } return parameters; @@ -167,7 +165,7 @@ public static IDictionary GetParametersFromSchemaAndQueryFields( protected static IDictionary GetParametersFromContext(IMiddlewareContext context) { - return GetParametersFromSchemaAndQueryFields(context.Selection.Field, context.Selection.SyntaxNode); + return GetParametersFromSchemaAndQueryFields(context.Selection.Field, context.Selection.SyntaxNode, context.Variables); } ///