Problem when using optimistic locking

58 views
Skip to first unread message

springbok

unread,
Nov 9, 2012, 1:13:41 AM11/9/12
to Composite Keys for ActiveRecord
Hi,

I'm using optimistic locking i.e. I have a lock_version column in my
table, when I try and update a record with a composite key the where
clause is not constructed correctly. After digging through the AR code
I have found the problem in the optimistic.rb file:


def update(attribute_names = @attributes.keys) #:nodoc:
return super unless locking_enabled?
return 0 if attribute_names.empty?

lock_col = self.class.locking_column
previous_lock_value = send(lock_col).to_i
increment_lock

attribute_names += [lock_col]
attribute_names.uniq!

begin
relation = self.class.unscoped

stmt = relation.where(
relation.table[self.class.primary_key].eq(id).and(

relation.table[lock_col].eq(quote_value(previous_lock_value))
)
).arel.compile_update(arel_attributes_values(false, false,
attribute_names))

affected_rows = connection.update stmt

unless affected_rows == 1
raise ActiveRecord::StaleObjectError.new(self, "update")
end

affected_rows

# If something went wrong, revert the version.
rescue Exception
send(lock_col + '=', previous_lock_value)
raise
end
end

At the start of the method it has this line:

def update(attribute_names = @attributes.keys) #:nodoc:
return super unless locking_enabled?

It will only call super and therefore the composite primary key update
method if no locking is in force, if I'm using locking it will
continue with the current method and construct the Arel relation
without correctly handling the composite keys.

For now I've removed the lock_version column from my table to get the
update to work correctly. I'm not sure of the inner workings of the
gem so any pointers on how to fix this issue would be appreciated. I'm
happy to change code if someone can point me in the right direction. I
would think that we would have to override this method and hook in
the composite key code.

Thanks.

cfis

unread,
Nov 22, 2012, 1:20:16 AM11/22/12
to compos...@googlegroups.com
Hi springbok,

            stmt = relation.where(
              relation.table[self.class.primary_key].eq(id).and(
 
relation.table[lock_col].eq(quote_value(previous_lock_value))
              )
            ).arel.compile_update(arel_attributes_values(false, false,
attribute_names))


It will only call super and therefore the composite primary key update
method if no locking is in force, if I'm using locking it will
continue with the current method and construct the Arel relation
without correctly handling the composite keys.

Right ok.  And the arel method has issues with the way it constructs the where clause for finding records via the primary keys.
 


happy to change code if someone can point me in the right direction. I
would think that we would  have to override this method and hook in
the composite key code.

Right - usually you have to fix the eq clauses for the primary keys.  Most of CPK changes do exactly that if you want to see some examples.

Charlie

Reply all
Reply to author
Forward
0 new messages