Skip to content

Commit 917e583

Browse files
authored
fix: aggregate with parent ref in relationship filter and sorting on relationship field (#197)
A test covering this fix has been created in ash_postgres
1 parent 4077cf8 commit 917e583

File tree

1 file changed

+52
-1
lines changed

1 file changed

+52
-1
lines changed

lib/query.ex

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -298,8 +298,19 @@ defmodule AshSql.Query do
298298
{calculations_require_rewrite, aggregates_require_rewrite, query} =
299299
rewrite_nested_selects(query)
300300

301+
parent_ref_attrs =
302+
query.__ash_bindings__[:load_aggregates]
303+
|> List.wrap()
304+
|> extract_aggregate_parent_ref_attributes(resource)
305+
306+
query_with_parent_refs =
307+
Enum.reduce(parent_ref_attrs, query, fn attr, query ->
308+
root_binding = query.__ash_bindings__.root_binding
309+
from(row in query, select_merge: %{^attr => field(as(^root_binding), ^attr)})
310+
end)
311+
301312
query_with_order =
302-
from(row in query, select_merge: %{__order__: over(row_number(), :order)})
313+
from(row in query_with_parent_refs, select_merge: %{__order__: over(row_number(), :order)})
303314

304315
query_without_limit_and_offset =
305316
query_with_order
@@ -619,4 +630,44 @@ defmodule AshSql.Query do
619630
end)
620631
end)
621632
end
633+
634+
defp extract_aggregate_parent_ref_attributes(aggregates, resource) do
635+
aggregates
636+
|> Enum.flat_map(fn aggregate ->
637+
case aggregate.relationship_path do
638+
[first_rel_name | _] ->
639+
relationship = Ash.Resource.Info.relationship(resource, first_rel_name)
640+
641+
if relationship && relationship.filter do
642+
extract_parent_attrs_from_filter(relationship.filter)
643+
else
644+
[]
645+
end
646+
647+
_ ->
648+
[]
649+
end
650+
end)
651+
|> Enum.uniq()
652+
end
653+
654+
defp extract_parent_attrs_from_filter(filter) do
655+
Ash.Filter.flat_map(filter, fn
656+
%Ash.Query.Parent{expr: expr} ->
657+
expr
658+
|> Ash.Filter.list_refs()
659+
|> Enum.filter(&Enum.empty?(&1.relationship_path))
660+
|> Enum.map(fn ref ->
661+
case ref.attribute do
662+
%{name: name} -> name
663+
name when is_atom(name) -> name
664+
_ -> nil
665+
end
666+
end)
667+
|> Enum.reject(&is_nil/1)
668+
669+
_other ->
670+
[]
671+
end)
672+
end
622673
end

0 commit comments

Comments
 (0)