feat: over() helper for window functions in Query macro#49
Merged
Conversation
89c4ca3 to
9dd4ed5
Compare
Adds composable over() helper for window functions inside mutate:
Dux.mutate(df,
rank: over(row_number(), partition_by: :dept, order_by: [desc: :salary]),
running: over(sum(amount), order_by: :date, frame: {:rows, :unbounded, :current}),
pct: salary * 100.0 / over(sum(salary), partition_by: :dept)
)
Options:
- partition_by: atom, list of atoms, or column expression
- order_by: atom, or keyword list with :asc/:desc
- frame: tuple {type, start, end} or raw SQL string
Frame tuple syntax:
- Type: :rows, :range, or :groups
- Start: negative int (PRECEDING), :unbounded, :current, or 0
- End: positive int (FOLLOWING), :unbounded, :current, or 0
- Optional 4th element: [exclude: :current | :group | :ties | :no_others]
Examples:
{:rows, -2, :current} # 3-row moving window
{:rows, :unbounded, :current} # cumulative
{:rows, -2, 2} # centered 5-row window
{:rows, :unbounded, :unbounded} # entire partition
{:rows, :unbounded, :unbounded, exclude: :current} # all except self
Raw SQL strings still work as fallback:
frame: "ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING"
35 tests (33 unit + 2 property-based) covering all categories:
happy path, sad path, adversarial, scale/wicked, property-based,
distributed, frame tuples, frame strings, exclude clauses.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9dd4ed5 to
d0286be
Compare
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
Adds
over()for window functions insidemutateexpressions with a full tuple-based frame syntax. Addresses feedback from @billylanchantin about making frames feel native rather than stringly-typed.Frame tuple syntax
`{type, start, end}` where:
Add `exclude:` as a 4th element:
Raw SQL strings still work as a fallback for anything the tuple syntax doesn't cover.
Implementation
`over()` is a macro transformation in `Dux.Query`. Compiles to `FUNC() OVER (PARTITION BY ... ORDER BY ... frame)`. Frame tuples are resolved at macro expansion time (handles Elixir AST representation of negative integers and 3+ element tuples).
Test plan (35 tests: 33 unit + 2 property-based)
746 total tests pass, 0 credo issues.
🤖 Generated with Claude Code