Skip to content

Commit f9bd171

Browse files
authored
fix: handle results that can't be mapped to the changeset in bulk_create (#638)
* fix: handle results that can't be mapped to the changeset in bulk_create If the identity used has attibutes that can be generated by the datalayer, we can't map the result back to the changeset and we need to just zip the results with the changesets and return them that way. * refactor: do a simple check for `upsert?` instead
1 parent d54f93c commit f9bd171

File tree

2 files changed

+49
-14
lines changed

2 files changed

+49
-14
lines changed

lib/data_layer.ex

Lines changed: 36 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2124,34 +2124,57 @@ defmodule AshPostgres.DataLayer do
21242124
end)
21252125

21262126
results =
2127-
changesets
2128-
|> Enum.map(fn changeset ->
2129-
identity =
2130-
changeset.attributes
2131-
|> Map.take(keys)
2127+
if opts[:upsert?] do
2128+
changesets
2129+
|> Enum.map(fn changeset ->
2130+
identity =
2131+
changeset.attributes
2132+
|> Map.take(keys)
21322133

2133-
result_for_changeset = Map.get(results_by_identity, identity)
2134+
result_for_changeset = Map.get(results_by_identity, identity)
21342135

2135-
if result_for_changeset do
2136+
if result_for_changeset do
2137+
if !opts[:upsert?] do
2138+
maybe_create_tenant!(resource, result_for_changeset)
2139+
end
2140+
2141+
case get_bulk_operation_metadata(changeset) do
2142+
{index, metadata_key} ->
2143+
Ash.Resource.put_metadata(result_for_changeset, metadata_key, index)
2144+
2145+
nil ->
2146+
# Compatibility fallback
2147+
Ash.Resource.put_metadata(
2148+
result_for_changeset,
2149+
:bulk_create_index,
2150+
changeset.context[:bulk_create][:index]
2151+
)
2152+
end
2153+
end
2154+
end)
2155+
|> Enum.filter(& &1)
2156+
else
2157+
results
2158+
|> Enum.zip(changesets)
2159+
|> Enum.map(fn {result, changeset} ->
21362160
if !opts[:upsert?] do
2137-
maybe_create_tenant!(resource, result_for_changeset)
2161+
maybe_create_tenant!(resource, result)
21382162
end
21392163

21402164
case get_bulk_operation_metadata(changeset) do
21412165
{index, metadata_key} ->
2142-
Ash.Resource.put_metadata(result_for_changeset, metadata_key, index)
2166+
Ash.Resource.put_metadata(result, metadata_key, index)
21432167

21442168
nil ->
21452169
# Compatibility fallback
21462170
Ash.Resource.put_metadata(
2147-
result_for_changeset,
2171+
result,
21482172
:bulk_create_index,
21492173
changeset.context[:bulk_create][:index]
21502174
)
21512175
end
2152-
end
2153-
end)
2154-
|> Enum.filter(& &1)
2176+
end)
2177+
end
21552178

21562179
{:ok, results}
21572180
end

test/bulk_create_test.exs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
defmodule AshPostgres.BulkCreateTest do
66
use AshPostgres.RepoCase, async: false
7-
alias AshPostgres.Test.{Post, Record}
7+
alias AshPostgres.Test.{IntegerPost, Post, Record}
88

99
require Ash.Query
1010
import Ash.Expr
@@ -356,6 +356,18 @@ defmodule AshPostgres.BulkCreateTest do
356356
|> Ash.Query.load(:ratings)
357357
|> Ash.read!()
358358
end
359+
360+
test "bulk creates with integer primary key return records" do
361+
%Ash.BulkResult{records: records} =
362+
Ash.bulk_create!(
363+
[%{title: "first"}, %{title: "second"}, %{title: "third"}],
364+
IntegerPost,
365+
:create,
366+
return_records?: true
367+
)
368+
369+
assert length(records) == 3
370+
end
359371
end
360372

361373
describe "validation errors" do

0 commit comments

Comments
 (0)