Skip to content

Commit 77e88ca

Browse files
committed
fix: filter query by source record ids when lateral joining
1 parent b02065c commit 77e88ca

File tree

1 file changed

+35
-1
lines changed

1 file changed

+35
-1
lines changed

lib/query.ex

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
defmodule AshSql.Query do
22
@moduledoc false
33
import Ecto.Query, only: [subquery: 1, from: 2]
4+
require Ash.Expr
45

56
def resource_to_query(resource, implementation, domain \\ nil) do
67
from(row in {implementation.table(resource) || "", resource}, [])
@@ -35,7 +36,7 @@ defmodule AshSql.Query do
3536

3637
data_layer_query =
3738
case context[:data_layer][:lateral_join_source] do
38-
{_data, path} ->
39+
{data, path} ->
3940
lateral_join_source_query = path |> List.first() |> elem(0)
4041

4142
lateral_join_source_query.resource
@@ -44,6 +45,7 @@ defmodule AshSql.Query do
4445
})
4546
|> Ash.Query.set_tenant(lateral_join_source_query.tenant)
4647
|> set_lateral_join_prefix(data_layer_query)
48+
|> filter_for_records(data)
4749
|> case do
4850
%{valid?: true} = query ->
4951
Ash.Query.data_layer_query(query)
@@ -119,6 +121,38 @@ defmodule AshSql.Query do
119121
end
120122
end
121123

124+
defp filter_for_records(query, records) do
125+
keys =
126+
case Ash.Resource.Info.primary_key(query.resource) do
127+
[] ->
128+
case Ash.Resource.Info.identities(query.resource) do
129+
%{keys: keys} -> keys
130+
_ -> []
131+
end
132+
133+
pkey ->
134+
pkey
135+
end
136+
137+
expr =
138+
case keys do
139+
[] ->
140+
raise "Cannot use lateral joins with a resource that has no primary key and no identities"
141+
142+
keys ->
143+
Enum.reduce(records, Ash.Expr.expr(false), fn record, filter_expr ->
144+
all_keys_match_expr =
145+
Enum.reduce(keys, Ash.Expr.expr(true), fn key, key_expr ->
146+
Ash.Expr.expr(^key_expr and ^Ash.Expr.ref(key) == ^Map.get(record, key))
147+
end)
148+
149+
Ash.Expr.expr(^filter_expr or ^all_keys_match_expr)
150+
end)
151+
end
152+
153+
Ash.Query.do_filter(query, expr)
154+
end
155+
122156
def return_query(%{__ash_bindings__: %{lateral_join?: true}} = query, resource) do
123157
query =
124158
AshSql.Bindings.default_bindings(query, resource, query.__ash_bindings__.sql_behaviour)

0 commit comments

Comments
 (0)