Skip to content

feat: check slicing Arguments passed when requireOneSlicingArgument#1456

Merged
ysmolski merged 9 commits intomasterfrom
yury/eng-8842-cost-validate-requireoneslicingargument-in-queries
Mar 26, 2026
Merged

feat: check slicing Arguments passed when requireOneSlicingArgument#1456
ysmolski merged 9 commits intomasterfrom
yury/eng-8842-cost-validate-requireoneslicingargument-in-queries

Conversation

@ysmolski
Copy link
Copy Markdown
Contributor

@ysmolski ysmolski commented Mar 23, 2026

For an operation, the engine validates if slicing arguments of the field satisfy the configured listSize:requireOneSlicingArgument option.

Summary by CodeRabbit

  • New Features
    • Cost estimation now validates list-slicing arguments after planning; fields configured to require exactly one slicing argument will error when none or multiple are provided, with errors referencing the field path.
  • Tests
    • Expanded coverage for slicing-argument validation across concrete and abstract/interface scenarios, multi-field error aggregation, and varying argument sources and counts.

For an operation, the engine validates if arguments of the field satisfy
the configured listSize:requireOneSlicingArgument option.
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review.

Tip: disable this comment in your organization's Code Review settings.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 23, 2026

📝 Walkthrough

Walkthrough

Adds runtime validation of list-slicing arguments: after plan lookup, ExecutionEngine calls CostCalculator.ValidateSliceArguments(...) using planner config and request variables and returns immediately on reported validation errors; supporting cost-tree, metadata, debug-print, and tests were added/updated.

Changes

Cohort / File(s) Summary
Execution engine integration
execution/engine/execution_engine.go, execution/graphql/request.go
ExecutionEngine now calls CostCalculator.ValidateSliceArguments(config, variables, &report) after obtaining a plan and returns on validation failures; minor debug-print argument adjustment in request code.
Cost calculation core
v2/pkg/engine/plan/cost.go, v2/pkg/engine/plan/cost_visitor.go, v2/pkg/engine/plan/federation_metadata.go
Added CostCalculator.ValidateSliceArguments and CostTreeNode.validateSliceArguments to enforce RequireOneSlicingArgument; renamed fieldCoordfieldCoords; removed literal-int ArgumentInfo.intValue usage; added abstract-type helper, AST-path builder, and FieldCoordinate.String(); adjusted debug output formatting.
Tests
execution/engine/execution_engine_cost_test.go
Extensive new tests for RequireOneSlicingArgument covering concrete and abstract fields, zero/one/multiple slicing-argument cases, literals vs variables, and multi-field error aggregation.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ExecutionEngine as EE
  participant Planner
  participant CostCalculator as CostCalc
  participant Operation as Op

  Client->>EE: send request
  EE->>Planner: resolve plan (cached or fresh)
  Planner-->>EE: return plan
  EE->>CostCalc: ValidateSliceArguments(config, variables, report)
  alt validation fails
    CostCalc-->>EE: report with errors
    EE-->>Client: return validation errors
  else validation succeeds
    EE->>Operation: ComputeEstimatedCost(plan, variables, report)
    Operation-->>EE: estimated cost
    EE-->>Client: continue execution / return result
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly describes the main feature: validating slicing arguments when requireOneSlicingArgument is configured, which matches the core changes in execution_engine.go and cost.go validation logic.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch yury/eng-8842-cost-validate-requireoneslicingargument-in-queries

Comment @coderabbitai help to get the list of available commands and usage tips.

@ysmolski ysmolski changed the title feat: validate operations against listSize:requireOneSlicingArgument feat: validate operations against slicingArguments Mar 23, 2026
@ysmolski ysmolski changed the title feat: validate operations against slicingArguments feat: require One Slicing Argument from fields with listSized Mar 23, 2026
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8e6071fa-bd55-4992-a2d5-a065f8f70f5b

📥 Commits

Reviewing files that changed from the base of the PR and between 18b292e and ecb21d4.

📒 Files selected for processing (5)
  • execution/engine/execution_engine.go
  • execution/engine/execution_engine_cost_test.go
  • v2/pkg/engine/plan/cost.go
  • v2/pkg/engine/plan/cost_visitor.go
  • v2/pkg/engine/plan/federation_metadata.go

