Skip to content

Commit 7546fdb

Browse files
committed
test: aggregate with parent ref in relationship filter and sorting on relationship field
1 parent 14397be commit 7546fdb

File tree

2 files changed

+86
-0
lines changed

2 files changed

+86
-0
lines changed

test/aggregate_test.exs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ defmodule AshSql.AggregateTest do
88
alias AshPostgres.Test.{Author, Chat, Comment, Organization, Post, Rating, User}
99

1010
require Ash.Query
11+
require Ash.Sort
1112
import Ash.Expr
1213

1314
test "nested sum aggregates" do
@@ -1920,6 +1921,81 @@ defmodule AshSql.AggregateTest do
19201921
end
19211922
end
19221923

1924+
test "aggregate with parent() ref in relationship filter and sorting on relationship field" do
1925+
chat_1 =
1926+
Chat
1927+
|> Ash.Changeset.for_create(:create, %{name: "Test Chat"})
1928+
|> Ash.create!()
1929+
1930+
chat_1_message_1 =
1931+
AshPostgres.Test.Message
1932+
|> Ash.Changeset.for_create(:create, %{
1933+
chat_id: chat_1.id,
1934+
content: "First message",
1935+
sent_at: DateTime.add(DateTime.utc_now(), -3600, :second)
1936+
})
1937+
|> Ash.create!()
1938+
1939+
_chat_1_message_2 =
1940+
AshPostgres.Test.Message
1941+
|> Ash.Changeset.for_create(:create, %{
1942+
chat_id: chat_1.id,
1943+
content: "Second message",
1944+
sent_at: DateTime.add(DateTime.utc_now(), -1800, :second)
1945+
})
1946+
|> Ash.create!()
1947+
1948+
# Update chat to set last_read_message to the first message
1949+
# This means message_2 should be "unread"
1950+
_chat =
1951+
chat_1
1952+
|> Ash.Changeset.for_update(:update, %{last_read_message_id: chat_1_message_1.id})
1953+
|> Ash.update!()
1954+
1955+
# Create a second chat to force multiple records and trigger DISTINCT ON
1956+
chat_2 =
1957+
Chat
1958+
|> Ash.Changeset.for_create(:create, %{name: "Test Chat 2"})
1959+
|> Ash.create!()
1960+
1961+
chat_2_message_1 =
1962+
AshPostgres.Test.Message
1963+
|> Ash.Changeset.for_create(:create, %{
1964+
chat_id: chat_2.id,
1965+
content: "Chat 2 - Message 1",
1966+
sent_at: DateTime.add(DateTime.utc_now(), -100, :second)
1967+
})
1968+
|> Ash.create!()
1969+
1970+
AshPostgres.Test.Message
1971+
|> Ash.Changeset.for_create(:create, %{
1972+
chat_id: chat_2.id,
1973+
content: "Chat 2 - Message 2",
1974+
sent_at: DateTime.utc_now()
1975+
})
1976+
|> Ash.create!()
1977+
1978+
chat_2
1979+
|> Ash.Changeset.for_update(:update, %{last_read_message_id: chat_2_message_1.id})
1980+
|> Ash.update!()
1981+
1982+
# This query should work but fails without the fix:
1983+
# - select() excludes last_read_message_id from the query
1984+
# - Sorting by last_message.sent_at (has_one from_many?) causes DISTINCT ON + subquery wrapping
1985+
# - Loading unread_messages_count_alt (aggregate on relationship with parent() in filter)
1986+
# uses a lateral join that references parent(last_read_message_id)
1987+
# - The wrapped subquery doesn't include last_read_message_id, so the lateral join fails
1988+
result =
1989+
Chat
1990+
|> Ash.Query.filter(id in [^chat_1.id, ^chat_2.id])
1991+
|> Ash.Query.select([:id, :name])
1992+
|> Ash.Query.load(:unread_messages_count_alt)
1993+
|> Ash.Query.sort([{Ash.Sort.expr_sort(expr(last_message.sent_at)), :asc}])
1994+
|> Ash.read!()
1995+
1996+
assert length(result) == 2
1997+
end
1998+
19231999
test "multiple aggregates filtering on nested first aggregate" do
19242000
post =
19252001
Post

test/support/resources/chat.ex

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,22 @@ defmodule AshPostgres.Test.Chat do
4646
filter(expr(is_nil(read_at)))
4747
sort(sent_at: :desc)
4848
end
49+
50+
has_many :unread_messages, AshPostgres.Test.Message do
51+
public?(true)
52+
no_attributes?(true)
53+
filter(expr(is_nil(parent(last_read_message_id)) or id > parent(last_read_message_id)))
54+
end
4955
end
5056

5157
aggregates do
5258
count :unread_message_count, :messages do
5359
public?(true)
5460
filter(expr(is_nil(parent(last_read_message_id)) or id > parent(last_read_message_id)))
5561
end
62+
63+
count :unread_messages_count_alt, :unread_messages do
64+
public?(true)
65+
end
5666
end
5767
end

0 commit comments

Comments
 (0)