feat: support offset option in lateral join queries#700
feat: support offset option in lateral join queries#700zachdaniel merged 1 commit intoash-project:mainfrom
Conversation
Applies relationship.offset to the lateral join base query so that has_one/has_many relationships with offset work correctly in PostgreSQL. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
Adds support for applying relationship.offset when generating lateral-join queries in AshPostgres.DataLayer, with accompanying test coverage to validate loading a “second latest” has_one relationship.
Changes:
- Apply
relationship.offsetto the destinationbase_queryin the lateral-join query builder. - Add a
second_latest_commentrelationship onPostusingsort + offset. - Add an integration test asserting the offset relationship returns the expected record when loaded.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
lib/data_layer.ex |
Applies relationship.offset when constructing lateral join destination subqueries. |
test/support/resources/post.ex |
Introduces second_latest_comment relationship to exercise sort+offset behavior. |
test/load_test.exs |
Adds a load test covering has_one relationship loading with offset via lateral join. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| has_one :second_latest_comment, AshPostgres.Test.Comment do | ||
| sort(created_at: :desc) | ||
| offset(1) |
There was a problem hiding this comment.
second_latest_comment uses sort/1 and offset/1 to pick a single record from the comments collection, but it doesn't set from_many?(true) like latest_comment does. Without from_many?(true), the lateral-join query builder won't apply limit: 1, and for posts with 3+ comments the subquery can return multiple rows (all rows after the offset), making the loaded has_one nondeterministic.
Consider adding from_many?(true) (and keeping the existing sort/offset) so this relationship is guaranteed to resolve to exactly one comment.
| offset(1) | |
| offset(1) | |
| from_many?(true) |
| test "has_one with offset returns the correct record" do | ||
| post = | ||
| Post | ||
| |> Ash.Changeset.for_create(:create, %{title: "title"}) | ||
| |> Ash.create!() | ||
|
|
||
| %{id: first_comment_id} = | ||
| Comment | ||
| |> Ash.Changeset.for_create(:create, %{title: "first"}) | ||
| |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) | ||
| |> Ash.create!() | ||
|
|
||
| :timer.sleep(1) | ||
|
|
||
| Comment | ||
| |> Ash.Changeset.for_create(:create, %{title: "second"}) | ||
| |> Ash.Changeset.manage_relationship(:post, post, type: :append_and_remove) | ||
| |> Ash.create!() | ||
|
|
||
| # second_latest_comment: sort(created_at: :desc), offset(1) => first comment | ||
| assert %{id: ^first_comment_id} = | ||
| Post | ||
| |> Ash.Query.load(:second_latest_comment) | ||
| |> Ash.read_one!() | ||
| |> Map.get(:second_latest_comment) | ||
| end |
There was a problem hiding this comment.
This test only inserts two comments, so offset(1) happens to leave a single remaining row even if the underlying lateral-join subquery doesn't apply limit: 1. To actually validate the "pick exactly one row after offset" behavior, add a third (or more) comment and assert the loaded second_latest_comment is still exactly the second-by-sort record (not any later record).
Summary
relationship.offsettobase_queryin lateral join queriessecond_latest_commenttest relationship (has_one with sort + offset)Related
Test plan
🤖 Generated with Claude Code