-
Notifications
You must be signed in to change notification settings - Fork 248
Prevent empty input node generation in mutation builder. #2729
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
Open
Alekhya-Polavarapu
wants to merge
7
commits into
main
Choose a base branch
from
dev/alpolava/primarykey
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
6f9e94f
modify create and update mutation input
Alekhya-Polavarapu 3b790a4
modify create and update mutation input
Alekhya-Polavarapu 56672c4
Merge branch 'main' into dev/alpolava/primarykey
Alekhya-Polavarapu ca683c6
modify create and update mutation input
Alekhya-Polavarapu 8696fc0
mutation builder tests
Alekhya-Polavarapu 8d1df55
Merge branch 'main' into dev/alpolava/primarykey
Aniruddh25 61dfd65
Merge branch 'main' into dev/alpolava/primarykey
Aniruddh25 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change | ||||||
---|---|---|---|---|---|---|---|---|
|
@@ -31,8 +31,8 @@ public static class CreateMutationBuilder | |||||||
/// <param name="databaseType">Database type of the relational database to generate input type for.</param> | ||||||||
/// <param name="entities">Runtime config information.</param> | ||||||||
/// <param name="IsMultipleCreateOperationEnabled">Indicates whether multiple create operation is enabled</param> | ||||||||
/// <returns>A GraphQL input type with all expected fields mapped as GraphQL inputs.</returns> | ||||||||
private static InputObjectTypeDefinitionNode GenerateCreateInputTypeForRelationalDb( | ||||||||
/// <returns>An optional GraphQL input type with all expected fields mapped as GraphQL inputs.</returns> | ||||||||
private static InputObjectTypeDefinitionNode? GenerateCreateInputTypeForRelationalDb( | ||||||||
Dictionary<NameNode, InputObjectTypeDefinitionNode> inputs, | ||||||||
ObjectTypeDefinitionNode objectTypeDefinitionNode, | ||||||||
string entityName, | ||||||||
|
@@ -44,6 +44,7 @@ private static InputObjectTypeDefinitionNode GenerateCreateInputTypeForRelationa | |||||||
bool IsMultipleCreateOperationEnabled) | ||||||||
{ | ||||||||
NameNode inputName = GenerateInputTypeName(name.Value); | ||||||||
InputObjectTypeDefinitionNode? input = null; | ||||||||
|
||||||||
if (inputs.TryGetValue(inputName, out InputObjectTypeDefinitionNode? db)) | ||||||||
{ | ||||||||
|
@@ -54,32 +55,35 @@ private static InputObjectTypeDefinitionNode GenerateCreateInputTypeForRelationa | |||||||
// 1. Scalar input fields corresponding to columns which belong to the table. | ||||||||
// 2. Complex input fields corresponding to related (target) entities (table backed entities, for now) | ||||||||
// which are defined in the runtime config. | ||||||||
List<InputValueDefinitionNode> inputFields = new(); | ||||||||
List<InputValueDefinitionNode?> inputFields = new(); | ||||||||
|
||||||||
// 1. Scalar input fields. | ||||||||
IEnumerable<InputValueDefinitionNode> scalarInputFields = objectTypeDefinitionNode.Fields | ||||||||
.Where(field => IsBuiltInType(field.Type) && !IsAutoGeneratedField(field)) | ||||||||
.Select(field => GenerateScalarInputType(name, field, IsMultipleCreateOperationEnabled)); | ||||||||
|
||||||||
// Add scalar input fields to list of input fields for current input type. | ||||||||
inputFields.AddRange(scalarInputFields); | ||||||||
|
||||||||
// Create input object for this entity. | ||||||||
InputObjectTypeDefinitionNode input = | ||||||||
new( | ||||||||
location: null, | ||||||||
inputName, | ||||||||
new StringValueNode($"Input type for creating {name}"), | ||||||||
new List<DirectiveNode>(), | ||||||||
inputFields | ||||||||
); | ||||||||
|
||||||||
// Add input object to the dictionary of entities for which input object has already been created. | ||||||||
// This input object currently holds only scalar fields. | ||||||||
// The complex fields (for related entities) would be added later when we return from recursion. | ||||||||
// Adding the input object to the dictionary ensures that we don't go into infinite recursion and return whenever | ||||||||
// we find that the input object has already been created for the entity. | ||||||||
inputs.Add(input.Name, input); | ||||||||
// Generate the create input type only if there are any scalar fields that are not auto-generated fields. | ||||||||
if (scalarInputFields.Any()) | ||||||||
{ | ||||||||
inputFields.AddRange(scalarInputFields); | ||||||||
|
||||||||
// Create input object for this entity. | ||||||||
input = | ||||||||
new( | ||||||||
location: null, | ||||||||
inputName, | ||||||||
new StringValueNode($"Input type for creating {name}"), | ||||||||
new List<DirectiveNode>(), | ||||||||
inputFields! | ||||||||
); | ||||||||
Comment on lines
+78
to
+79
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit:
Suggested change
|
||||||||
// Add input object to the dictionary of entities for which input object has already been created. | ||||||||
// This input object currently holds only scalar fields. | ||||||||
// The complex fields (for related entities) would be added later when we return from recursion. | ||||||||
// Adding the input object to the dictionary ensures that we don't go into infinite recursion and return whenever | ||||||||
// we find that the input object has already been created for the entity. | ||||||||
inputs.Add(input.Name, input); | ||||||||
} | ||||||||
|
||||||||
// Generate fields for related entities when | ||||||||
// 1. Multiple mutation operations are supported for the database type. | ||||||||
|
@@ -88,7 +92,7 @@ private static InputObjectTypeDefinitionNode GenerateCreateInputTypeForRelationa | |||||||
{ | ||||||||
// 2. Complex input fields. | ||||||||
// Evaluate input objects for related entities. | ||||||||
IEnumerable<InputValueDefinitionNode> complexInputFields = | ||||||||
IEnumerable<InputValueDefinitionNode?> complexInputFields = | ||||||||
objectTypeDefinitionNode.Fields | ||||||||
.Where(field => !IsBuiltInType(field.Type) && IsComplexFieldAllowedForCreateInputInRelationalDb(field, definitions)) | ||||||||
.Select(field => | ||||||||
|
@@ -148,7 +152,7 @@ private static InputObjectTypeDefinitionNode GenerateCreateInputTypeForRelationa | |||||||
databaseType: databaseType, | ||||||||
entities: entities, | ||||||||
IsMultipleCreateOperationEnabled: IsMultipleCreateOperationEnabled); | ||||||||
}); | ||||||||
}).Where(complexInputType => complexInputType != null); | ||||||||
// Append relationship fields to the input fields. | ||||||||
inputFields.AddRange(complexInputFields); | ||||||||
} | ||||||||
|
@@ -307,8 +311,8 @@ private static InputValueDefinitionNode GenerateScalarInputType(NameNode name, F | |||||||
/// <param name="objectTypeDefinitionNode">The GraphQL object type to create the input type for.</param> | ||||||||
/// <param name="databaseType">Database type to generate the input type for.</param> | ||||||||
/// <param name="entities">Runtime configuration information for entities.</param> | ||||||||
/// <returns>A GraphQL input type value.</returns> | ||||||||
private static InputValueDefinitionNode GenerateComplexInputTypeForRelationalDb( | ||||||||
/// <returns>An Optional GraphQL input type value.</returns> | ||||||||
private static InputValueDefinitionNode? GenerateComplexInputTypeForRelationalDb( | ||||||||
string entityName, | ||||||||
Dictionary<NameNode, InputObjectTypeDefinitionNode> inputs, | ||||||||
IEnumerable<HotChocolate.Language.IHasName> definitions, | ||||||||
|
@@ -320,7 +324,7 @@ private static InputValueDefinitionNode GenerateComplexInputTypeForRelationalDb( | |||||||
RuntimeEntities entities, | ||||||||
bool IsMultipleCreateOperationEnabled) | ||||||||
{ | ||||||||
InputObjectTypeDefinitionNode node; | ||||||||
InputObjectTypeDefinitionNode? node; | ||||||||
NameNode inputTypeName = GenerateInputTypeName(typeName); | ||||||||
if (!inputs.ContainsKey(inputTypeName)) | ||||||||
{ | ||||||||
|
@@ -340,7 +344,7 @@ private static InputValueDefinitionNode GenerateComplexInputTypeForRelationalDb( | |||||||
node = inputs[inputTypeName]; | ||||||||
} | ||||||||
|
||||||||
return GetComplexInputType(field, node, inputTypeName, IsMultipleCreateOperationEnabled); | ||||||||
return node == null ? null : GetComplexInputType(field, node, inputTypeName, IsMultipleCreateOperationEnabled); | ||||||||
} | ||||||||
|
||||||||
/// <summary> | ||||||||
|
@@ -487,7 +491,7 @@ public static IEnumerable<FieldDefinitionNode> Build( | |||||||
{ | ||||||||
List<FieldDefinitionNode> createMutationNodes = new(); | ||||||||
Entity entity = entities[dbEntityName]; | ||||||||
InputObjectTypeDefinitionNode input; | ||||||||
InputObjectTypeDefinitionNode? input; | ||||||||
if (!IsRelationalDb(databaseType)) | ||||||||
{ | ||||||||
input = GenerateCreateInputTypeForNonRelationalDb( | ||||||||
|
@@ -528,28 +532,31 @@ public static IEnumerable<FieldDefinitionNode> Build( | |||||||
|
||||||||
string singularName = GetDefinedSingularName(name.Value, entity); | ||||||||
|
||||||||
// Create one node. | ||||||||
FieldDefinitionNode createOneNode = new( | ||||||||
location: null, | ||||||||
name: new NameNode(GetPointCreateMutationNodeName(name.Value, entity)), | ||||||||
description: new StringValueNode($"Creates a new {singularName}"), | ||||||||
arguments: new List<InputValueDefinitionNode> { | ||||||||
if(input != null) | ||||||||
{ | ||||||||
// Create one node. | ||||||||
FieldDefinitionNode createOneNode = new( | ||||||||
location: null, | ||||||||
name: new NameNode(GetPointCreateMutationNodeName(name.Value, entity)), | ||||||||
description: new StringValueNode($"Creates a new {singularName}"), | ||||||||
arguments: new List<InputValueDefinitionNode> { | ||||||||
new( | ||||||||
location : null, | ||||||||
new NameNode(MutationBuilder.ITEM_INPUT_ARGUMENT_NAME), | ||||||||
new StringValueNode($"Input representing all the fields for creating {name}"), | ||||||||
new NonNullTypeNode(new NamedTypeNode(input.Name)), | ||||||||
defaultValue: null, | ||||||||
new List<DirectiveNode>()) | ||||||||
}, | ||||||||
type: new NamedTypeNode(returnEntityName), | ||||||||
directives: fieldDefinitionNodeDirectives | ||||||||
); | ||||||||
}, | ||||||||
type: new NamedTypeNode(returnEntityName), | ||||||||
directives: fieldDefinitionNodeDirectives | ||||||||
); | ||||||||
|
||||||||
createMutationNodes.Add(createOneNode); | ||||||||
createMutationNodes.Add(createOneNode); | ||||||||
} | ||||||||
|
||||||||
// Multiple create node is created in the schema only when multiple create operation is enabled. | ||||||||
if (IsMultipleCreateOperationEnabled) | ||||||||
if (IsMultipleCreateOperationEnabled && input != null) | ||||||||
{ | ||||||||
// Create multiple node. | ||||||||
FieldDefinitionNode createMultipleNode = new( | ||||||||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just out of curiosity, I am not entirely sure how the mutation builder works for non-relational databases. So do you think this might also be a bug that could be found there? If so then it would also be a good idea to change the
GenerateCreateInputTypeForNonRelationalDb
function.