aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Patterson <aaron.patterson@gmail.com>2011-09-07 15:06:42 -0700
committerAaron Patterson <aaron.patterson@gmail.com>2011-09-07 15:26:47 -0700
commit834d429e849b590ee7a283909eda9affed065387 (patch)
tree6093bf93f9093aed253439b2d6fc099d6ee9867d
parent8e79c5216038976f403be32de500fcb82e918512 (diff)
downloadrails-834d429e849b590ee7a283909eda9affed065387.tar.gz
rails-834d429e849b590ee7a283909eda9affed065387.tar.bz2
rails-834d429e849b590ee7a283909eda9affed065387.zip
LRU should cache per process in postgresql. fixes #1339
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb24
-rw-r--r--activerecord/test/cases/adapters/postgresql/statement_cache_test.rb23
2 files changed, 37 insertions, 10 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index 272663a91d..5402918b1d 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -251,34 +251,38 @@ module ActiveRecord
def initialize(connection, max)
super
@counter = 0
- @cache = {}
+ @cache = Hash.new { |h,pid| h[pid] = {} }
end
- def each(&block); @cache.each(&block); end
- def key?(key); @cache.key?(key); end
- def [](key); @cache[key]; end
- def length; @cache.length; end
+ def each(&block); cache.each(&block); end
+ def key?(key); cache.key?(key); end
+ def [](key); cache[key]; end
+ def length; cache.length; end
def next_key
"a#{@counter + 1}"
end
def []=(sql, key)
- while @max <= @cache.size
- dealloc(@cache.shift.last)
+ while @max <= cache.size
+ dealloc(cache.shift.last)
end
@counter += 1
- @cache[sql] = key
+ cache[sql] = key
end
def clear
- @cache.each_value do |stmt_key|
+ cache.each_value do |stmt_key|
dealloc stmt_key
end
- @cache.clear
+ cache.clear
end
private
+ def cache
+ @cache[$$]
+ end
+
def dealloc(key)
@connection.query "DEALLOCATE #{key}"
end
diff --git a/activerecord/test/cases/adapters/postgresql/statement_cache_test.rb b/activerecord/test/cases/adapters/postgresql/statement_cache_test.rb
new file mode 100644
index 0000000000..a82c6f67d6
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/statement_cache_test.rb
@@ -0,0 +1,23 @@
+require 'cases/helper'
+
+module ActiveRecord::ConnectionAdapters
+ class PostgreSQLAdapter < AbstractAdapter
+ class StatementPoolTest < ActiveRecord::TestCase
+ def test_cache_is_per_pid
+ return skip('must support fork') unless Process.respond_to?(:fork)
+
+ cache = StatementPool.new nil, 10
+ cache['foo'] = 'bar'
+ assert_equal 'bar', cache['foo']
+
+ pid = fork {
+ lookup = cache['foo'];
+ exit!(!lookup)
+ }
+
+ Process.waitpid pid
+ assert $?.success?, 'process should exit successfully'
+ end
+ end
+ end
+end