Skip to content

Commit 32ca3b5

Browse files
authored
fix: flatten nested calculation/aggregate maps before wrapping in subquery for aggregates (#206)
When keyset pagination is combined with a relationship sort and loaded aggregates, the query's select contains nested maps like `%{calculations: %{__calc__0: expr}}`. Ecto doesn't allow nested maps in subquery selects, causing an error. This fix reuses `AshSql.Query.rewrite_nested_selects/1` (already used in `distinct.ex` and `query.ex` for the same purpose) to flatten these nested maps before creating the subquery in `wrap_in_subquery_for_aggregates`. Fixes the failing test in ash-project/ash_postgres#677
1 parent 2eb94a3 commit 32ca3b5

File tree

1 file changed

+32
-2
lines changed

1 file changed

+32
-2
lines changed

lib/aggregate.ex

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2548,6 +2548,24 @@ defmodule AshSql.Aggregate do
25482548
)
25492549
end
25502550

2551+
# Flatten nested calculations/aggregates maps before creating subquery
2552+
# Ecto doesn't allow nested maps in subquery select expressions
2553+
{calculations_require_rewrite, aggregates_require_rewrite, query_with_all_attrs} =
2554+
AshSql.Query.rewrite_nested_selects(query_with_all_attrs)
2555+
2556+
# After flattening, we need to:
2557+
# 1. Use the updated select_calculations from the rewritten query (which excludes :calculations)
2558+
# 2. Add the flattened calculation/aggregate field names to the select
2559+
flattened_calc_fields = Map.keys(calculations_require_rewrite)
2560+
flattened_agg_fields = Map.keys(aggregates_require_rewrite)
2561+
2562+
# Get select_calculations from the rewritten query (it has :calculations removed)
2563+
select_calculations =
2564+
(query_with_all_attrs.__ash_bindings__[:select_calculations] || []) -- [:calculations]
2565+
2566+
select_aggregates =
2567+
(query_with_all_attrs.__ash_bindings__[:select_aggregates] || []) -- [:aggregates]
2568+
25512569
subquery_query =
25522570
from(row in subquery(query_with_all_attrs),
25532571
as: ^query.__ash_bindings__.root_binding,
@@ -2556,8 +2574,10 @@ defmodule AshSql.Aggregate do
25562574
row,
25572575
^Enum.concat([
25582576
selected_fields,
2559-
query.__ash_bindings__[:select_calculations] || [],
2560-
query.__ash_bindings__[:select_aggregates] || []
2577+
select_calculations,
2578+
select_aggregates,
2579+
flattened_calc_fields,
2580+
flattened_agg_fields
25612581
])
25622582
)
25632583
)
@@ -2572,6 +2592,16 @@ defmodule AshSql.Aggregate do
25722592
query.__ash_bindings__
25732593
|> Map.put(:bindings, only_root_binding)
25742594
|> Map.delete(:__order__?)
2595+
|> Map.update(
2596+
:calculations_require_rewrite,
2597+
calculations_require_rewrite,
2598+
&Map.merge(&1, calculations_require_rewrite)
2599+
)
2600+
|> Map.update(
2601+
:aggregates_require_rewrite,
2602+
aggregates_require_rewrite,
2603+
&Map.merge(&1, aggregates_require_rewrite)
2604+
)
25752605

25762606
Map.put(subquery_query, :__ash_bindings__, new_bindings)
25772607
end

0 commit comments

Comments
 (0)