Comment thread v2/pkg/engine/plan/cost.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@v2/pkg/engine/plan/cost.go`:
- Around line 657-672: The count logic in cost.go currently only increments for
variable-based slicing arguments; update the loop over listSize.SlicingArguments
(using node.arguments and the arg variable) to also count literal integer
slicing arguments: inside the loop, keep the existing branch that checks if
arg.hasVariable and consults variables.Get(arg.varName), but add an else-if that
checks arg.intValue > 0 (or the equivalent literal value field on arg) and
increments count for those literals as well so literal slicing args (e.g.,
users(first: 10)) are included in the validation.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b435e971-573f-4213-8af2-848448b16978

📥 Commits

Reviewing files that changed from the base of the PR and between ecb21d4 and 08483b0.

📒 Files selected for processing (1)
  • v2/pkg/engine/plan/cost.go

Comment thread v2/pkg/engine/plan/cost.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@v2/pkg/engine/plan/cost.go`:
- Around line 646-653: The current logic only consults
node.parent.requiringOneArgImplementingField when listSize is nil, so an
abstract field's listSize with RequireOneSlicingArgument=false can mask a
concrete implementation that requires one; change the logic so that when
node.isEnclosingTypeAbstract and node.parent != nil you always consult the
implementing-type info via
node.parent.requiringOneArgImplementingField(dsCostConfig,
node.fieldCoords.FieldName) and if that returns a non-nil listSize with
RequireOneSlicingArgument==true then treat the effective listSize as requiring
one slicing argument (either by replacing listSize or setting
RequireOneSlicingArgument=true), before the subsequent check that enforces
RequireOneSlicingArgument and SlicingArguments length.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d12531ec-b49b-4ce1-a692-40d12016b18d

📥 Commits

Reviewing files that changed from the base of the PR and between 08483b0 and 0c7204f.

📒 Files selected for processing (1)
  • v2/pkg/engine/plan/cost.go

Comment thread v2/pkg/engine/plan/cost.go
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
v2/pkg/engine/plan/cost.go (1)

616-623: ⚠️ Potential issue | 🟠 Major

Don't let the abstract field config mask a stricter implementation.

This only consults requiringOneArgImplementingField when the abstract coordinate has no listSize. If the interface field is configured with RequireOneSlicingArgument=false and any concrete implementation sets it to true, the abstract selection is incorrectly accepted.

💡 Suggested fix
-		listSize := dsCostConfig.ListSizes[node.fieldCoords]
-		if listSize == nil && node.isEnclosingTypeAbstract && node.parent != nil && node.parent.returnsAbstractType {
-			// We pick the first from the list of implementing types. Composition should verify that
-			// all implementations are aligned on the slicingArguments within the single subgraph.
-			// Otherwise, we would have inconsistent expectations between implementing types.
-			listSize = node.parent.requiringOneArgImplementingField(dsCostConfig, node.fieldCoords.FieldName)
-		}
+		listSize := dsCostConfig.ListSizes[node.fieldCoords]
+		if node.isEnclosingTypeAbstract && node.parent != nil && node.parent.returnsAbstractType {
+			// Any strict implementation must make the abstract selection strict as well.
+			if requiring := node.parent.requiringOneArgImplementingField(dsCostConfig, node.fieldCoords.FieldName); requiring != nil &&
+				(listSize == nil || !listSize.RequireOneSlicingArgument) {
+				listSize = requiring
+			}
+		}
Based on learnings: In wundergraph/graphql-go-tools (v2/pkg/engine/plan/cost.go), when validating `RequireOneSlicingArgument` for abstract fields, the intended behavior is: if ANY implementing concrete type has `RequireOneSlicingArgument=true`, the operation must satisfy the slicing argument constraint.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@v2/pkg/engine/plan/cost.go` around lines 616 - 623, When handling abstract
fields in calculate cost, also consult implementing-type configs even when the
abstract `listSize` is present: call
node.parent.requiringOneArgImplementingField(dsCostConfig,
node.fieldCoords.FieldName) (when node.isEnclosingTypeAbstract && node.parent !=
nil) and compute an effective requirement like effectiveRequireOne := (listSize
!= nil && listSize.RequireOneSlicingArgument) || (implListSize != nil &&
implListSize.RequireOneSlicingArgument); then use effectiveRequireOne and the
presence of slicing args from either listSize or implListSize to decide the
error path (e.g., if effectiveRequireOne && (both SlicingArguments lists are
empty or missing) then treat as missing slicing argument). Update the checks
around listSize, RequireOneSlicingArgument and SlicingArguments accordingly so a
concrete implementation requiring a slicing arg cannot be masked by the abstract
field config.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@execution/engine/execution_engine_cost_test.go`:
- Around line 3415-3425: The test currently sets RequireOneSlicingArgument=true
for all implementations so it never exercises the mixed abstract-policy path;
update the ListSizes map in execution_engine_cost_test.go (the entries keyed by
plan.FieldCoordinate like {TypeName: "UserPaginated", FieldName: "items"} and
{TypeName: "PostPaginated", FieldName: "items"}) to create a mixed-policy case —
e.g., make one implementation have RequireOneSlicingArgument=false (or add a new
concrete implementation entry with false) while another stays true — so the
abstractCostConfig code path that treats abstract fields as requiring an
argument if ANY implementation requires it is exercised and the test assertions
reflect that behavior.

