Skip to content

[C#] Removes Query<TRow> and .Build() in favor of IQuery<TRow>#4393

Merged
clockwork-labs-bot merged 3 commits intomasterfrom
rekhoff/csharp-query-builder-implicit-build
Feb 23, 2026
Merged

[C#] Removes Query<TRow> and .Build() in favor of IQuery<TRow>#4393
clockwork-labs-bot merged 3 commits intomasterfrom
rekhoff/csharp-query-builder-implicit-build

Conversation

@rekhoff
Copy link
Contributor

@rekhoff rekhoff commented Feb 22, 2026

This fixes an issue with the C# implementation of Query Builder requiring Build() to return a query, and the return type being Query<TRow> rather than IQuery<TRow>.

Description of Changes

  1. Runtime/query-builder
  • Removed the concrete Query<TRow> carrier type and every .Build(). Query builder shapes now expose only IQuery<TRow> plus ToSql().
  • Ensured all builder entry points (tables, joins, filters) continue to return IQuery<TRow>.
  1. Source generator + bindings
  • Updated ViewDeclaration analysis to treat any return type implementing SpacetimeDB.IQuery<TRow> as a SQL view.
  • Dispatcher generation now emits ViewResultHeader.RawSql(returnValue.ToSql()) . This eliminates a Query<TRow> special-case.
  1. Tests, fixtures, regression module
  • Converted the C# query-builder unit tests, codegen fixtures, and regression-test server views to call ToSql()/return IQuery<TRow>.
  • Added coverage proving RightSemiJoin (and friends) still satisfy IQuery<TRow>.
  1. CLI templates & generated bindings
  • Regenerated/edited C# template bindings so SubscriptionBuilder.AddQuery accepts Func<QueryBuilder, IQuery<TRow>> and captures SQL via ToSql().

API and ABI breaking changes

While technically API breaking, this actually brings the API closer to the intended design.

  • Query<TRow> has been removed from the public surface area; any previous references (including .Build() and .Sql) must be replaced with the builder instance itself plus .ToSql().
  • View methods must now return an IQuery<TRow> (or any custom type implementing it) when producing SQL for the host.
  • Generated C# client bindings now expect typed subscription callbacks to produce IQuery<TRow>, aligning the client SDK with the new runtime contract.

Expected complexity level and risk

3 - Medium: Touches runtime, codegen, fixtures, and templates. Risk is mitigated by parity with Rust semantics and comprehensive test updates, but downstream modules must recompile to adopt the new interface.

Testing

  • Built CLI and ran regression tests locally with removed .Build()
  • Ran dotnet test .\sdks\csharp\tests~\tests.csproj -c Release with all tests passing
  • Ran dotnet test .\crates\bindings-csharp\Codegen.Tests\Codegen.Tests.csproj -c Release with all tests passing

@rekhoff rekhoff self-assigned this Feb 22, 2026
@rekhoff rekhoff changed the title Adds an implicit Build() conversion to Query Adds an implicit Build() conversion to AddQuery Feb 22, 2026
@rekhoff rekhoff changed the title Adds an implicit Build() conversion to AddQuery Adds an implicit Build() conversion to Query Feb 22, 2026
@rekhoff rekhoff changed the title Adds an implicit Build() conversion to Query Adds an implicit Build() conversion to Query<TRow> Feb 22, 2026
@rekhoff rekhoff changed the title Adds an implicit Build() conversion to Query<TRow> [C#] Removes Query<TRow> and .Build() in favor of IQuery<TRow> Feb 23, 2026
@rekhoff rekhoff marked this pull request as ready for review February 23, 2026 04:00
@clockwork-labs-bot clockwork-labs-bot added this pull request to the merge queue Feb 23, 2026
Merged via the queue into master with commit 85095cf Feb 23, 2026
34 of 35 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants