Apparently, I can't edit previous messages. Here is the reworked version 
that allows you to reference the same column in the lookup as in the update.

https://gist.github.com/Aryk/ea6d9bce063a502323e3f42910925159


On Sunday, August 13, 2023 at 9:58:24 AM UTC-7 aryk....@gmail.com wrote:

> Thanks Jeremy. I continued to be impressed with the Sequel library! 
>
> For anyone else who wants it... not sure if this has a place in the 
> library but it is much more straight-forward and faster than iterating 
> through records on migrations or using complicated insert_conflict logic.
>
> Here is what I have so far... please test yourself as it's not battle 
> tested! 
>
> # Use like this: User.batch_update([[{id: 4}, {full_name: "New Full 
> Name"}]]) 
>   def self.batch_update(data_lookup, return_sql: false)
>     if data_lookup.present?
>       lookup_columns, update_columns = data_lookup.first.map(&:keys)
>       from, to = Sequel[:data], Sequel[table_name]
>       conditions = lookup_columns.each.with_object({}) { |col, h| 
> h[to[col]] = from[col] }
>       updates    = update_columns.each.with_object({}) { |col, h| h[col] = 
> from[col] }
>       values = data_lookup.map { |l, u| l.values + u.values }
>
>       ds = db.
>         from(
>           to.value.to_sym,
>           db.values(values).as(from.value.to_sym, [*lookup_columns, 
> *update_columns])
>         ).
>         where(conditions)
>
>       ds.send(return_sql ? :update_sql : :update, updates)
>     end
>   end
>
> On Wednesday, August 9, 2023 at 4:24:47 PM UTC-7 Jeremy Evans wrote:
>
>> On Wed, Aug 9, 2023 at 11:35 AM aryk....@gmail.com <aryk....@gmail.com> 
>> wrote:
>>
>>> Hi Jeremy,
>>>
>>> I saw some historical posts about batch updates like this one:
>>>
>>> https://groups.google.com/g/sequel-talk/c/uV7PRbEvQj0/m/lCvZaLx8AAAJ
>>>
>>> It feels a little "hacky" to say insert this record with a unique 
>>> primary key that already exists...when you get an error, then update it. 
>>>
>>> I've been using a solution like this:
>>>
>>>     run <<-SQL
>>>           update user_expo_push_tokens as uept set -- postgres FTW
>>>             device_id = ud2.device_id
>>>           from (values
>>>             #{updates.join(", ")}
>>>           ) as ud2(installation_id, device_id)
>>>           where ud2.installation_id = uept.installation_id;
>>>     SQL
>>>
>>> This also works in the case where the values are not a primary key or 
>>> have a unique index to throw the "on duplicate key update" logic. 
>>>
>>> Is there a way to accomplish this without having to drop to straight sql?
>>>
>>
>> I think this will work:
>>
>> DB.from(Sequel.as(:user_expo_push_tokens, :uept), 
>> DB.values(updates).as(:ud2, [:installation_id, :device_id])).
>>   where{{ud2[:installation_id]=>uept[:installation_id]}}.
>>   update(:device_id => Sequel[:ud2][:device_id])
>>
>> SQL:
>>
>> UPDATE "user_expo_push_tokens" AS "uept"
>> SET "device_id" = "ud2"."device_id"
>> FROM (VALUES ...) AS "ud2"("installation_id", "device_id")
>> WHERE ("ud2"."installation_id" = "uept"."installation_id")
>>
>> It depends on what "updates" is supposed to be.
>>
>> Thanks,
>> Jeremy
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sequel-talk+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/sequel-talk/7392c230-f7eb-4ce8-80ed-41c6944695dbn%40googlegroups.com.

Reply via email to