Update_all Not Incrementing lock_version

Shouldn’t update_all be updating lock_version? As you can see from my
console session below, it is upating the record (changed running
attribute to true and returned 1 to show 1 recored was updated). But it
did not increment lock_version. And optimistic locking is working
correctly otherwise. As you can see below, lock version = 562 before
and after the update_all call but it is incremented to 563 when I save()
the object.

Am I missing something here?

Thanks, Don

jobs = Job.find(:all, :conditions => [‘id = 10’])
=> [#<Job:0xb73f9ea4 @attributes={“status”=>“1”, “server_id”=>nil,
“running”=>“0”, “poller_id”=>“10”, “lock_version”=>“562”,
“response_time”=>“8”, “id”=>“10”, “next_run_at”=>“2006-07-06 13:43:33”,
“last_run_at”=>“2006-07-06 13:42:33”, “late”=>“0.532686”}>]

puts jobs[0].running, jobs[0].lock_version
false
562
=> nil

Job.update_all([‘running = ?’, true], [‘id in (?)’, jobs.map { |j| j.id}])
=> 1

jobs = Job.find(:all, :conditions => [‘id = 10’])
=> [#<Job:0xb73e835c @attributes={“status”=>“1”, “server_id”=>nil,
“running”=>“1”, “poller_id”=>“10”, “lock_version”=>“562”,
“response_time”=>“8”, “id”=>“10”, “next_run_at”=>“2006-07-06 13:43:33”,
“last_run_at”=>“2006-07-06 13:42:33”, “late”=>“0.532686”}>]

puts jobs[0].running, jobs[0].lock_version
true
562
=> nil

j = Job.find(10)
=> #<Job:0xb73e2cb8 @attributes={“status”=>“1”, “server_id”=>nil,
“running”=>“1”, “poller_id”=>“10”, “lock_version”=>“562”,
“response_time”=>“8”, “id”=>“10”, “next_run_at”=>“2006-07-06 13:43:33”,
“last_run_at”=>“2006-07-06 13:42:33”, “late”=>“0.532686”}>

j.running = false
=> false

j.save
=> true

j
=> #<Job:0xb73e2cb8 @attributes={“status”=>“1”, “server_id”=>nil,
“running”=>false, “poller_id”=>“10”, “lock_version”=>563,
“response_time”=>“8”, “id”=>“10”, “next_run_at”=>“2006-07-06 13:43:33”,
“last_run_at”=>“2006-07-06 13:42:33”, “late”=>“0.532686”},
@errors=#<ActiveRecord::Errors:0xb73dfe8c @base=#<Job:0xb73e2cb8 …>,
@errors={}>>

j.reload
=> #<Job:0xb73e2cb8 @server=nil, @attributes={“status”=>“1”,
“server_id”=>nil, “running”=>“0”, “poller_id”=>“10”,
“lock_version”=>“563”, “response_time”=>“8”, “id”=>“10”,
“next_run_at”=>“2006-07-06 13:43:33”, “last_run_at”=>“2006-07-06
13:42:33”, “late”=>“0.532686”}, @poller=nil,
@errors=#<ActiveRecord::Errors:0xb73dfe8c @base=#<Job:0xb73e2cb8 …>,
@errors={}>>

Don S. wrote:

Comments anyone? Unless I’m making a newbie mistake this is a
significant bug.

  • Don

Don S. wrote:

OK. I’m NOT an SQL expert, but I think I know why this is the case. It
is because of the way update_all queries are structured.

For example:

UPDATE jobs SET jobs.running = 1 WHERE (id in (10,11,12))

There is no reference to the lock_version column. Please know that I’m
a total SQL hack. But why couldn’t we do this instead?

Assuming:

±—±-------------+
| id | lock_version |
±—±-------------+
| 10 | 1340 |
| 11 | 1333 |
| 12 | 807 |
±—±-------------+

UPDATE jobs
SET jobs.running = 1
WHERE (id in (10,11,12)
AND lock_version in (1340, 1333, 807));

This seems to do the trick. Don’t even ask me how optimistic locking
exception handling would work for this kind of update. I’ll leave that
to the professionals. :wink:

Thoughts?

  • Don

BTW : At the very least, we need the update_all documentation to reflect
the fact it’s not honoring optimistic locking. And if it’s too tricky
to add support for it then I might have to look into another approach.
Maybe a stored proc.