@@ -2207,8 +2207,8 @@ defmodule Ecto.Query.Planner do
22072207 { { :ok , { :struct , _ } } , { :fragment , _ , _ } } ->
22082208 error! ( query , "it is not possible to return a struct subset of a fragment" )
22092209
2210- { { :ok , { :struct , _ } } , % Ecto.SubQuery { } } ->
2211- error! ( query , "it is not possible to return a struct subset of a subquery" )
2210+ { { :ok , { :struct , fields } } , % Ecto.SubQuery { select: select } } ->
2211+ handle_subquery_struct ( select , fields , ix , query )
22122212
22132213 { { :ok , { _ , [ ] } } , { _ , _ , _ } } ->
22142214 error! (
@@ -2280,6 +2280,39 @@ defmodule Ecto.Query.Planner do
22802280 end )
22812281 end
22822282
2283+ defp handle_subquery_struct ( select , requested_fields , ix , query ) do
2284+ available_fields = subquery_source_fields ( select )
2285+ requested_fields = List . wrap ( requested_fields )
2286+
2287+ Enum . each ( requested_fields , fn field ->
2288+ unless field in available_fields do
2289+ error! ( query , "field `#{ field } ` in struct/2 is not available in the subquery. " <>
2290+ "Subquery only returns fields: #{ inspect ( available_fields ) } " )
2291+ end
2292+ end )
2293+
2294+ schema =
2295+ case select do
2296+ { :struct , schema , _ } -> schema
2297+ { :source , { _ , schema } , _ , _ } when not is_nil ( schema ) -> schema
2298+ _ ->
2299+ error! ( query , "it is not possible to return a struct subset of a subquery that does not return a schema or a struct" )
2300+ end
2301+
2302+ types =
2303+ Enum . map ( requested_fields , fn field ->
2304+ { :ok , type } = subquery_type_for ( select , field )
2305+ { field , type }
2306+ end )
2307+
2308+ field_exprs =
2309+ Enum . map ( types , fn { field , type } ->
2310+ { { :. , [ type: type ] , [ { :& , [ ] , [ ix ] } , field ] } , [ ] , [ ] }
2311+ end )
2312+
2313+ { { :source , { nil , schema } , nil , types } , field_exprs }
2314+ end
2315+
22832316 defp select_field ( field , ix , writable ) do
22842317 { { :. , [ writable: writable ] , [ { :& , [ ] , [ ix ] } , field ] } , [ ] , [ ] }
22852318 end
0 commit comments