@@ -104,6 +104,60 @@ defmodule AshSql.Atomics do
104104 end
105105 end
106106
107+ @ doc """
108+ Converts atomics to subquery values suitable for insert_all.
109+
110+ Returns `{:ok, map}` where map contains `{field => subquery}` pairs.
111+ Each subquery returns a single value that can be used as a field value in insert_all.
112+
113+ All changesets in a batch share the same atomics (Ash groups by atomics before dispatch).
114+ """
115+ def atomics_to_insert_values ( _resource , _query , [ ] ) , do: { :ok , % { } }
116+
117+ def atomics_to_insert_values ( resource , query , atomics ) do
118+ atomics = type_atomics ( query . __ash_bindings__ . sql_behaviour , resource , atomics )
119+
120+ Enum . reduce_while ( atomics , { :ok , % { } } , fn { field , expr } , { :ok , acc } ->
121+ attribute = Ash.Resource.Info . attribute ( resource , field )
122+
123+ expr = unwrap_type ( expr )
124+
125+ expr =
126+ if AshSql.Calculation . map_type? ( attribute . type , attribute . constraints || [ ] ) do
127+ expr
128+ else
129+ maybe_cast_atomic_expr (
130+ expr ,
131+ attribute ,
132+ query . __ash_bindings__ . sql_behaviour ,
133+ resource
134+ )
135+ end
136+
137+ type =
138+ case query . __ash_bindings__ . sql_behaviour . storage_type ( resource , attribute . name ) do
139+ nil -> { attribute . type , attribute . constraints }
140+ storage_type -> storage_type
141+ end
142+
143+ case AshSql.Expr . dynamic_expr ( query , expr , query . __ash_bindings__ , false , type ) do
144+ { dynamic , _acc } ->
145+ subquery =
146+ Ecto.Query . from ( row in fragment ( "(VALUES(1))" ) , select: ^ dynamic )
147+ |> Map . put ( :__ash_bindings__ , query . __ash_bindings__ )
148+
149+ { :cont , { :ok , Map . put ( acc , field , subquery ) } }
150+
151+ other ->
152+ { :halt , other }
153+ end
154+ end )
155+ end
156+
157+ defp unwrap_type ( % Ash.Query.Function.Type { arguments: [ expr | _ ] } ) , do: expr
158+ defp unwrap_type ( % Ash.Query.Call { name: :type , args: [ expr | _ ] } ) , do: expr
159+ defp unwrap_type ( expr ) , do: expr
160+
107161 def set_subquery_prefix ( sub_query , query ) do
108162 % {
109163 sub_query
0 commit comments