From 834d429e849b590ee7a283909eda9affed065387 Mon Sep 17 00:00:00 2001
From: Aaron Patterson <aaron.patterson@gmail.com>
Date: Wed, 7 Sep 2011 15:06:42 -0700
Subject: LRU should cache per process in postgresql. fixes #1339

---
 .../connection_adapters/postgresql_adapter.rb      | 24 +++++++++++++---------
 .../adapters/postgresql/statement_cache_test.rb    | 23 +++++++++++++++++++++
 2 files changed, 37 insertions(+), 10 deletions(-)
 create mode 100644 activerecord/test/cases/adapters/postgresql/statement_cache_test.rb

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
-- 
cgit v1.2.3