Skip to content

Commit

Permalink
@Skip and @include on same field
Browse files Browse the repository at this point in the history
  • Loading branch information
tobias-tengler committed Dec 1, 2024
1 parent 8197895 commit 45ae235
Show file tree
Hide file tree
Showing 2 changed files with 132 additions and 49 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,8 @@ public RootPlanNode CreatePlan(DocumentNode document, string? operationName)

if (TryPlanSelectionSet(operation, operation, new Stack<SelectionPathSegment>()))
{
if (TryPlanConditionNode(operation.Selections, out var conditionNode))
{
conditionNode.AddChildNode(operation);
operationPlan.AddChildNode(conditionNode);
}
else
{
operationPlan.AddChildNode(operation);
}
var planNodeToAdd = PlanConditionNode(operation.Selections, operation);
operationPlan.AddChildNode(planNodeToAdd);
}
}

Expand Down Expand Up @@ -226,15 +219,8 @@ private bool TryHandleUnresolvedSelections(
continue;
}

if (TryPlanConditionNode(lookupField.Selections, out var conditionNode))
{
conditionNode.AddChildNode(lookupOperation);
operation.AddChildNode(conditionNode);
}
else
{
operation.AddChildNode(lookupOperation);
}
var planNodeToAdd = PlanConditionNode(lookupField.Selections, lookupOperation);
operation.AddChildNode(planNodeToAdd);

foreach (var selection in lookupField.Selections)
{
Expand Down Expand Up @@ -413,44 +399,60 @@ private static Dictionary<string, int> GetSchemasWeighted(
return counts;
}

private bool TryPlanConditionNode(IReadOnlyList<SelectionPlanNode> selectionPlanNodes,
[NotNullWhen(true)] out ConditionPlanNode? conditionNode)
private PlanNode PlanConditionNode(
IReadOnlyList<SelectionPlanNode> selectionPlanNodes,
OperationPlanNode operation)
{
conditionNode = null;
// TODO: This is not correct
Condition? sharedCondition = null;

foreach (var selection in selectionPlanNodes)
var firstSelection = selectionPlanNodes.FirstOrDefault();
if (firstSelection is null || firstSelection.Conditions.Count == 0)
{
if (selection.Conditions.Count < 1)
{
return false;
}
return operation;
}

var condition = selection.Conditions[0];
var conditionsOnFirstSelectionNode = new HashSet<Condition>(firstSelection.Conditions);

if (sharedCondition is null)
foreach (var selection in selectionPlanNodes.Skip(1))
{
if (selection.Conditions.Count == 0)
{
sharedCondition = condition;
continue;
return operation;
}

// One of the selection doesn't have same condition as the others.
if (sharedCondition != condition)
foreach (var condition in selection.Conditions)
{
return false;
if (!conditionsOnFirstSelectionNode.Contains(condition))
{
return operation;
}
}
}

if (sharedCondition is not null)
ConditionPlanNode? startConditionNode = null;
ConditionPlanNode? lastConditionNode = null;

foreach (var sharedCondition in conditionsOnFirstSelectionNode)
{
RemoveConditionFromSelections(selectionPlanNodes, sharedCondition);
conditionNode = new ConditionPlanNode(sharedCondition.VariableName, sharedCondition.PassingValue);
foreach (var selection in selectionPlanNodes)
{
selection.RemoveCondition(sharedCondition);
}

return true;
if (startConditionNode is null)
{
startConditionNode = lastConditionNode =
new ConditionPlanNode(sharedCondition.VariableName, sharedCondition.PassingValue);
}
else if (lastConditionNode is not null)
{
var childCondition = new ConditionPlanNode(sharedCondition.VariableName, sharedCondition.PassingValue);
lastConditionNode.AddChildNode(childCondition);
lastConditionNode = childCondition;
}
}

return false;
lastConditionNode?.AddChildNode(operation);

return startConditionNode!;
}

private bool IsSelectionAlwaysSkipped(ISelectionNode selectionNode)
Expand Down Expand Up @@ -536,14 +538,6 @@ private bool IsSelectionAlwaysSkipped(ISelectionNode selectionNode)
return (isSelectionNodeObsolete, conditions);
}

private void RemoveConditionFromSelections(IReadOnlyList<SelectionPlanNode> selectionPlanNodes, Condition condition)
{
foreach (var selection in selectionPlanNodes)
{
selection.RemoveCondition(condition);
}
}

public record SelectionPathSegment(
SelectionPlanNode PlanNode);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -724,4 +724,93 @@ await Assert
}
""");
}

[Test]
public async Task Skip_And_Include_On_RootField_Only_Skipped_Field_Selected()
{
// arrange
var compositeSchema = CreateCompositeSchema();

// act
var plan = PlanOperationAsync(
compositeSchema,
"""
query GetProduct($id: ID!, $skip: Boolean!, $include: Boolean!) {
productById(id: $id) @skip(if: $skip) @include(if: $include) {
name
}
}
""");

// assert
await Assert
.That(plan.Serialize())
.IsEqualTo(
"""
{
"kind": "Root",
"nodes": [
{
"kind": "Condition",
"variableName": "skip",
"passingValue": false,
"nodes": [
{
"kind": "Condition",
"variableName": "include",
"passingValue": true,
"nodes": [
{
"kind": "Operation",
"schema": "PRODUCTS",
"document": "{ productById(id: $id) { name } }"
}
]
}
]
}
]
}
""");
}

[Test]
public async Task Skip_And_Include_On_RootField()
{
// arrange
var compositeSchema = CreateCompositeSchema();

// act
var plan = PlanOperationAsync(
compositeSchema,
"""
query GetProduct($id: ID!, $skip: Boolean!, $include: Boolean!) {
productById(id: $id) @skip(if: $skip) @include(if: $include) {
name
}
products {
nodes {
name
}
}
}
""");

// assert
await Assert
.That(plan.Serialize())
.IsEqualTo(
"""
{
"kind": "Root",
"nodes": [
{
"kind": "Operation",
"schema": "PRODUCTS",
"document": "query($id: ID!, $include: Boolean!, $skip: Boolean!) { productById(id: $id) @skip(if: $skip) @include(if: $include) { name } products { nodes { name } } }"
}
]
}
""");
}
}

0 comments on commit 45ae235

Please sign in to comment.