diff --git a/spec/interro_spec.cr b/spec/interro_spec.cr index 7d7daca..5bfc832 100644 --- a/spec/interro_spec.cr +++ b/spec/interro_spec.cr @@ -117,6 +117,12 @@ struct UserQuery < Interro::QueryBuilder(User) do: Interro::Update.new(set: {name: name, updated_at: Time.utc}) end + def upsert!(user_templates : Array(Template), name_on_conflict : String) : Int32 + insert! user_templates.map(&.to_named_tuple), + on_conflict: Interro::ConflictHandler.new("email", + do: Interro::Update.new(set: {name: name_on_conflict})) + end + def destroy(user : User) self .where(id: user.id) @@ -457,6 +463,22 @@ describe Interro do UserQuery.new.find!(id: user.id).name.should eq "Bar" end + it "can upsert multiple rows" do + templates = [ + UserQuery::Template.new(email: "ivy-#{UUID.random}@example.com", name: "Ivy"), + UserQuery::Template.new(email: "jack-#{UUID.random}@example.com", name: "Jack"), + ] + + # No rows exist yet, so this only inserts; the conflict update does not run. + query.upsert!(templates, name_on_conflict: "ignored").should eq 2 + UserQuery.new.find!(email: templates[0].email).name.should eq "Ivy" + + # Every row now conflicts on email, so the handler updates each name. + query.upsert!(templates, name_on_conflict: "Updated").should eq 2 + UserQuery.new.find!(email: templates[0].email).name.should eq "Updated" + UserQuery.new.find!(email: templates[1].email).name.should eq "Updated" + end + it "can find a row" do email = "finduser-#{UUID.random}@example.com" created_user = UserQuery.new.create(email: email, name: "Find User") diff --git a/src/create_many_operation.cr b/src/create_many_operation.cr index 5e6707f..aa1ae08 100644 --- a/src/create_many_operation.cr +++ b/src/create_many_operation.cr @@ -66,7 +66,8 @@ module Interro if conflict_handler if (action = conflict_handler.action) && (handler_params = action.params) if handler_params.responds_to? :each_value - start = params.size + # The VALUES lists consume one placeholder per row per column. + start = params.size * params.first.size handler_params.each_value do |value| args << Interro::Any.new(value) end