@@ -1863,30 +1863,7 @@ defmodule AshPostgres.DataLayer do
18631863embedded? ,
18641864_type
18651865) do
1866- { left_type , right_type } =
1867- case determine_type ( mod , left ) do
1868- nil ->
1869- case determine_type ( mod , right , true ) do
1870- nil ->
1871- { nil , nil }
1872-
1873- left_type ->
1874- { left_type , nil }
1875- end
1876-
1877- right_type ->
1878- if vague? ( right_type ) do
1879- case determine_type ( mod , right , true ) do
1880- nil ->
1881- { nil , right_type }
1882-
1883- left_type ->
1884- { left_type , nil }
1885- end
1886- else
1887- { nil , right_type }
1888- end
1889- end
1866+ [ left_type , right_type ] = determine_types ( mod , [ left , right ] )
18901867
18911868{ params , left_expr } =
18921869do_filter_to_expr ( left , bindings , params , pred_embedded? || embedded? , left_type )
@@ -1966,76 +1943,101 @@ defmodule AshPostgres.DataLayer do
19661943value
19671944end
19681945
1969- defp determine_type ( mod , ref , flip? \\ false )
1946+ defp determine_types ( mod , values ) do
1947+ mod . types ( )
1948+ |> Enum . map ( fn types ->
1949+ case types do
1950+ :same ->
1951+ types =
1952+ for _ <- values do
1953+ :same
1954+ end
19701955
1971- defp determine_type ( mod , % Ref { attribute: % { type: type } } , flip? ) do
1972- Enum . find_value ( mod . types ( ) , fn types ->
1973- types =
1974- case types do
1975- :same ->
1976- [ type ]
1956+ closest_fitting_type ( types , values )
19771957
1978- :any ->
1979- [ ]
1958+ :any ->
1959+ for _ <- values do
1960+ :any
1961+ end
19801962
1981- other when is_list ( other ) ->
1982- other =
1983- if flip? do
1984- Enum . reverse ( other )
1985- else
1986- other
1987- end
1963+ types ->
1964+ closest_fitting_type ( types , values )
1965+ end
1966+ end )
1967+ |> Enum . min_by ( fn types ->
1968+ types
1969+ |> Enum . map ( & vagueness / 1 )
1970+ |> Enum . sum ( )
1971+ end )
1972+ end
19881973
1989- Enum . map ( other , fn
1990- { :array , :any } ->
1991- { :in , :any }
1974+ defp closest_fitting_type ( types , values ) do
1975+ types_with_values = Enum . zip ( types , values )
19921976
1993- { :array , :same } ->
1994- { :in , type }
1977+ types_with_values
1978+ |> fill_in_known_types ( )
1979+ |> clarify_types ( )
1980+ end
19951981
1996- { :array , type } ->
1997- { :in , type }
1982+ defp clarify_types ( types ) do
1983+ basis =
1984+ types
1985+ |> Enum . map ( & elem ( & 1 , 0 ) )
1986+ |> Enum . min_by ( & vagueness ( & 1 ) )
19981987
1999- type ->
2000- type
2001- end )
1988+ Enum . map ( types , fn { type , _value } ->
1989+ replace_same ( type , basis )
1990+ end )
1991+ end
20021992
2003- other ->
2004- [ other ]
2005- end
1993+ defp replace_same ( { :in , type } , basis ) do
1994+ { :in , replace_same ( type , basis ) }
1995+ end
20061996
2007- types
2008- |> Enum . sort_by ( & vague? / 1 )
2009- |> Enum . at ( 0 )
2010- |> case do
2011- nil ->
2012- nil
1997+ defp replace_same ( :same , :same ) do
1998+ :any
1999+ end
20132000
2014- { :in , :any } ->
2015- { :in , :any }
2001+ defp replace_same ( :same , { :in , :same } ) do
2002+ { :in , :any }
2003+ end
20162004
2017- { :in , type } ->
2018- if Ash.Type . ash_type? ( type ) do
2019- { :in , Ash.Type . storage_type ( type ) }
2020- else
2021- { :in , type }
2022- end
2005+ defp replace_same ( :same , basis ) do
2006+ basis
2007+ end
20232008
2024- type ->
2025- if Ash.Type . ash_type? ( type ) do
2026- Ash.Type . storage_type ( type )
2027- else
2028- type
2029- end
2030- end
2031- end )
2009+ defp replace_same ( other , _basis ) do
2010+ other
20322011end
20332012
2034- defp determine_type ( _mod , _ , _ ) , do: nil
2013+ defp fill_in_known_types ( types ) do
2014+ Enum . map ( types , & fill_in_known_type / 1 )
2015+ end
2016+
2017+ defp fill_in_known_type ( { vague_type , % Ref { attribute: % { type: type } } } = ref )
2018+ when vague_type in [ :any , :same ] do
2019+ if Ash.Type . ash_type? ( type ) do
2020+ { type |> Ash.Type . storage_type ( ) |> array_to_in ( ) , ref }
2021+ else
2022+ { type |> array_to_in ( ) , ref }
2023+ end
2024+ end
2025+
2026+ defp fill_in_known_type (
2027+ { { :array , type } , % Ref { attribute: % { type: { :array , type } } = attribute } = ref }
2028+ ) do
2029+ { :in , fill_in_known_type ( { type , % { ref | attribute: % { attribute | type: type } } } ) }
2030+ end
2031+
2032+ defp fill_in_known_type ( { type , value } ) , do: { array_to_in ( type ) , value }
2033+
2034+ defp array_to_in ( { :array , v } ) , do: { :in , array_to_in ( v ) }
2035+ defp array_to_in ( v ) , do: v
20352036
2036- defp vague? ( { :in , :any } ) , do: true
2037- defp vague? ( :any ) , do: true
2038- defp vague? ( _ ) , do: false
2037+ defp vagueness ( { :in , type } ) , do: vagueness ( type )
2038+ defp vagueness ( :same ) , do: 2
2039+ defp vagueness ( :any ) , do: 1
2040+ defp vagueness ( _ ) , do: 0
20392041
20402042defp ref_binding ( ref , bindings ) do
20412043case ref . attribute do