---

Duplicate comments:
In `@v2/pkg/engine/plan/cost.go`:
- Around line 616-623: When handling abstract fields in calculate cost, also
consult implementing-type configs even when the abstract `listSize` is present:
call node.parent.requiringOneArgImplementingField(dsCostConfig,
node.fieldCoords.FieldName) (when node.isEnclosingTypeAbstract && node.parent !=
nil) and compute an effective requirement like effectiveRequireOne := (listSize
!= nil && listSize.RequireOneSlicingArgument) || (implListSize != nil &&
implListSize.RequireOneSlicingArgument); then use effectiveRequireOne and the
presence of slicing args from either listSize or implListSize to decide the
error path (e.g., if effectiveRequireOne && (both SlicingArguments lists are
empty or missing) then treat as missing slicing argument). Update the checks
around listSize, RequireOneSlicingArgument and SlicingArguments accordingly so a
concrete implementation requiring a slicing arg cannot be masked by the abstract
field config.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 205f35aa-e7a9-46c5-8792-0d1d83463aa8

📥 Commits

Reviewing files that changed from the base of the PR and between 3faabb5 and d0acab6.

📒 Files selected for processing (4)
  • execution/engine/execution_engine.go
  • execution/engine/execution_engine_cost_test.go
  • execution/graphql/request.go
  • v2/pkg/engine/plan/cost.go
✅ Files skipped from review due to trivial changes (1)
  • execution/engine/execution_engine.go

Comment thread execution/engine/execution_engine_cost_test.go
@ysmolski ysmolski changed the title feat: require One Slicing Argument from fields with listSized feat: check slicing Arguments passed when requireOneSlicingArgument=true Mar 26, 2026
@ysmolski ysmolski changed the title feat: check slicing Arguments passed when requireOneSlicingArgument=true feat: check slicing Arguments passed when requireOneSlicingArgument Mar 26, 2026
@ysmolski ysmolski merged commit 72c181f into master Mar 26, 2026
10 checks passed
@ysmolski ysmolski deleted the yury/eng-8842-cost-validate-requireoneslicingargument-in-queries branch March 26, 2026 10:48
ysmolski pushed a commit that referenced this pull request Mar 26, 2026
🤖 I have created a release *beep* *boop*
---


##
[2.0.0-rc.267](v2.0.0-rc.266...v2.0.0-rc.267)
(2026-03-26)


### Features

* check slicing Arguments passed when requireOneSlicingArgument
([#1456](#1456))
([72c181f](72c181f))
ysmolski pushed a commit that referenced this pull request Apr 8, 2026
##
[1.11.0](execution/v1.10.0...execution/v1.11.0)
(2026-04-08)


### Features

* check slicing Arguments passed when requireOneSlicingArgument
([#1456](#1456))
([72c181f](72c181f))
* handle recursion for arguments containing input objects
([#1461](#1461))
([ba21793](ba21793))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants