feat(schema)!: broadcast semantics for mixed select and context-dependent orderBy expressions - #60
Merged
kudima03 merged 4 commits intoSep 24, 2026
Conversation
kudima03
force-pushed
the
docs/select-broadcast-semantics
branch
from
September 24, 2026 13:24
a613f19 to
e196dd5
Compare
kudima03
changed the base branch from
main
to
feat/grouped-select-single-value
September 24, 2026 13:24
Without groupBy, a select that mixes array-returning items (fields, each* columns) with single-value items (aggregates, scalars) now has a defined result: N rows, with each single-value item repeated on every row. A select of only single-value items yields one row. Aggregates are computed over all N rows before distinct and pagination. Add sample 22 (grand total and share-of-total next to order fields) and document the rule in README, CLAUDE.md and CHANGELOG. Closes #52 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Add expressionOrderByItem ({ expression: singleValueReturning,
direction }). With groupBy, orderBy items must be expressionOrderByItem
(root dependentSchemas); without groupBy they must be orderByItem
(root anyOf). A group has no single value for a field, so sorting
groups by a field is rejected; sort by an aggregate instead, and wrap
group keys in an aggregate such as min_string.
Migrate sample 12 to sort by sum(total_amount) desc, then
min_string(users.name) asc, and document the rule in README,
CLAUDE.md and CHANGELOG.
BREAKING CHANGE: grouped queries that sort by a field no longer
validate; use an aggregate expression instead.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kudima03
force-pushed
the
docs/select-broadcast-semantics
branch
from
September 24, 2026 13:45
e196dd5 to
1583d6e
Compare
Replace the { field } / { expression } split with a single orderByItem
{ expression, direction }. The allowed expression kind follows the
query context, the same split as where/having and grouped select:
array-returning without groupBy (fields and each* computations),
single-value with groupBy (aggregates and arithmetic over them).
Drop expressionOrderByItem.
This makes sorting by computed values possible in both contexts. Add
sample 23 (order items sorted by eachMultiply(unit_price, quantity))
and update README, CLAUDE.md and CHANGELOG.
BREAKING CHANGE: orderBy items use { "expression": X } in place of
{ "field": X }.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Drop the root anyOf that rejected single-value orderBy expressions in ungrouped queries. Such keys are constants and leave the order unchanged, like OrderBy(r => 1) in LINQ, so rejecting them added schema complexity without catching an ambiguous query. Grouped queries still require single-value keys via dependentSchemas. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
Closes #52 together with #59. Stacked on #59: this PR targets
feat/grouped-select-single-value. Once #59 merges, it retargets tomain.1. Broadcast semantics for a mixed
selectwithoutgroupBy(docs only)#52 flagged
select: [field, sum(...)]withoutgroupByas a query whose result is undefined. This PR doesn't reject it; it gives it a defined meaning, using the broadcast model thateach*operators already follow:each*column):Nrows, whereNcomes fromfrom+joins+where. Every single-value item is repeated on each row. IfN = 0, the result is empty.Nrows: they're computed beforedistinctandpagination.New sample
22_select_broadcast.json: order fields plussum(total_amount)asgrand_totalandeachDivide(total_amount, sum(total_amount))asshare_of_total.2.
orderBykeys follow the query context (breaking)orderBysorts result rows, so its key has to produce one value per result row. Before this PR it only accepted fields, which allowed ambiguous grouped sorts (a field has no single value per group) and gave no way to sort by a computed value.Now every item is one shape,
orderByItem={ expression, direction }, and the allowed kind ofexpressionfollows the context. This is the same split aswhere/havingand asselectwith and withoutgroupBy:expressionmust begroupByarrayReturning: field,each*(single-value is allowed but has no effect)groupBysingleValueReturning: aggregate, arithmetic over aggregatesdependentSchemasIn LINQ terms:
items.OrderByDescending(i => i.UnitPrice * i.Quantity)and.GroupBy(o => o.UserId).OrderByDescending(g => g.Sum(o => o.Total) / g.Count()).expression; the{ field }form is gone.selectcolumn, you repeat the expression, which keeps validation strict.min_string(users.name)) until Add order-sensitive aggregates firstElement / lastElement with per-aggregate orderBy #61 addsfirstElement.sum(total_amount) desc, thenmin_string(users.name) asc.23_order_by_computed.json: order items sorted byeachMultiply(unit_price, quantity) desc, thenid.Verification
All 23 samples validate. Scenario checks for
orderBy:divide(sum, count)eachMultiplyeachMultiply{ field }formdirectionBreaking change
orderByitems use{ "expression": X }in place of{ "field": X }, in every query. Grouped queries must sort by a single-value expression. The release needs a major bump.Follow-up
Order-sensitive aggregates (
firstElement/lastElement, each with its ownorderBy) are tracked in a separate issue.firstElement(key)would also let groups be sorted by keys of any type, includinguuidandboolean.🤖 Generated with Claude Code