Disable query cache for lock queries #6985

Merged
merged 1 commit into from Jul 6, 2012

Projects

None yet

10 participants

Contributor
sidonath commented Jul 6, 2012

Query caching should be disabled for queries asking for a pessimistic lock. Otherwise the lock query may not reach the database, thus breaking the expected functionality.

Fixes #867

@rafaelfranca rafaelfranca commented on the diff Jul 6, 2012
...ve_record/connection_adapters/abstract/query_cache.rb
@@ -83,6 +83,14 @@ def cache_sql(sql, binds)
result.collect { |row| row.dup }
end
end
+
+ def locked?(arel)
+ if arel.respond_to?(:locked)
rafaelfranca
rafaelfranca Jul 6, 2012 Owner

Are there some case where locked is not defined?

sidonath
sidonath Jul 6, 2012 Contributor

Yes, sometimes the arel is actually a String.

Without the check QueryCacheTest#test_cache_does_not_wrap_string_results_in_arrays was failing.

@rafaelfranca rafaelfranca merged commit 717aa92 into rails:master Jul 6, 2012
Contributor
jjb commented Jul 6, 2012

@rafaelfranca - should this also be ported to the rails 3 branch?

Owner

@jjb I can backport to 3-2-stable, but I want to confirm with @tenderlove first.

Owner

@jbb done at 7adc4f2

Contributor
jjb commented Jul 6, 2012

whoo hoo!

Contributor
nragaz commented Jul 27, 2012

Line 83 causes an NoMethodFound exception when there is a 'locked' scope defined on a model. The respond_to? call returns true but the method is not found.

Perhaps having a scope named 'locked' is a bad idea anyway, but that isn't documented as far as I know.

ihoka commented Aug 14, 2012

@nragaz Agreed on naming. Just got bitten by this when upgrading Rails. It has a weird interaction with Draper.

Member

@ihoka oh?

ihoka commented Aug 14, 2012

@steveklabnik yes. Draper uses method_missing and respond_to? to delegate to the model.

The issue I ran into was triggered by calling a method on the wrapped model within a decorator, which internally uses associations (has_one in my case). When doing so, it spits out an "undefined method `locked' for #Class:0x007f82fb067068", like this: https://gist.github.com/7498247d20ecd191d77e.

I spent a bunch of time chasing the cause, and finally ended up renaming my "locked" named scope to something else.

Member

Roger, okay. So not really something I could have fixed.

Contributor
nragaz commented Aug 14, 2012

@steveklabnik I think the point is that suddenly relying on the behaviour of a method named locked to all relations may not be so great, especially since there's no documented list of scope and class method names to avoid. It's going to cause a bunch of weird interactions, because if you redefine locked the query_cache logic is still going to call your redefined method -- and sometimes it'll even still seem to work, but mostly it won't.

Member

@nragaz in this case I'm speaking as the Draper maintainer, not as someone who works on Rails.

I agree that locked is a pretty common name to be adding to every relation.

Contributor
nragaz commented Aug 14, 2012

@steveklabnik Ah, cool. I didn't realize you were the Draper maintainer.

On 2012-08-14, at 1:13 PM, Steve Klabnik notifications@github.com wrote:

@nragaz in this case I'm speaking as the Draper maintainer, not as someone who works on Rails.

I agree that locked is a pretty common name to be adding to every relation.


Reply to this email directly or view it on GitHub.

I ran into this exact problem as well and have to rename many scopes. Would it be possible to add something similar to DangerousAttributeError for scopes?

Owner

One of the possibles solution is add a method locked? as alias to loked here and check arel.respond_to?(:locked?). But I need feedback from @tenderlove if this make sense.

giddie commented May 2, 2013

Would be nice to get this fixed, or at least find a way to provide a slightly less obscure error message. Just got bitten by this.

BM5k commented Aug 19, 2013

Wasted a bunch of time on this. A better error is definitely needed :(

@grosser grosser commented on the diff Oct 25, 2013
...ve_record/connection_adapters/abstract/query_cache.rb
@@ -83,6 +83,14 @@ def cache_sql(sql, binds)
result.collect { |row| row.dup }
end
end
+
+ def locked?(arel)
+ if arel.respond_to?(:locked)
+ arel.locked
grosser
grosser Oct 25, 2013 Contributor

FYI we have a scope called locked and this is blowing up ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment