Skip to content

Commit c753a37

Browse files
committed
fix: fix invalid select on sorting by some calculations
1 parent 27837d1 commit c753a37

File tree

4 files changed

+19
-109
lines changed

4 files changed

+19
-109
lines changed

lib/data_layer.ex

Lines changed: 9 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -759,7 +759,7 @@ defmodule AshPostgres.DataLayer do
759759
query,
760760
AshSql.repo_opts(repo, AshPostgres.SqlImplementation, nil, nil, resource)
761761
)
762-
|> remap_mapped_fields(query)}
762+
|> AshSql.Query.remap_mapped_fields(query)}
763763
end)
764764
end
765765
rescue
@@ -942,7 +942,7 @@ defmodule AshPostgres.DataLayer do
942942
path
943943
) do
944944
{calculations_require_rewrite, aggregates_require_rewrite, query} =
945-
rewrite_nested_selects(query)
945+
AshSql.Query.rewrite_nested_selects(query)
946946

947947
case lateral_join_query(
948948
query,
@@ -964,7 +964,11 @@ defmodule AshPostgres.DataLayer do
964964
lateral_join_query,
965965
AshSql.repo_opts(repo, AshPostgres.SqlImplementation, nil, nil, source_resource)
966966
)
967-
|> remap_mapped_fields(query, calculations_require_rewrite, aggregates_require_rewrite)
967+
|> AshSql.Query.remap_mapped_fields(
968+
query,
969+
calculations_require_rewrite,
970+
aggregates_require_rewrite
971+
)
968972

969973
{:ok, results}
970974

@@ -973,100 +977,6 @@ defmodule AshPostgres.DataLayer do
973977
end
974978
end
975979

976-
defp rewrite_nested_selects(query) do
977-
case query.select do
978-
%Ecto.Query.SelectExpr{
979-
expr:
980-
{:merge, [],
981-
[
982-
{:&, [], [0]},
983-
{:%{}, [], merging}
984-
]}
985-
} = select ->
986-
{merging, aggregate_merges} = remap_sub_select(merging, :aggregates)
987-
988-
{new_sub_selects, calculation_merges} =
989-
remap_sub_select(merging, :calculations)
990-
991-
new_query =
992-
%{
993-
query
994-
| select: %{select | expr: {:merge, [], [{:&, [], [0]}, {:%{}, [], new_sub_selects}]}}
995-
}
996-
997-
{calculation_merges, aggregate_merges, new_query}
998-
999-
_ ->
1000-
{%{}, %{}, query}
1001-
end
1002-
end
1003-
1004-
# sobelow_skip ["DOS.StringToAtom"]
1005-
defp remap_sub_select(merging, sub_key) do
1006-
case Keyword.fetch(merging, sub_key) do
1007-
{:ok, {:%{}, [], nested}} ->
1008-
Enum.reduce(nested, {Keyword.delete(merging, sub_key), %{}}, fn {name, expr},
1009-
{subselect, remapping} ->
1010-
new_name = String.to_atom("__#{sub_key}__#{name}")
1011-
{Keyword.put(subselect, new_name, expr), Map.put(remapping, new_name, name)}
1012-
end)
1013-
1014-
:error ->
1015-
{merging, %{}}
1016-
end
1017-
end
1018-
1019-
defp remap_mapped_fields(
1020-
results,
1021-
query,
1022-
calculations_require_rewrite \\ %{},
1023-
aggregates_require_rewrite \\ %{}
1024-
) do
1025-
calculation_names = query.__ash_bindings__.calculation_names
1026-
aggregate_names = query.__ash_bindings__.aggregate_names
1027-
1028-
if Enum.empty?(calculation_names) and Enum.empty?(aggregate_names) and
1029-
Enum.empty?(calculations_require_rewrite) and Enum.empty?(aggregates_require_rewrite) do
1030-
results
1031-
else
1032-
Enum.map(results, fn result ->
1033-
result
1034-
|> remap_to_nested(:calculations, calculations_require_rewrite)
1035-
|> remap_to_nested(:aggregates, aggregates_require_rewrite)
1036-
|> remap(:calculations, calculation_names)
1037-
|> remap(:aggregates, aggregate_names)
1038-
end)
1039-
end
1040-
end
1041-
1042-
defp remap_to_nested(record, _subfield, mapping) when mapping == %{} do
1043-
record
1044-
end
1045-
1046-
defp remap_to_nested(record, subfield, mapping) do
1047-
Map.update!(record, subfield, fn subfield_values ->
1048-
Enum.reduce(mapping, subfield_values, fn {source, dest}, subfield_values ->
1049-
subfield_values
1050-
|> Map.put(dest, Map.get(record, source))
1051-
|> Map.delete(source)
1052-
end)
1053-
end)
1054-
end
1055-
1056-
defp remap(record, _subfield, mapping) when mapping == %{} do
1057-
record
1058-
end
1059-
1060-
defp remap(record, subfield, mapping) do
1061-
Map.update!(record, subfield, fn subfield_values ->
1062-
Enum.reduce(mapping, subfield_values, fn {dest, source}, subfield_values ->
1063-
subfield_values
1064-
|> Map.put(dest, Map.get(subfield_values, source))
1065-
|> Map.delete(source)
1066-
end)
1067-
end)
1068-
end
1069-
1070980
defp lateral_join_query(
1071981
query,
1072982
root_data,
@@ -1425,7 +1335,7 @@ defmodule AshPostgres.DataLayer do
14251335
end)
14261336

14271337
if options[:return_records?] do
1428-
{:ok, remap_mapped_fields(results, query)}
1338+
{:ok, AshSql.Query.remap_mapped_fields(results, query)}
14291339
else
14301340
:ok
14311341
end
@@ -1691,7 +1601,7 @@ defmodule AshPostgres.DataLayer do
16911601
end)
16921602

16931603
if options[:return_records?] do
1694-
{:ok, remap_mapped_fields(results, query)}
1604+
{:ok, AshSql.Query.remap_mapped_fields(results, query)}
16951605
else
16961606
:ok
16971607
end

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ defmodule AshPostgres.MixProject do
163163
defp deps do
164164
[
165165
{:ash, ash_version("~> 3.0 and >= 3.0.7")},
166-
{:ash_sql, ash_sql_version("~> 0.2 and >= 0.2.3")},
166+
{:ash_sql, ash_sql_version("~> 0.2 and >= 0.2.4")},
167167
{:ecto_sql, "~> 3.9"},
168168
{:ecto, "~> 3.9"},
169169
{:jason, "~> 1.0"},

mix.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
"spark": {:hex, :spark, "2.1.24", "fb596da83ee85b83f27f3a98df226869963ec5e423b4137884a6176f332e84ff", [:mix], [{:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.0", [hex: :sourceror, repo: "hexpm", optional: false]}], "hexpm", "e57f62fe1de1b327c2bfe04473496497edb6817371ba677099389deda38da90d"},
3535
"splode": {:hex, :splode, "0.2.4", "71046334c39605095ca4bed5d008372e56454060997da14f9868534c17b84b53", [:mix], [], "hexpm", "ca3b95f0d8d4b482b5357954fec857abd0fa3ea509d623334c1328e7382044c2"},
3636
"statistex": {:hex, :statistex, "1.0.0", "f3dc93f3c0c6c92e5f291704cf62b99b553253d7969e9a5fa713e5481cd858a5", [:mix], [], "hexpm", "ff9d8bee7035028ab4742ff52fc80a2aa35cece833cf5319009b52f1b5a86c27"},
37-
"stream_data": {:hex, :stream_data, "1.1.0", "ef3a7cac0f200c43caf3e6caf9be63115851b4f1cde3f21afaab220adc40e3d7", [:mix], [], "hexpm", "cccc411d5facf1bab86e7c671382d164f05f8992574c95349d3c8b317e14d953"},
37+
"stream_data": {:hex, :stream_data, "1.1.1", "fd515ca95619cca83ba08b20f5e814aaf1e5ebff114659dc9731f966c9226246", [:mix], [], "hexpm", "45d0cd46bd06738463fd53f22b70042dbb58c384bb99ef4e7576e7bb7d3b8c8c"},
3838
"telemetry": {:hex, :telemetry, "1.2.1", "68fdfe8d8f05a8428483a97d7aab2f268aaff24b49e0f599faa091f1d4e7f61c", [:rebar3], [], "hexpm", "dad9ce9d8effc621708f99eac538ef1cbe05d6a874dd741de2e689c47feafed5"},
3939
"typable": {:hex, :typable, "0.3.0", "0431e121d124cd26f312123e313d2689b9a5322b15add65d424c07779eaa3ca1", [:mix], [], "hexpm", "880a0797752da1a4c508ac48f94711e04c86156f498065a83d160eef945858f8"},
4040
"yamerl": {:hex, :yamerl, "0.10.0", "4ff81fee2f1f6a46f1700c0d880b24d193ddb74bd14ef42cb0bcf46e81ef2f8e", [:rebar3], [], "hexpm", "346adb2963f1051dc837a2364e4acf6eb7d80097c0f53cbdc3046ec8ec4b4e6e"},

test/sort_test.exs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -231,20 +231,18 @@ defmodule AshPostgres.SortTest do
231231
|> Ash.Changeset.for_create(:create, %{title: "aaa", score: 0})
232232
|> Ash.create!()
233233

234-
view1 =
235-
PostView
236-
|> Ash.Changeset.for_action(:create, %{browser: :firefox, post_id: post1.id})
237-
|> Ash.create!()
234+
PostView
235+
|> Ash.Changeset.for_action(:create, %{browser: :firefox, post_id: post1.id})
236+
|> Ash.create!()
238237

239238
post2 =
240239
Post
241240
|> Ash.Changeset.for_create(:create, %{title: "bbb", score: 0})
242241
|> Ash.create!()
243242

244-
view2 =
245-
PostView
246-
|> Ash.Changeset.for_action(:create, %{browser: :chrome, post_id: post2.id})
247-
|> Ash.create!()
243+
PostView
244+
|> Ash.Changeset.for_action(:create, %{browser: :chrome, post_id: post2.id})
245+
|> Ash.create!()
248246

249247
assert [
250248
%{title: "aaa", views: [%{browser: :firefox}]},
@@ -263,6 +261,8 @@ defmodule AshPostgres.SortTest do
263261
Ash.read!(
264262
Post
265263
|> Ash.Query.load(:views)
264+
# this doesn't really make sense to do, you'd want to do something like `max(views, field: :time)` or something.
265+
# but it illustrates a bug fix, and nothing currently prevents you from doing it, so we keep the test for now.
266266
|> Ash.Query.sort({Ash.Sort.expr_sort(views.time, :datetime), :desc}, title: :asc)
267267
)
268268
end

0 commit comments

Comments
 (0)