@@ -72,8 +72,9 @@ defmodule AshPostgres.DataLayer do
7272}
7373
7474alias Ash.Filter
75- alias Ash.Filter . { Expression , Not , Predicate }
76- alias Ash.Filter.Predicate . { Eq , GreaterThan , In , IsNil , LessThan }
75+ alias Ash.Filter . { Expression , Not , Predicate , Ref }
76+ alias Ash.Filter.Predicate . { GreaterThan , IsNil , LessThan }
77+ alias Ash.Filter.Operator . { Eq , In }
7778alias AshPostgres.Predicates.Trigram
7879
7980import AshPostgres , only: [ table: 1 , repo: 1 ]
@@ -150,8 +151,9 @@ defmodule AshPostgres.DataLayer do
150151def can? ( _ , :filter ) , do: true
151152def can? ( _ , :limit ) , do: true
152153def can? ( _ , :offset ) , do: true
154+ def can? ( _ , { :filter_operator , % Eq { right: % Ref { } } } ) , do: false
155+ def can? ( _ , { :filter_operator , % Eq { left: % Ref { } } } ) , do: true
153156def can? ( _ , { :filter_predicate , _ , % In { } } ) , do: true
154- def can? ( _ , { :filter_predicate , _ , % Eq { } } ) , do: true
155157def can? ( _ , { :filter_predicate , _ , % LessThan { } } ) , do: true
156158def can? ( _ , { :filter_predicate , _ , % GreaterThan { } } ) , do: true
157159def can? ( _ , { :filter_predicate , _ , % IsNil { } } ) , do: true
@@ -886,6 +888,39 @@ defmodule AshPostgres.DataLayer do
886888{ params , { :not , [ ] , [ new_expression ] } }
887889end
888890
891+ defp filter_to_expr (
892+ % Eq { left: % Ref { } = left , right: % Ref { } = right , operator: :== } ,
893+ bindings ,
894+ params
895+ ) do
896+ left = ref_to_field ( left , bindings )
897+ right = ref_to_field ( right , bindings )
898+
899+ { params , { :== , [ ] , [ left , right ] } }
900+ end
901+
902+ defp filter_to_expr (
903+ % Eq { left: % Ref { } = left , right: right } ,
904+ bindings ,
905+ params
906+ ) do
907+ left_ref = ref_to_field ( left , bindings )
908+
909+ { params ++ [ { right , op_type ( left . attribute . type ) } ] ,
910+ { :== , [ ] , [ left_ref , param_binding ( Enum . count ( params ) ) ] } }
911+ end
912+
913+ defp filter_to_expr (
914+ % Eq { left: % Ref { } = left , right: right } ,
915+ bindings ,
916+ params
917+ ) do
918+ left_ref = ref_to_field ( left , bindings )
919+
920+ { params ++ [ { right , op_type ( left . attribute . type ) } ] ,
921+ { :== , [ ] , [ left_ref , param_binding ( Enum . count ( params ) ) ] } }
922+ end
923+
889924defp filter_to_expr ( % Predicate { } = pred , bindings , params ) do
890925% { predicate: predicate , relationship_path: relationship_path , attribute: attribute } = pred
891926
@@ -912,23 +947,25 @@ defmodule AshPostgres.DataLayer do
912947)
913948end
914949
915- defp filter_value_to_expr (
916- attribute ,
917- % Eq { value: value } ,
918- type ,
919- current_binding ,
920- params ,
921- embedded?
922- ) do
923- simple_operator_expr (
924- :== ,
925- params ,
926- value ,
927- type ,
928- current_binding ,
929- attribute ,
930- embedded?
931- )
950+ defp ref_to_field ( ref , bindings ) do
951+ binding =
952+ case ref . attribute do
953+ % Ash.Resource.Attribute { } ->
954+ Enum . find_value ( bindings , fn { binding , data } ->
955+ data . path == ref . relationship_path && data . type in [ :inner , :left , :root ] && binding
956+ end )
957+
958+ % Ash.Query.Aggregate { } = aggregate ->
959+ Enum . find_value ( bindings , fn { binding , data } ->
960+ data . path == aggregate . relationship_path && data . type == :aggregate && binding
961+ end )
962+ end
963+
964+ { { :. , [ ] , [ { :& , [ ] , [ binding ] } , ref . attribute . name ] } , [ ] , [ ] }
965+ end
966+
967+ def param_binding ( ix ) do
968+ { :^ , [ ] , [ ix ] }
932969end
933970
934971defp filter_value_to_expr (