@@ -505,12 +505,14 @@ defmodule Ash.Actions.Read.Relationships do
505505 tenant: related_query . tenant
506506 } )
507507 |> case do
508- { :ok , records } ->
509- records
510- |> Enum . flat_map ( fn { key , value } ->
508+ { :ok , result_records } ->
509+ result_records
510+ |> normalize_manual_results ( records , relationship )
511+ |> Enum . with_index ( )
512+ |> Enum . flat_map ( fn { value , index } ->
511513 value
512514 |> List . wrap ( )
513- |> Enum . map ( & Ash.Resource . put_metadata ( & 1 , :manual_key , key ) )
515+ |> Enum . map ( & Ash.Resource . put_metadata ( & 1 , :manual_key , index ) )
514516 end )
515517 |> Ash . load ( related_query ,
516518 domain: related_query . domain ,
@@ -520,7 +522,7 @@ defmodule Ash.Actions.Read.Relationships do
520522 )
521523 |> case do
522524 { :ok , results } ->
523- { :ok , regroup_manual_results ( results , relationship ) }
525+ { :ok , regroup_manual_results ( results , relationship , Enum . count ( records ) ) }
524526
525527 { :error , error } ->
526528 { :error , error }
@@ -870,18 +872,126 @@ defmodule Ash.Actions.Read.Relationships do
870872 end )
871873 end
872874
873- defp regroup_manual_results ( records , % { cardinality: :many } ) do
874- Enum . group_by ( records , & & 1 . __metadata__ . manual_key , & delete_manual_key / 1 )
875+ defp regroup_manual_results ( records , % { cardinality: :many } , count ) do
876+ indexed_records =
877+ Enum . group_by ( records , & & 1 . __metadata__ . manual_key , & delete_manual_key / 1 )
878+
879+ Enum . map ( 0 .. max ( count - 1 , 0 ) , fn index ->
880+ Map . get ( indexed_records , index , [ ] )
881+ end )
875882 end
876883
877- defp regroup_manual_results ( records , % { cardinality: :one } ) do
878- Map . new ( records , & { & 1 . __metadata__ . manual_key , delete_manual_key ( & 1 ) } )
884+ defp regroup_manual_results ( records , % { cardinality: :one } , count ) do
885+ indexed_records =
886+ Map . new ( records , fn record ->
887+ { record . __metadata__ . manual_key , delete_manual_key ( record ) }
888+ end )
889+
890+ Enum . map ( 0 .. max ( count - 1 , 0 ) , fn index ->
891+ Map . get ( indexed_records , index )
892+ end )
879893 end
880894
881895 defp delete_manual_key ( record ) do
882896 Map . update! ( record , :__metadata__ , & Map . delete ( & 1 , :manual_key ) )
883897 end
884898
899+ defp normalize_manual_results ( result_records , [ % resource { } | _ ] = records , relationship )
900+ when is_map ( result_records ) do
901+ default =
902+ case relationship . cardinality do
903+ :one ->
904+ nil
905+
906+ :many ->
907+ [ ]
908+ end
909+
910+ if Ash.Resource.Info . primary_key_simple_equality? ( resource ) do
911+ pkey = Ash.Resource.Info . primary_key ( resource )
912+
913+ single_match? =
914+ case pkey do
915+ [ _ ] -> true
916+ _ -> false
917+ end
918+
919+ Enum . map ( records , fn record ->
920+ value =
921+ if single_match? do
922+ case Map . fetch ( result_records , Map . get ( record , Enum . at ( pkey , 0 ) ) ) do
923+ { :ok , value } -> { :ok , value }
924+ :error -> Map . fetch ( result_records , Map . take ( record , pkey ) )
925+ end
926+ else
927+ Map . fetch ( result_records , Map . take ( record , pkey ) )
928+ end
929+
930+ case value do
931+ { :ok , result } ->
932+ result
933+
934+ :error ->
935+ default
936+ end
937+ end )
938+ else
939+ pkey = Ash.Resource.Info . primary_key ( resource )
940+
941+ case pkey do
942+ [ pkey_key ] ->
943+ Enum . map ( records , fn record ->
944+ pkey_values = Map . take ( record , pkey )
945+
946+ value =
947+ Enum . find_value ( result_records , fn { key , value } ->
948+ if is_map ( key ) do
949+ if resource . primary_key_matches? ( key , pkey_values ) do
950+ { :ok , value }
951+ end
952+ else
953+ if resource . primary_key_matches? ( % { pkey_key => key } , pkey_values ) do
954+ { :ok , value }
955+ end
956+ end
957+ end ) || :error
958+
959+ case value do
960+ { :ok , result } ->
961+ result
962+
963+ :error ->
964+ default
965+ end
966+ end )
967+
968+ _pkeys ->
969+ Enum . map ( records , fn record ->
970+ pkey_values = Map . take ( record , pkey )
971+
972+ value =
973+ Enum . find_value ( result_records , fn { key , value } ->
974+ if resource . primary_key_matches? ( key , pkey_values ) do
975+ { :ok , value }
976+ end
977+ end ) || :error
978+
979+ case value do
980+ { :ok , result } ->
981+ result
982+
983+ :error ->
984+ default
985+ end
986+ end )
987+ end
988+ end
989+ end
990+
991+ defp normalize_manual_results ( result_records , _records , _relationship ) do
992+ result_records
993+ end
994+
885995 defp select_destination_attribute ( related_query , relationship ) do
886996 if Map . get ( relationship , :no_attributes? ) ||
887997 ( Map . get ( relationship , :manual ) &&
@@ -1082,99 +1192,25 @@ defmodule Ash.Actions.Read.Relationships do
10821192 end
10831193
10841194 defp do_attach_related_records (
1085- [ % resource { } | _ ] = records ,
1195+ records ,
10861196 % { manual: { _module , _opts } } = relationship ,
1087- map ,
1197+ values ,
10881198 _related_query
10891199 ) do
10901200 default =
10911201 case relationship . cardinality do
1092- :one ->
1093- nil
1094-
1095- :many ->
1096- [ ]
1202+ :one -> nil
1203+ :many -> [ ]
10971204 end
10981205
1099- if Ash.Resource.Info . primary_key_simple_equality? ( resource ) do
1100- pkey = Ash.Resource.Info . primary_key ( resource )
1101-
1102- single_match? =
1103- case pkey do
1104- [ _ ] -> true
1105- _ -> false
1106- end
1107-
1108- Enum . map ( records , fn record ->
1109- value =
1110- if single_match? do
1111- case Map . fetch ( map , Map . get ( record , Enum . at ( pkey , 0 ) ) ) do
1112- { :ok , value } -> { :ok , value }
1113- :error -> Map . fetch ( map , Map . take ( record , pkey ) )
1114- end
1115- else
1116- Map . fetch ( map , Map . take ( record , pkey ) )
1117- end
1118-
1119- case value do
1120- { :ok , result } ->
1121- Map . put ( record , relationship . name , result )
1122-
1123- :error ->
1124- Map . put ( record , relationship . name , default )
1125- end
1126- end )
1127- else
1128- pkey = Ash.Resource.Info . primary_key ( resource )
1129-
1130- case pkey do
1131- [ pkey_key ] ->
1132- Enum . map ( records , fn record ->
1133- pkey_values = Map . take ( record , pkey )
1134-
1135- value =
1136- Enum . find_value ( map , fn { key , value } ->
1137- if is_map ( key ) do
1138- if resource . primary_key_matches? ( key , pkey_values ) do
1139- { :ok , value }
1140- end
1141- else
1142- if resource . primary_key_matches? ( % { pkey_key => key } , pkey_values ) do
1143- { :ok , value }
1144- end
1145- end
1146- end ) || :error
1147-
1148- case value do
1149- { :ok , result } ->
1150- Map . put ( record , relationship . name , result )
1151-
1152- :error ->
1153- Map . put ( record , relationship . name , default )
1154- end
1155- end )
1156-
1157- _pkeys ->
1158- Enum . map ( records , fn record ->
1159- pkey_values = Map . take ( record , pkey )
1160-
1161- value =
1162- Enum . find_value ( map , fn { key , value } ->
1163- if resource . primary_key_matches? ( key , pkey_values ) do
1164- { :ok , value }
1165- end
1166- end ) || :error
1167-
1168- case value do
1169- { :ok , result } ->
1170- Map . put ( record , relationship . name , result )
1206+ records
1207+ |> Enum . zip_with ( values , fn
1208+ record , nil ->
1209+ Map . put ( record , relationship . name , default )
11711210
1172- :error ->
1173- Map . put ( record , relationship . name , default )
1174- end
1175- end )
1176- end
1177- end
1211+ record , value ->
1212+ Map . put ( record , relationship . name , value )
1213+ end )
11781214 end
11791215
11801216 defp do_attach_related_records (
0 commit comments