@@ -82,6 +82,34 @@ defmodule AshSql.Join do
8282 parent_query ,
8383 no_inner_join?
8484 ) do
85+ do_join_all_relationships (
86+ query ,
87+ filter ,
88+ opts ,
89+ relationship_paths ,
90+ path ,
91+ source ,
92+ sort? ,
93+ join_filters ,
94+ parent_query ,
95+ no_inner_join? ,
96+ nil
97+ )
98+ end
99+
100+ defp do_join_all_relationships (
101+ query ,
102+ filter ,
103+ opts ,
104+ relationship_paths ,
105+ path ,
106+ source ,
107+ sort? ,
108+ join_filters ,
109+ parent_query ,
110+ no_inner_join? ,
111+ aggregates_by_path
112+ ) do
85113 no_inner_join? = left_join_only? ( query , opts , no_inner_join? )
86114
87115 case join_parent_paths ( query , filter , relationship_paths ) do
@@ -108,6 +136,12 @@ defmodule AshSql.Join do
108136 { updated_query , relationship_paths ++ parent_relationship_paths }
109137 end
110138
139+ aggregates_by_path =
140+ aggregates_by_path ||
141+ if Enum . any? ( relationship_paths , & match? ( { _join_type , [ _ | _ ] } , & 1 ) ) do
142+ aggregates_by_path ( filter )
143+ end
144+
111145 Enum . reduce_while ( relationship_paths , { :ok , query } , fn
112146 { _join_type , [ ] } , { :ok , query } ->
113147 { :cont , { :ok , query } }
@@ -144,7 +178,7 @@ defmodule AshSql.Join do
144178 # We can't reuse joins if we're adding filters/have a separate parent binding
145179 if is_nil ( join_filters ) && is_nil ( parent_query ) && binding do
146180 full_path = Enum . map ( current_path , & & 1 . name )
147- used_aggregates = Ash.Filter . used_aggregates ( filter , full_path )
181+ used_aggregates = Map . get ( aggregates_by_path , full_path , [ ] )
148182
149183 case AshSql.Aggregate . add_aggregates (
150184 query ,
@@ -155,14 +189,18 @@ defmodule AshSql.Join do
155189 { query . __ash_bindings__ . resource , full_path }
156190 ) do
157191 { :ok , query } ->
158- case join_all_relationships (
192+ case do_join_all_relationships (
159193 query ,
160194 filter ,
161195 opts ,
162196 [ { join_type , rest_rels } ] ,
163197 current_path ,
164198 source ,
165- sort?
199+ sort? ,
200+ nil ,
201+ nil ,
202+ false ,
203+ aggregates_by_path
166204 ) do
167205 { :ok , query } ->
168206 { :cont , { :ok , query } }
@@ -181,14 +219,14 @@ defmodule AshSql.Join do
181219 Enum . map ( path , & & 1 . name ) ,
182220 current_join_type ,
183221 source ,
184- filter ,
222+ aggregates_by_path ,
185223 sort? ,
186224 join_filters [ Enum . map ( current_path , & & 1 . name ) ]
187225 ) do
188226 { :ok , joined_query , _binding } ->
189227 joined_query_with_distinct = add_distinct ( relationship , join_type , joined_query )
190228
191- case join_all_relationships (
229+ case do_join_all_relationships (
192230 joined_query_with_distinct ,
193231 filter ,
194232 opts ,
@@ -207,7 +245,9 @@ defmodule AshSql.Join do
207245 Enum . map ( path , & & 1 . name ) ++ [ relationship . name ]
208246 )
209247 end
210- )
248+ ) ,
249+ false ,
250+ aggregates_by_path
211251 ) do
212252 { :ok , query } ->
213253 { :cont , { :ok , query } }
@@ -227,6 +267,13 @@ defmodule AshSql.Join do
227267 end
228268 end
229269
270+ defp aggregates_by_path ( filter ) do
271+ filter
272+ |> Ash.Filter . used_aggregates ( :* , true )
273+ |> Enum . group_by ( & ( & 1 . relationship_path || [ ] ) , & & 1 . attribute )
274+ |> Map . new ( fn { path , aggregates } -> { path , Enum . uniq ( aggregates ) } end )
275+ end
276+
230277 @ doc false
231278 def join_relationship_path ( query , resource , relationship_path , join_filters ) do
232279 relationships = relationship_path_to_relationships ( resource , relationship_path )
@@ -241,7 +288,7 @@ defmodule AshSql.Join do
241288 path ,
242289 :left ,
243290 resource ,
244- nil ,
291+ % { } ,
245292 false ,
246293 join_filters [ full_path ]
247294 ) do
@@ -1190,7 +1237,7 @@ defmodule AshSql.Join do
11901237 path ,
11911238 kind ,
11921239 source ,
1193- filter ,
1240+ aggregates_by_path ,
11941241 sort? ,
11951242 apply_filter
11961243 ) do
@@ -1201,7 +1248,7 @@ defmodule AshSql.Join do
12011248
12021249 query = AshSql.Bindings . add_binding ( query , binding_data )
12031250
1204- used_aggregates = Ash.Filter . used_aggregates ( filter , full_path )
1251+ used_aggregates = Map . get ( aggregates_by_path , full_path , [ ] )
12051252
12061253 with { :ok , relationship_destination } <-
12071254 related_subquery ( relationship , query ,
@@ -1273,7 +1320,7 @@ defmodule AshSql.Join do
12731320 path ,
12741321 kind ,
12751322 source ,
1276- filter ,
1323+ aggregates_by_path ,
12771324 sort? ,
12781325 apply_filter
12791326 ) do
@@ -1298,7 +1345,7 @@ defmodule AshSql.Join do
12981345 path ,
12991346 kind ,
13001347 source ,
1301- filter ,
1348+ aggregates_by_path ,
13021349 sort? ,
13031350 apply_filter ,
13041351 used_parent_aggregates ,
@@ -1316,7 +1363,7 @@ defmodule AshSql.Join do
13161363
13171364 binding_data = % { type: kind , path: full_path , source: source }
13181365
1319- used_aggregates = Ash.Filter . used_aggregates ( filter , full_path )
1366+ used_aggregates = Map . get ( aggregates_by_path , full_path , [ ] )
13201367
13211368 query =
13221369 query
@@ -1425,7 +1472,7 @@ defmodule AshSql.Join do
14251472 path ,
14261473 kind ,
14271474 source ,
1428- filter ,
1475+ aggregates_by_path ,
14291476 _sort? ,
14301477 apply_filter
14311478 ) do
@@ -1436,7 +1483,7 @@ defmodule AshSql.Join do
14361483
14371484 query = AshSql.Bindings . add_binding ( query , binding_data )
14381485
1439- used_aggregates = Ash.Filter . used_aggregates ( filter , full_path )
1486+ used_aggregates = Map . get ( aggregates_by_path , full_path , [ ] )
14401487
14411488 binding_kinds =
14421489 case kind do
@@ -1633,7 +1680,7 @@ defmodule AshSql.Join do
16331680 path ,
16341681 kind ,
16351682 source ,
1636- filter ,
1683+ aggregates_by_path ,
16371684 sort? ,
16381685 apply_filter ,
16391686 used_parent_aggregates ,
@@ -1650,7 +1697,7 @@ defmodule AshSql.Join do
16501697
16511698 binding_data = % { type: kind , path: full_path , source: source }
16521699
1653- used_aggregates = Ash.Filter . used_aggregates ( filter , full_path )
1700+ used_aggregates = Map . get ( aggregates_by_path , full_path , [ ] )
16541701
16551702 binding_kinds =
16561703 case kind do
0 commit comments